7

我最近遇到了 glassfish 独立 (v3.1) 与 glassfish 嵌入式 (v3.1) 与 java SE 以及 java.endorsed.dirs 的使用方式的问题。我遇到的具体问题就在这里,但我认为这不是我最后一次遇到类似的问题。

我在此处此处找到的信息建议在编译时将 glassfish 认可的库添加到引导类路径中。但是,错误报告表明,在使用 glassfish 嵌入式时,很难正确设置认可的库。

因此,似乎当我部署到独立 glassfish 容器时,我的应用程序将针对 glassfish 包含的认可库运行,但在使用嵌入式容器时不会。我遇到了我原来的问题,因为 maven-embedded-glassfish-plugin 没有像 glassfish 独立一样使用认可的库启动 glassfish 嵌入。我也不确定其他容器(例如:jboss)是否包含与 glassfish 相同的认可库集。

所以,我 (1) 是否应该(很多)努力确保我的应用程序是针对认可的库编译的,并始终部署到使用认可的库引导的容器中,还是应该 (2) 坚持使用捆绑的内容使用 Java SE 6?

如果我选择 (2),在将我的应用程序部署到使用更新的认可库引导的容器时,我是否需要担心不兼容?

我将不胜感激任何人都可以提供的任何见解。

4

2 回答 2

4

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.

于 2012-08-15T15:14:07.860 回答
2

我可能在这里遗漏了一些明显的东西,但是……GlassFish Embeded 不附带与 Java EE 规范兼容的库吗?这些库不是默认加载的吗?(如果不是,请在此处填写错误:http: //java.net/jira/browse/EMBEDDED_GLASSFISH)。

我的意思是:您应该针对 Java EE 规范 API 进行编译,并让容器使用它自己的实现。

对于第一部分,如果您使用 Maven,我喜欢Codehaus 原型设置背书库的方式。它既干净又与应用程序服务器无关:

<properties>
   <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

...

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <compilerArguments>
            <endorseddirs>${endorsed.dir}</endorseddirs>
        </compilerArguments>
    </configuration>
 </plugin>

...

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.1</version>
    <executions>
       <execution>
            <phase>validate</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <outputDirectory>${endorsed.dir}</outputDirectory>
                <silent>true</silent>
                <artifactItems>
                    <artifactItem>
                        <groupId>javax</groupId>
                        <artifactId>javaee-endorsed-api</artifactId>
                        <version>6.0</version>
                        <type>jar</type>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

这几乎是针对 Java EE 6 API 编译项目所需的全部内容。任何符合 Java EE 6 的应用服务器都应该提供这些服务,而且您不必担心它们如何让您的应用程序使用这些服务。

引导 Java EE 服务的责任应该是您的应用服务器。如果您尝试自己的“内部”解决方案,JAR Hell 很可能会崩溃。

干杯,

于 2011-06-25T23:34:05.663 回答