users@glassfish.java.net

Re: Question on included JEE versions and packaging apps with Maven

From: Craig Ringer <craig_at_postnewspapers.com.au>
Date: Mon, 23 Aug 2010 23:41:07 +0800

First: I'm a Java EE 6 newbie myself. The opinions expressed below are
from my own limited experience, though I've been doing a **lot** of
research and reading lately. In other words: This is based on my recent
Java EE 6 experience, and longer experience with Maven/java in general,
but shouldn't be taken without some caution.

Corrections, flames, etc appreciated.

On 23/08/2010 10:55 PM, glassfish_at_javadesktop.org wrote:
> I saw that Glassfish already ships a number of JEE jars such as
> javax.persistence or eclipselink. I tried to discover their versions
> from the jar itself but none of the attributes looked like a 2.0 or
> similar version number. My first question is therefore, where can I
> find out about the versions of the included jars?

Glassfish 3 is a Java EE 6 server. It promises to include support for
the various sub-specs in Java EE 6, rather than exact versions of
particular implementations of those specs. You're not generally meant to
care what version of a library Glassfish uses to implement the spec, or
even which implementation of a spec Glassfish has included. In reality,
sometimes you have to, but I'd deal with those issues as you encounter them.

It's helpful to review the list of "technologies" (generally really JSR
specs) included in Java EE 6.

http://www.oracle.com/technetwork/java/javaee/tech/index.html

(blech, that "oracle" still seems wrong)


All you should *really* have to do is declare a provided scope
dependency on the Java EE 6 APIs:

         <dependency>
             <groupId>javax</groupId>
             <artifactId>javaee-web-api</artifactId>
             <version>6.0</version>
             <scope>provided</scope>
         </dependency>

... which includes javax.persistence, etc, so you can use all the Java
EE 6 APIs in your code. You shouldn't need to depend on particular
versions of particular implementations of those APIs at all, unless you
intend to use interfaces outside the Java EE 6 API spec (like
EclipseLink-specific extensions, for example).



As it sounds like you're working on learning Java EE, and I very
recently found it pretty hard to get a handle on myself, I thought I'd
include a few suggestions on that too. I strongly recommend starting here:

http://www.oracle.com/technetwork/java/javaee/documentation/tutorials-137605.html

particularly:

http://download.oracle.com/javaee/6/tutorial/doc/

as the Java EE tutorial is good quality, pretty well written, and well
help you fit all the pieces together at least a little bit.

Then, as becomes necessary, grab the documentation for the specific
"technologies" used in the Java EE 6 and read them. Avoid the JSF2 spec
at all costs, though, it's awful; there's some good (if repetitive)
introductory material for JSF2 at:

   http://www.coreservlets.com/JSF-Tutorial/jsf2/

> When it comes to compiling my JEE app with Maven, I'm wondering,
> which version I need to specify for javax.persistence, eclipselink,
> etc.

Just depend on the Java EE spec.

If you don't want to depend on the full Java EE spec, you can declare a
<scope>provided</scope> dependeny on the JPA2 API as shipped by your
persistence provider. For EclipseLink that appears to be:

<dependency>
   <groupId>org.eclipse.persistence</groupId>
   <artifactId>javax.persistence</artifactId>
   <version>2.0.0</version>
   <scope>provided</scope>
</dependency>

... but as I'm using Hibernate I haven't verified that.

You can also declare a runtime dependency on the implementation, like:

<dependency>
   <groupId>org.eclipse.persistence</groupId>
   <artifactId>eclipselink</artifactId>
   <version>2.1.0</version>
   <scope>runtime</scope>
</dependency>

... though I prefer to avoid <scope>compile</scope> unless I intend to
use interfaces that are specific to that persistence provider in my code.

If you use <scope>runtime</scope> the exclipselink jars will be bundled
in your war but your code can't refer to them directly. Personally I
prefer to avoid declaring the dependency at all, just using an
appropriate persistence.xml to specify a persistence provider and using
the JPA2 API only in my code.

> I have a feeling that I should compile the app against exactly the
> same version of jars as dependencies that are included in Glassfish.

It'll run with whatever's included in Glassfish (if you don't bundle
your own versions) so that's a good idea, but shouldn't really matter so
long as the APIs are the same.

I prefer to avoid bundling jars for things that Glassfish ships in my
app as well, instead using <scope>provided</scope> dependencies on the
versions in Glassfish if I have to refer to them at all outside the Java
EE API dependency. That way there's no possible confusion about which
classes will be used at runtime, the copies in glassfish or in my .war,
because there *are* no copies in my .war .

It makes deployment nice and fast, too.

> Can someone confirm or dispute that theory (rather than guessing I
> would really like to know for sure)? This would mean, that I either
> have to specify exactly the same JEE versions in the Maven scripts so
> it can download them, or point Maven to the physical files shipped
> with Glassfish.

You do not have to use exactly the same versions, and generally
shouldn't need to depend on most of them directly at all.

Of course, if you're using code that's not part of the Java EE 6 spec,
you'll want to specify a compile-time dependency on it as normal, so
it's bundled in your war. Make that a runtime dependency instead if you
don't need to use its APIs directly, as in the case of things like the
slf4j backend implementation jars.

If you're using code that's bundled in Glassfish but not covered by the
Java EE 6 API, then I'd declare a <scope>provided</scope> dependency on
the bundled version of the jar.

> Or should it not matter that I compiled against 2.1.0 but Glassfish
> let's say contains 2.0.1?

It depends on the particular package. if 2.1.0 is API compatible with
2.0.1 then it's fine, but if 2.1.0 isn't API compatible you might get
weird runtime issues, deployment failure, classloader errors, etc.

Stick to the Java EE 6 APIs where possible.

-- 
Craig Ringer
Tech-related writing at http://soapyfrogs.blogspot.com/