2009-12-24

Spring to Java EE 6 porting gotchas

JSF/Facelets:
  • Don't use JSTL tags with Facelets. Just don't do it. Substitute <ui:repeat> for <c:foreach>, and <f:subview rendered="#{expression}"> for <c:if>.
  • If you're wondering why your JavaScript can't access the document variable on the Google Chrome browser in a Facelets application, it's because the default Facelets content-type is application/xml+xhtml which doesn't sit well with some browsers. <f:view contenttype="text/html> will help.
JPA/EclipseLink:
  • GlassFish has a directory called domains/domain1/lib/databases, but won't find your JDBC driver from there. Put the JAR in domains/domain1/lib.
  • Getting EclipseLink to do JOINs instead of N+1 or even 2N+1 queries is sometimes challenging. query.setHint(QueryHints.BATCH, "user.emails") to the rescue.
  • Using Postgresql sequences with default settings all around will lead to problems when trying to insert several new entities in a session, because by default JPA will assume that once it has acquired an identity number from the sequence, it can freely use 50 numbers up from there before having to re-acquire a new identity number from the sequence.
    The workaround is to configure either your JPA @SequenceGenerator to have the parameter @SequenceGenerator(allocationSize=1) or to modify your database sequence to have a step of 50 instead of 1. I'm going with the JPA configuration, although if I'd be inserting large batches regularly, I'd rather reconfigure the database sequences to avoid the roundtrip.
    Or just use IDENTITY instead of SEQUENCE, if you're also using the SERIAL datatype.
JAX-RS/Jersey:
  • If you've mapped your Jersey servlet to, say, "/jersey/*" in web.xml, your class-level resource path is @Path("jersey") and your method-level resource path is @Path("users/{id}"), you need to do the HTTP request to http://server/jersey/jersey/users/123, because the servlet starts interpreting paths from its own root, and not from the context root.

3 comments:

  1. Hi Mikael,

    interesting post. But: why you would like to port your Spring application to Java EE 6?

    thanks!,

    adam
    ReplyDelete
  2. It was one of those cases where one thing led to another. It's a small app, and I'm the customer.

    When I first had the need for the application, I wanted to try out whether Google App Engine is really a practical application platform, so I wrote the app for GAE.

    When I figured out that no, it was then impossible for me to predict the application performance, given datasets larger than 1000 items, I ported it to Spring as a vanilla Spring/JDBC/JSP application. When I was almost done, I got frustrated with the amount of ORM code I was having to write, I thought it would be less work to just use JPA.

    After having decided to use JPA, a friend of mine was wondering whether one could use Java EE 6 to get the same benefits one gets from Spring, I thought, what the heck, while I'm making insensible project management choices, I can just as well port the whole application over to Java EE 6. And here we are.
    ReplyDelete