如何使JNDI名称与GlassFish和WildFly兼容

时间:2014-10-19 13:43:40

标签: java java-ee glassfish jndi wildfly

我正在开发Java EE 7应用程序,并且要求将应用程序部署到运行GlassFish 4.0或WildFly 8.1.0的应用程序服务器上。我遇到的问题是GlassFish和WildFly对JNDI名称使用略有不同的格式,但我无法看到如何使我的应用程序兼容两者。

在GlassFish中,我的persistence.xml文件引用数据源jdbc / myDataSouce,但在WildFly中,数据源需要是java:/ jdbc / myDataSource。

对于使用@Resource注释的类也是如此。在GlassFish中,使用JavaMail的类的注释将是@Resource(name =" mail / myMailSession"),但要部署到WildFly,这需要是@Resource(name =" java:mail / myMailSession&#34)

我知道我可以解压缩EAR和JAR文件以手动编辑persistence.xml等文件,但我不能对已经使用@Resource注释的类执行此操作。

有没有办法可以将我的编译应用程序部署到GlassFish和WildFly上,而无需维护两个不同版本的代码?我假设答案可能取决于特定于应用程序的部署描述符,但我找不到涵盖这两种情况的任何示例。

有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:4)

您可以修改Wildfly JNDi名称并从相应的JNDI名称中删除不需要的前缀,以找到两个应用服务器中的最小公分母。以下适用于Glassfish和JBoss AS 7.1。由于我希望Wildfly在这方面与JBoss向后兼容,我想它也适用于Wildfly。

持久性

注入:

@PersistenceContext(unitName="TestPU")
private EntityManager entityManager;

或通过ejb-jar.xml

<persistence-context-ref>
    <persistence-context-ref-name>entityManager</persistence-context-ref-name>
    <persistence-unit-name>TestPU</persistence-unit-name>
    <injection-target> ... </injection-target>
</persistence-context-ref>

相应的persistence.xml

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="         http://java.sun.com/xml/ns/persistence         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="TestPU" transaction-type="JTA">
    <jta-data-source>datasources/TestDS</jta-data-source>
    <class>org.jeeventstore.persistence.jpa.EventStoreEntry</class>
    <properties>
      <property name="hibernate.show_sql" value="false"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.connection.charSet" value="UTF-8"/>
      <property name="eclipselink.logging.level" value="FINE"/>
      <property name="eclipselink.logging.level.sql" value="FINE"/>
      <property name="eclipselink.logging.parameters" value="true"/>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

(请注意简单的jta-data-source JNDI名称)

这里有一个用于在部署时指定Derby数据库的glassfish-resources.xml文件,类似的设置可以用于MySQL或Postgres。

<resources>

    <jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
                   jndi-name="datasources/TestDS"/>

    <jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
                          res-type="javax.sql.DataSource"
                          datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
                          is-isolation-level-guaranteed="false">
        <property name="databaseName" value="target/databases/derby"/>
        <property name="createDatabase" value="create"/>
    </jdbc-connection-pool>

</resources>

来自JBoss standalone.xml的设置:

<datasource jta="true" jndi-name="java:/datasources/TestDS" pool-name="TestDS" enabled="true" use-ccm="false">
    <connection-url>jdbc:postgresql://localhost/test_db</connection-url>
    ...
</datasource>

资源

我没有在Glassfish上注入JavaMail组件,但是类似于datasoruce设置,可能值得尝试剥离&#34; java:&#34;部分来自@Resource注释。

@Resource(name = "mail/myMailSession")

然后配置Wildfly,以便邮件资源在&#34; java:mail/myMailSession&#34; JNDI的位置。

通过ejb-jar.xml

注入

