I've recently run into a problem with glassfish standalone (v3.1) vs glassfish embedded (v3.1) vs java SE and the way java.endorsed.dirs is used. The specific problem I had is here, but I don't think it's the last time I'm going to run into something similar.
The information I found here and here suggests adding the glassfish endorsed libs to the bootstrap classpath when compiling. However, this bug report suggests it is difficult to get the endorsed libs set correctly when using glassfish embedded.
So, it seems like when I deploy to a standalone glassfish container my application is going to run against the endorsed libs that glassfish includes, but when using the embedded container it won't. I encountered my original problem because the maven-embedded-glassfish-plugin doesn't start glassfish embedded using the endorsed libs like glassfish standalone does. I'm also unsure whether other containers (ex: jboss) include the same set of endorsed libs as glassfish.
So, am I (1)supposed to struggle (a lot) to make sure my application is compiled against the endorsed libs and always deployed to a container that is bootstrapped using the endorsed libs or should I (2)just stick to using what's bundled with Java SE 6?
If I choose (2), will I have to worry about incompatibilities when deploying my application to a container that is bootstrapped with newer endorsed libs?
I would appreciate any insight that anyone can offer.
EDIT: The javaee-endorsed-api
approach above probably will work fine, but it gives me the willies. I don't think it is produced or maintained anymore. Furthermore the pom.xml
it contains within it reflects that at some point it was called javaee-compact-api
, and you can see how they strip the implementation classes out of it. By contrast, cherry-picking the API jars you want to use as endorsed (as I recommend below) seems to be more stable and flexible. Finally, if you still want to use the javaee-endorsed-api
approach, you can still use the general approach I recommend and point to javaee-endorsed-api.jar
instead.
Ryan; I just combed through your long trail on this (touching StackOverflow, the java.net forums, etc.) on the same journey.
During unit or integration testing you'll need to set the java.endorsed.dirs
System property, as you know.
The trick is you have to do this in such a way that the JVM running the tests picks it up. And that depends on how you have Surefire running.
If for some reason you have Surefire set to not fork, this is probably a bad thing, and you should re-evaluate your configuration here.
If you have Surefire set to fork, then you might think you could simply include java.endorsed.dirs
in a systemPropertyVariables
stanza, like this:
<systemPropertyVariables>
<java.endorsed.dirs>weWillGetToThisInAMoment</java.endorsed.dirs>
</systemPropertyVariables>
...but that would be wrong. The reason is that the program that is actually running is something called the ForkedBooter
, and the ForkedBooter
programmatically sets system properties for your unit tests. That is, by the time your <systemPropertyVariables>
stanza is read by the ForkedBooter
it's already too late.
But you can use <argLine>
in your Surefire configuration like this:
<configuration>
<argLine>-Djava.endorsed.dirs=weWillGetToThisInAMoment</argLine>
</configuration>
Now the VM that Surefire forks will have its endorsed directories set appropriately. Now let's talk about what value to supply.
You want to cherry pick the APIs to override. In your case, javax.annotation.*
is a legitimate choice. You want to supply the directory in your local Maven repository that houses the relevant jar.
Here is the value that I use:
${settings.localRepository}${file.separator}org${file.separator}glassfish${file.separator}main${file.separator}javaee-api${file-separator}javax.annotation${file.separator}${javaxAnnotationVersion}
${settings.localRepository}
will expand to the value of where your local Maven repository lives.${file.separator}
is a way of getting the value of System.getProperty("file.separator")
in a Maven property replacement.<dependency>
on the GlassFish artifact that bundles up the javax.annotation
package as defined in Java EE 6. So here I've constructed a path to the artifact. I've also defined a property named javaxAnnotationVersion
, which, for me, is set to 3.1.2
.Once you do all of this, then when Surefire forks a VM to run your unit tests, the endorsed directories will be set to the directory in your local Maven repository containing the jar that houses the javax.annotation
classes, and now embedded GlassFish—which runs in-process—will use the Java EE 6 versions of javax.annotation
classes instead of the Java SE 6 versions. I hope this helps you out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With