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: