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}
- Maven guarantees that
${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.
- In my case, I've already declared a
<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.