Yet another tech geek weblog with a focus on technical Linux and open source, particularly server-side PostgreSQL and Kubernetes
Tuesday, July 17, 2012
Tips for interactively debugging CDI applications
Of course, this is my blog, so you know there's a "but". Sure enough there is, albeit a pretty minor one: It's a mess for interactive debugging, because stepping through a CDI invocation takes you through layers of weld proxies, scope lookups, and all sorts of other crud you usually don't want to see. LOTS of it. CDI isn't unique in this respect, as anyone who's stepped through EJB calls will know, but it's perhaps worse than some due to extensive use of proxies, interceptors, etc.
There's a solution in Eclipse. It could be simpler and it could be more complete, but it's a heck of a lot better than nothing.
Java EE 7 needs improvements in app configuration mechanisms
This is not a new issue, as can be seen with this 2001 question on The Server Side. Back then they suggested *using JMX* ... which doesn't exactly fit the *simple* requirement.
Java EE is supposed to provide much of the groundwork for apps as part of the container, so the app author can get on with solving their problem. Right now it doesn't help much with application settings, and this needs improvement so that apps:
- Don't need to each provide a custom UI in order to edit even the simplest settings
- Can easily modify their own settings
- Can guarantee the persistence of their settings across redeploys and across cluster nodes
- Don't require a full database and data access layer / JPA / etc just to store simple configuration options.
UPDATE: Marcus Eisele pointed out a related post by Antonio Goncalves as part of a jsr342-experts post on configuration. Have a look at Antonio's piece; he's looking at it from a slightly different angle, but with many of the same issues.
See also this stack overflow post from a while back, where I asked for help on this topic and got crickets.
Vaadin is pleasantly productive
I strongly recommend Vaadin 6 for anyone doing web applications - highly stateful tools where user counts are relatively low and UI complexity is relatively high.
The only real caveats I have to that recommendation are that:
- JPAContainer is very inefficient - largely due to an API design problem in Vaadin's Container API that makes it very hard to use the entity manager efficiently. Alas, this design flaw hasn't been remedied for Vaadin 7, so it's sometimes best to avoid JPAContainer and drive a Vaadin table from the outside instead.
- JPAContainer doesn't play well with Hibernate and lazily loaded entities. A workaround is provided, but it's clearly more used with EclipseLink. This won't be a problem if you drive your tables with your own data model code.
- Vaadin's stateful design means that each client costs you a non-trivial amount of memory on the server. If you want to serve large numbers of users who're doing simpler things you might want to consider a stateless JAX-RS API driven by client-side JavaScript and a lightweight templating engine, or look into one of the stateless server-side frameworks.
Vaadin 6 feels a little bit old at times, and you can certainly see its Java 1.4 history in more frequent use of casts rather than generics. It also requires an extension to integrate it with CDI - even then, only with pseudo-scopes.
Vaadin isn't beautiful, but damn, it works. Works well, and reliably. It's been at least two weeks since I found a bug in the tools I've been using, and that has never happened to me since I started using the Java EE stack!
Despite its flaws, JPAContainer is also impressively powerful. I really hope an enhanced Container API can be introduced to Vaadin 7 so it can reach its potential as a truly awesome RAD tool.
Thursday, June 21, 2012
NullPointerException on @Inject site even with beans.xml?
Have you checked to make sure beans.xml is in the right place:
- .jar and .rar:
/META-INF/beans.xml - .war:
/WEB-INF/beans.xml - .ear: an EAR can't be a bean archive
Still not working? Does a message about activating CDI appear in the server log, but injection still not work?
Make sure you used the right @Inject annotation. Especially with code completion and dependencies pulling Google's Guice onto the classpath it's easy to land up accidentally choosing
com.google.inject.Inject instead of javax.inject.Inject.Yep, I just wasted twenty minutes staring at code that wasn't working before I noticed this. Time to find out which dependency is pulling in Guice, add an exclusion, and nag them to make it an
<optional>true</optional> dependency. It looks like in my case it's coming from org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-impl-maven, so a quick:<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
</exclusion>
ensured that mistake wouldn't happen again.
JPA 2.1 will support CDI Injection in EntityListener - in Java EE 7
Added support for use of CDI injection in entity listeners. Added requirement for Java EE container to pass reference to BeanManager on createContainerEntityManagerFactory call.
This is good news. The spec needs more eyes. If you use JPA, you need to have a look. Check to see if any pain points you encounter in JPA 2 are addressed. Check the revision notes at the end and see if something jumps out at you as being problematic or unsafe. If you have concerns contact the EG. More eyes on draft standards means fewer problems in released standards. EclipseLink has already implemented JPA 2.1 Arithmetic expressions with Sub-Queries, option support for select and from clause subqueries and JPA 2.1 JPQL Generic Function support so go try them out in EclipseLink 2.4.0 pre-releases using the latest milestone.
It might be worth trying out the new goodies too. Sometimes a feature seems reasonable on paper, but works very poorly in practice. The spec-before-implementation development model of Java EE means we get to "enjoy" lots of those issues; help prevent more by testing the implementation early.
I didn't see anything about fetch strategies and modes, so I'm going to have to go nag them again. I had success the first time around in pushing for CDI injection into EntityListener, but the spec is significantly further along now. OTOH, the difficulty of controlling eager vs lazy properties on a per-query basis is a big pain point.
UPDATE: done, let's see what happens.
(BTW, it seems a shame that JPA 2.1 is being tied to EE 7, as that's still a long way off.)
Thursday, April 19, 2012
Arquillian initially overpromises and frustrates, but delivers real benefits
Arquillian is changing fairly rapidly, and the Arquillian folks are paying a lot of attention to feedback. This post discusses Arquillian 1.0.0.Final, and more importantly the ShinkWrap Resolver and ShrinkWrap Dependency extensions. A lot has already improved since I wrote this, though most of it hasn't hit -Final versions yet.
After seeing a lot of talk, hype and excitement about Arquillian on twitter for several months, I finally got around to introducing it into a new project to give it a try. I'm told it'll make testing massively easier and save me tons of time, so using it is a no-brainer.
Tweet to @craigdevel After my recent experience I recommend that you start using it too - but you'll need to be prepared for some rough edges and the need for workarounds until a few point releases have gone by.
To jump straight to the summary of it all, click here, or read on for the whole experience.
Thursday, July 14, 2011
Java EE 6 - Traps, pitfalls and warts list
Java EE 6 has the potential to be a great platform. It just needs plenty of cleanup, implementation bug fixing, and real-world use to get there.
One of the bigger issues is the significant array of spec inconsistencies and oversights that leave parts of the system working (or not working) in ways very different to one might expect. These issues can greatly increase debugging time and take important time away from productive development and into chasing issues in appservers, frameworks, and the specifications themselves.
I thought I'd make a list of some of the ones I've hit so far. I'm really hoping we'll see a Java EE 6.1 - a fixes-only revision that, unlike EE 7, focuses on polish and usability over adding new features. These are things I think are important to see covered by it.
The shortlist, explained in detail below:
@Inject into a @FacesConverter. Use Seam 3 Faces to work around this. UPDATE: This should be fixed in JSF 2.1.@Inject into a JPA 2.0 EntityListener or an entity. Do a direct BeanManager lookup from JNDI or use Seam 3 Solder's BeanManagerAware to kind of hack around this; it's ugly. Lack of JPA 2.0 lifecycle hooks for EntityListener classes means Seam 3 Persistence can't fix this one. UPDATE Jan 2012: It appears that into EntityListener will be supported in JPA 2.1, but not injection into entities.javax.annotation.ManagedBean. It was obsolete before release, is only inconsistently recognised, duplicates JSF2 functionality that's also obsoleted by CDI's @Named, and should simply be removed.resource-ref resource names in web.xml to a global resource name defined in glasfish-web.xml or jboss-web.xml doesn't work for persistence.xml jta datasource references and isn't supposed to work. Ignore all the examples and official documentation that suggest it should, they work with direct JDBC and with Spring but not with JPA 2.0.beans.xml. Your container will not warn you about this at deployment or runtime even if CDI annotations are present on classes.Many of these workarounds require the use of Seam 3 (ie: "let's finish the work EE 6 started") modules. Because of Glassfish bugs, some additional work is required to use Seam 3 on Glassfish versions prior to the yet-to-be-released 3.2. See this previous post for some information.
In addition to the genuine issues with EE 6, there's also the learning curve to contend with. A while ago I wrote a broad conceptual overview of EE 6 intended for those coming to it cold, rather than migrating from EE 5 or from Seam. I felt it was necessary because of the struggle I had getting started with EE 6 and the bugs that bit me and confused me during the learning process. Perhaps it'll benefit others here or even provide insight into areas of the documentation and tutorial that would benefit from improvement.
Now, for the details:
Wednesday, July 13, 2011
Someone else in Java EE 6 pain
I'm not alone!
Harald Wellmann writes about his experience moving a Tomcat-based app to Glassfish, JBoss AS 6, and Resin. Warts and all.
I think Java EE 6 really needs more real-world attitude and less hype. More bug fixing and more spec tidying, less focus on the next whizz-bang feature. It's nice to see somebody else who's had similarly painful experiences with it. Perhaps I'm not stupid after all, I simply make the foolish mistake of expecting released software like Glassfish 3.0.1 to have most features fairly solid.
Harald also notes that CDI was a huge problem with Java EE 6 until quite recently, largely because Glassfish 3.0 was half-baked and under-tested; JPA 2.0 is prone to exciting implementation differences and bugs, and more.
My favourite quote:
Legacy
Backward compatibility is a good thing for veteran users of a framework. Users don't want to change all of their application code just for upgrading to a new framework version.
On the other hand, backward compatibility can be extremely confusing to new users: There's two or three solutions for the same kind of problem, the legacy one is not marked as legacy or deprecated clearly enough, tutorials and example code still use the old style, and you can only resort to your favourite search engine or to trial and error to make things work consistently.
(Emphasis mine)
That's a perfect description of some of the problems I encountered when trying to get a handle on the released standard Java EE 6 and Glassfish 3.0, which I foolishly assumed was a stable platform to build my app on as I moved into the Java EE world
Java EE 7 really needs to modularize the backward compatibility crap into separate archives so that apps can depend on either javaee-7 or javaee-7-legacy as appropriate. That way we'll finally be free of the two copies of the obsolete-before-release @ManagedBean annotation and all the other horrible legacy crap.
Friday, February 4, 2011
How to get the context path (context root) in jsf2
Use:
#{facesContext.externalContext.request.contextPath}
For some insane reason, none of the methods that should work would work when invoked via a @RequestScoped object with @Inject @FacesContext - they all merrily returned the empty string. More stupid CDI/JSF brokenness.
Sunday, August 22, 2010
Java EE 6 doesn't "just work" in even trivial real-world uses
Lincoln Baxter III writes that with Java EE 6, It all “Just works”.
Personally, I have not found that to be the case in even simple, toy applications.
I suspect it'll be true in a few years, probably after a much needed "Java EE 6.2" and some major bug-fixing. Right now it all "just works" ... except when it doesn't, which is frequently, due to spec oversights, bugs, and a general lack of real-world use and testing.
Wednesday, August 18, 2010
Simple Java EE 6 project fails in different ways on Glassfish and JBoss AS 6
I'm coming to really like Java EE 6 ... or at least, I would if anything worked properly. There seem to be an awful lot of quirks and bugs in even fairly basic functionality, though.
Take this simple project, where a @Stateless EJB that inherits from an abstract base is injected into a regular JSF2 backing bean. It's done two different ways - once using the new CDI/Weld injection facilities, and once with old-style JSF2 injection and EJB container management.
One works on glassfish, the other on JBoss. Neither works on both.
The glassfish failure is caused by a problem resolving methods inherited from superclasses in the Weld-generated local no-interface EJB proxies. The JBoss issue appears to be caused by issues with its local no-interface EJB support, too, though I'm not sure exactly what yet.
The point: Local no-interface EJBs were supposed to save time and pain for developers, yet all I'm finding so far is bugs, or at least quirks and inconsistent behaviour.
Sources to the sample can be found here and a deployable war is here.
Posted on StackOverflow and The Glassfish forums
.Monday, August 9, 2010
I'm not smart enough to use Java EE
I don't seem to be smart enough to use Java EE.
Reading the Java EE tutorial certainly helps. It's very good at explaining a lot of the how, though not as much of the why; there isn't a strong overview of what EE is and how it fits together, but there's plenty on how the parts work and how to use them. Before sitting down for some quality reading time, I was totally lost. This is not something you can dive head-first into. After reading the tutorial I'm only very confused. [Edit 2012: The tutorial seems to have more overview info now, or I understood it better this time around. It's still hard to see what uses what, builds on what, and relates to what from the tutorial though.]
UPDATE 2011: I seem to be managing despite the learning curve and the quality challenges, and am trying to help others avoid the same suffering I went through by providing some overview level documentation on how it all fits together and what all the damn acronyms mean.
UPDATE mid-2012: It's two years since I wrote this, and sometimes I still struggle with the complexity of the Java EE stack. JSF2 in particular feels significantly over-engineered and doesn't have documentation to match its complexity; it feels as complicated as the rest of Java EE put together without close to as much useful documentation (and lots more bugs).
The remainder was written in August 2010, not long after I moved from Swing development over to Java EE 6 - unbeknownst to me, just as Java EE 6 implementations were in their infancy and not in any sense stable or production ready.
Problem 1: Acronym soup
Seam. Struts. Tapestry. Weave. Weld. JSF. JSF2. JPA. JPA2. EJB2. EJB3. CDI. Hibernate, EclipseLink, etc. J2EE. JARs in OSGi bundles in WARs in EARs. Glassfish. JBoss. Tomcat. Jetty. @Inject. @EJB. @Resource. @PersistenceContext. @javax.annotation.ManagedBean. @javax.faces.bean.ManagedBean. @Named. @Stateless. @Stateful. Spring. Servlet filters. @javax.faces.bean.RequestScoped, javax.enterprise.context.RequestScoped, @javax.faces.bean.SessionScoped, javax.enterprise.context.SessionsCoped, @javax.faces.bean.ApplicationScoped, javax.enterprise.context.ApplicationScoped, javax.enterprise.context.ConversationScoped, @javax.faces.bean.ViewScoped. @Singleton. DAOs and data access layers. JTA. JNDI. JMS. RMI. Deployment descriptors (web.xml, etc). Vendor deployment descriptors (sun-web.xml, sun-resources.xml, etc). Various config files, some of which have an effect even when empty (faces-config.xml, beans.xml). Maven plugins, oh god the maven plugins. RichFaces, MyFaces, IceFaces, PrimeFaces, SeamFaces.
Java EE makes me understand how "non computer people" feel when listening to programmers talk.
Problem 2: Bad or incomplete documentation, narrow-view docs without an overview
For a newbie, it's extremely hard to understand the layering, and made even more confusing by the mixing of specs (eg JAX-RS, JSF2) with implementations (eg Jackson or RestEASY, Mojarra or MyFaces). Each project's documentation talks largely about its self in isolation.
Most of the documentation, even the Java EE 6 tutorial, focuses on narrow parts of the spec without ever trying to help you understand how it all fits together. Some overview documentation that focuses on the basic concepts is sorely needed.
It doesn't help that the JSF2 spec is [wording edited] a very dense document that specifies but does not document or explain JSF2. The assumption seems to be that you'll get a book for JSF2[/end edit]. [Added 2012:] Many recommend Core JavaServerFaces over JavaServer Faces 2.0, The Complete Reference; I certainly found the former helpful.[/end added]
Problem 3: Legacy, duplication, and specs created in isolation
Part of the problem is that there are several generation of "technology" that are mashed together in an overlapping mess. For example, J2EE6 uses CDI with Weld, but everyone already does this with Spring, which also does all sorts of other things so you might want to still use it even though you're doing DI with Weld in a J2EE container. Your objects might be being managed by some combination of JSF2 @ManagedBean lifecycle management, @EJB lifecycle management, Weld, or (if you're using it) Spring.
Or does JSF2 actually use CDI to manage its beans via Weld? Who knows! (Update: the answer is "Maybe", btw. If you're using CDI, JSF2 beans are managed with CDI as implemented by Weld. Otherwise they're managed by JSF2 its self.) Every framework uses every other framework or has semi-transparent integration hooks for them - hooks that mostly work, but with some subtle bugs or limitations. Every framework claims to make everything simple, while adding yet another layer of nightmarish complexity. Specifications inevitably have a reference implementation from Sun/Oracle/JBoss, and an Apache implementation, so you have to figure out what the relationship between the implementation names and the spec name is for each, what they actually do, which implementation you might want to choose and why, etc.
When trying to learn about this stuff, it's hard to find materials that don't already assume you know the older technologies and just want to update to the newer ones. Hell, it's hard to figure out what the older ones and newer ones even are, or why you should want to use one over the other.
The J2EE platform releases are supposed to help with that, but seem to add complexity more than remove it, due to the need for backward compat, support for older frameworks and code that uses them, the messy overlap between different specs, the way different specs each added feature like injection in different and incompatible ways, etc.
Problem 4: Too much magic, not enough visibility when (not if) the magic breaks
There's so much transparent management of application state, object lifetimes, request handling, etc that it becomes quite hard to figure out what your app is actually doing, how and when to do something, or how to alter some part of the automatic behaviour when you need to. As for debugging... good luck following your app though a JSF2 request lifecycle.
Heaven save you if you forget to put an empty beans.xml magic marker file in a project. It'll be NullPointerException soup with absolutely NO indication that CDI is turned off. Obvious and simple with experience, hell when I first got started.
Struggling? You're not alone
On the other hand, it makes me feel better when really, really smart people point out that all this architecture makes it hard to see what you're actually trying to do.
... and all this means that paradoxically, even as we have higher and higher level programming tools with better and better abstractions, becoming a proficient programmer is getting harder and harder.
.... and really, reading the manual makes it a little more approachable. Entirely avoiding JSF2 in favour of something sane like Vaadin or even Play if you're so inclined will help even more.