Lookup jndi resources WebSphere 8.5, Spring 3.1.3,

2019-06-13 17:27发布

问题:

In my application I need to lookup jndi resources for database connection.

I have an EAR which contain my EJB project with remote and stateless ejb: ABean.jar

Reading Using Spring and Hibernate with WebSphere Application Server I defined in the application.xml of EAR project:

<module>
    <ejb>ABean.jar</ejb>

</module>

<resource-ref>
    <res-ref-name>jdbc/b</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

In my spring context:

<jee:jndi-lookup
    id="aDataSource" 
    jndi-name="jdbc/b" 
    cache="true" 
    expected-type="javax.sql.DataSource"/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="META-INF/persistence.xml"/>
    <property name="dataSource" ref="aDataSource" />
    <property name="persistenceUnitName" value="APU"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.DB2390Dialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property> 
</bean>

Now, if I install application by WebSphere console, it ask to me to assign the jndi resource to jdbc/b (and it is ok), but if I try to call an ejb, a NameNotFoundException is throw because jdbc/b is not found!

Reading better the previous link i see:

For EJB JAR files, the same resource-ref should be declared in each EJB that needs to access the data source.

so I try to define resource references into my ejb-jar.xml

<enterprise-beans>
<session>
   <ejb-name>TestServiceBean</ejb-name>
   <ejb-class>it.test.TestServiceBean</ejb-class>
   <session-type>Stateless</session-type>
   <transaction-type>Container</transaction-type>
   <resource-ref>
        <res-ref-name>jdbc/b</res-ref-name>         
        <res-type>javax.sql.DataSource</res-type>   
   </resource-ref>
 </session>
 </enterprise-beans>

I try to install again (I also assign the jndi resource to jdbc/b) and the call to the ejb run successfully, but if I have n ejb, do I need to assign n-times the same jndi resource to the n ejb resource-ref for jdbc/b?

What is wrong with my configuration? Isn't it possible "point" to the same resource-ref from all ejb? Do you have a complete example?

回答1:

Per the EE 6 spec, references declared in application.xml must be in the java:app (or java:global) namespaces, and it is recommend that they be in the env subcontext, so:

<res-ref-name>java:app/env/jdbc/b</res-ref-name>

This will allow the resource to be visible to all components in the application. Alternatively, you can declare a reference in the java:module context in ejb-jar.xml or via annotation.



回答2:

Updated answer. Example based on bkail answer. You need to define resource reference in application.xml like this:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
    <display-name>RefTestEAR</display-name>
    ....
    <resource-ref>
        <res-ref-name>java:app/env/jdbc/b</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</application>

Then in your application you can access it via:

InitialContext ctx = new InitialContext();
DataSource datasource = (DataSource) ctx.lookup("java:app/env/jdbc/b");

In your case since you are using Spring not InitialContext directly, you will probably need to change the lookup to and also verify if you have datasource reference in persistence.xml (I didn't test that in Spring as I don't have Spring sample at hand):

<jee:jndi-lookup
    id="aDataSource" 
    jndi-name="java:app/env/jdbc/b" 
    cache="true" 
    expected-type="javax.sql.DataSource"/>