有处理 Java EE 和 java.endorsed.dirs 的最佳实践吗?
我最近遇到了 glassfish 独立版 (v3.1) 与 glassfish 嵌入式版 (v3.1) 与 java SE 以及 java.endorsed.dirs 的使用方式的问题。我遇到的具体问题是 在这里,但我不认为这是我最后一次遇到类似的事情。
我在此处和此处建议添加glassfish 在编译时将库支持到引导类路径。但是,此错误报告表明,在使用时很难正确设置认可的库嵌入玻璃鱼。
因此,当我部署到独立的 glassfish 容器时,我的应用程序似乎将针对 glassfish 包含的认可库运行,但在使用嵌入式容器时则不会。我遇到了最初的问题,因为 maven-embedded-glassfish-plugin 不会像 glassfish 独立那样使用认可的库启动内嵌 glassfish。我也不确定其他容器(例如:jboss)是否包含与 glassfish 相同的一组认可库。
那么,我是否 (1) 应该努力(很多)确保我的应用程序是针对认可的库进行编译的,并始终部署到使用认可的库引导的容器中,或者我应该 (2) 只坚持使用捆绑的内容使用 Java SE 6?
如果我选择 (2),在将应用程序部署到使用较新认可的库引导的容器时,我是否需要担心不兼容性?
我将不胜感激任何人都可以提供的任何见解。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编辑:上面的
javaee-endorsed-api
方法可能会很好地工作,但它让我感到不安。我认为它不再被生产或维护了。此外,它包含的pom.xml
反映了它在某个时候被称为javaee-compact-api
,您可以看到他们如何从中剥离实现类。相比之下,挑选您想要使用的 API jar(正如我在下面推荐的那样)似乎更加稳定和灵活。最后,如果您仍然想使用javaee-endorsed-api
方法,您仍然可以使用我推荐的通用方法并指向javaee-endorsed-api.jar
。瑞安;我刚刚梳理了您在同一旅程中对此的长期跟踪(涉及 StackOverflow、java.net 论坛等)。
如您所知,在单元或集成测试期间,您需要设置 java.endorsed.dirs 系统属性。
诀窍是您必须以这样的方式执行此操作,以便运行测试的 JVM 能够识别它。这取决于 Surefire 的运行方式。
如果由于某种原因您将 Surefire 设置为而不 fork,这可能是一件坏事,您应该在此处重新评估您的配置。
如果您将 Surefire 设置为 fork,那么您可能会认为您可以简单地将
java.endorsed.dirs
包含在systemPropertyVariables
节中,如下所示:...但这将是错误的。原因是实际运行的程序称为
ForkedBooter
,并且ForkedBooter
以编程方式为单元测试设置系统属性。也就是说,当
节被ForkedBooter
读取时,已经太晚了。但是你可以使用
在 Surefire 配置中如下所示:现在,Surefire 分叉的 VM 将适当设置其认可目录。现在我们来谈谈要提供什么价值。
您想要挑选要覆盖的 API。就您而言,
javax.annotation.*
是一个合法的选择。您想要提供本地 Maven 存储库中包含相关 jar 的目录。以下是我使用的值:
${settings.localRepository}
将扩展为本地 Maven 存储库所在位置的值。${file.separator}
是一种在 Maven 属性替换中获取System.getProperty("file.separator")
值的方法。javax.annotation
包的 GlassFish 工件EE 6。所以在这里我构建了一条通往工件的路径。我还定义了一个名为javaxAnnotationVersion
的属性,对我来说,它设置为3.1.2
。完成所有这些操作后,当 Surefire 分叉 VM 来运行单元测试时,认可的目录将设置为本地 Maven 存储库中的目录,其中包含包含 javax.annotation 类的 jar ,现在嵌入的 GlassFish(在进程中运行)将使用 Java EE 6 版本的 javax.annotation 类,而不是 Java SE 6 版本。我希望这对你有帮助。
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 thepom.xml
it contains within it reflects that at some point it was calledjavaee-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 thejavaee-endorsed-api
approach, you can still use the general approach I recommend and point tojavaee-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 asystemPropertyVariables
stanza, like this:...but that would be wrong. The reason is that the program that is actually running is something called the
ForkedBooter
, and theForkedBooter
programmatically sets system properties for your unit tests. That is, by the time your<systemPropertyVariables>
stanza is read by theForkedBooter
it's already too late.But you can use
<argLine>
in your Surefire configuration like this: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}
will expand to the value of where your local Maven repository lives.${file.separator}
is a way of getting the value ofSystem.getProperty("file.separator")
in a Maven property replacement.<dependency>
on the GlassFish artifact that bundles up thejavax.annotation
package as defined in Java EE 6. So here I've constructed a path to the artifact. I've also defined a property namedjavaxAnnotationVersion
, which, for me, is set to3.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 ofjavax.annotation
classes instead of the Java SE 6 versions. I hope this helps you out.我可能在这里遗漏了一些明显的东西,但是...GlassFish Embeded 不是附带与 Java EE 规范兼容的库吗?这些库不是默认加载的吗? (如果不是,请在此处填写错误:http://java.net/jira/browse/ EMBEDDED_GLASSFISH)。
我的意思是:您应该针对 Java EE 规范 API 进行编译,并让容器使用它自己的实现。
对于第一部分,如果您使用 Maven,我喜欢 Codehaus archetypes 设置的方式认可的库。它既干净又与应用程序服务器无关:
……
这
几乎是您根据 Java EE 6 API 编译项目所需的全部内容。任何符合 Java EE 6 的应用程序服务器都应该提供这些服务,并且您不应该担心它们如何将其提供给您的应用程序。
引导 Java EE 服务的责任应该由您的应用服务器负责。如果您尝试自己的“内部”解决方案,JAR Hell 很可能会崩溃。
干杯,
I may be missing something obvious here but... Isn't GlassFish Embbeded shipped with libraries compatible with the Java EE specs? And aren't those libraries loaded by default? (If they aren't, please fill a bug here: http://java.net/jira/browse/EMBEDDED_GLASSFISH).
What I mean is: You should compile against Java EE spec APIs, and just let the container use it's own implementations.
For the first part, if you use Maven, I like the way Codehaus archetypes sets the endorsed libs. It is both clean and Application Server Agnostic:
...
...
Which is pretty much all you need to compile your projects against Java EE 6 APIs. Any Java EE 6 compliant App Server should provide those services, and you shouldn't be worried about how they are making it available to your application.
The responsibility of bootstrapping Java EE Services should be of your App Server. If you try your own "in house" solution, chances are that JAR Hell will break loose.
Cheers,