另一种选择是通过ejb-jar.xml文件手动注入字段,然后使用maven等构建工具将ejb-jar-glassfish.xmlejb-jar-wildfly.xml复制到所需的{{1}在汇编时。

在我们的一个项目中,我们使用混合方法来避免xml配置的负担:我们配置了少量的&#34;提供商&#34; bean通过ejb-jar.xml将持久化上下文注入ejb-jar.xml,然后使用CDI通过PersistenceContextProviderPersistenceContextProvider注入到EJB中,这些都是在没有进一步发现的情况下发现的配置,因为它们位于同一个EAR中。

答案 1 :(得分:1)

我还没有遇到邮件困境。但是我遇到了与数据源定义相同的问题,而我的解决方案是不使用服务器控制台设置数据源,而是使用@DataSourceDefinition注释使它们与归档一起部署。事实证明,如果在部署期间设置了数据源,WildFly不会抱怨java:app/blabla..

以下是适用于GlassFish和WildFly的真实世界示例:

https://github.com/martinanderssondotcom/java-ee-concepts/../ArquillianDS.java

请注意,声明的数据源JNDI名称为:

  

的java:应用程序/ ENV / ArquillianDS

这是相关的persistence.xml文件(不介意此存储库中文件的名称,存储库代表在运行时构建存档的测试项目,应用程序将更改文件的名称归档到persistence.xml):

https://github.com/MartinanderssonDotcom/java-ee-concepts/../persistence-update.xml

另请注意,持久性单元需要使用此JNDI名称定位的数据源:

  

的java:应用程序/ ENV / ArquillianDS

此部署与GlassFish和WildFly完美配合。我已经注意到,如果我们在部署期间声明数据源,那么我们付出的代价是没有看到admin gui / console中任何地方列出的数据源。对我来说,这是一个很小的代价,以便有一个真正的便携式应用程序。作为额外的奖励,我不必编写冗长的安装/设置说明。对于我的所有项目,数据源是应用程序的固有部分,我不介意在存档中有一个表示数据源的类文件。

上述数据源使用的是Java DB(或旧式学校的“Apache Derby”)。正如ArquillianDS.java文件中的一些注释所描述的那样:GlassFish在使用简单的URL连接字符串和Java DB时遇到了问题。因此,我使用了明确指定@DataSourceDefinition的所有属性。最近在我的另一个项目(唉不是公共项目)中,我使用了相同的部署时间数据源定义结构,但是针对MySQL。这是数据源定义,它适用于两个服务器:

@DataSourceDefinition(
        name = "java:app/env/maLivechatDS",
        url = "jdbc:mysql://localhost:3306/malivechat_db?createDatabaseIfNotExist=true&user=root&password",
        className = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
)
@ManagedBean
public class MySQLDataSource { }

请注意,驱动程序为MysqlDataSource而非MysqlXADataSource。我的应用程序中的一点使用了相当复杂的事务方案,如果我使用XA驱动程序,GlassFish会遇到问题。但是,我的应用程序使用的非XA驱动程序仍然可以正常使用JTA事务,所以对我来说,这只是一个让船浮动的廉价技巧。您应该使用XA驱动程序。

答案 2 :(得分:0)

对于带有可移植DataSourceDefinition注释的JNDI可移植性,我在payara-5.192,wildfly-17.0.1,tomee-8-M3和openLiberty-19.0.0.7上对其进行了测试

@DataSourceDefinition(
name = "java:app/env/jdbc/mysql_app_name",
className = "com.mysql.cj.jdbc.MysqlConnectionPoolDataSource",
url = "jdbc:mysql://localhost:3306/db_name?characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&user=root&password=password",
minPoolSize = 1,
properties = {"characterEncoding=utf-8","zeroDateTimeBehavior=CONVERT_TO_NULL"})

我将它与MySQL连接器8一起使用。 请参阅reference。对于wildfly,我创建了用于配置的启动bean类,并在启动类中设置了注释。 对于openLiberty,请在server.xml中添加

<application id="app_name" contextRoot="/app_name" name="app_name" location="../app_name.war" type="war">
  <classloader commonLibraryRef="mysql"/>
</application>
<library id="mysql">
    <file name="/path_to/mysql-connector-java-8.0.17.jar"/>
</library>

并将战争文件放入

  

usr / servers / defaultServer

文件夹