0

May be this is a common question, I am trying to create an Stateless session EJB 3.0 with resource reference for data source in Websphere 7.0.

The following code is working:

package com;
import javax.ejb.Stateless;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Stateless
public class Test1 implements Test1Remote {
 @Resource DataSource ds;
 public Test1() {}
 public boolean testDs() {
  boolean valid = true;
  try {
   ds.getConnection();
  } catch (Exception e) {
   e.printStackTrace();
   valid = true;
  }
  return valid;
 }
}


<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd
    xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee 
    http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" version="1.0">

    <session name="Test1">
     <interface class="com.Test1Remote" binding-name="Test1"/>
     <resource-ref name="com.Test1/ds" binding-name="jdbc/myDataSource"></resource-ref>
    </session>
</ejb-jar-bnd>

The following code is not working and giving me excpetion

javax.naming.NameNotFoundException: Name comp/env/jdbc not found in context "java:".

But not sure how to proceed when the Datasource needs to be looked up in initialContext out side of EJB.

package com;
import javax.ejb.Stateless;
@Stateless
public class Test1 implements Test1Remote {
    public Test1() {
    }
    public boolean testDs(){
     boolean valid = true;
     try {
         MyConnection ds = new MyConnection();
         ds.getConnection();
     } catch (Exception e) {
        e.printStackTrace();
        valid = true;
    }
    return valid;
    }
}

package com;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;


public class MyConnection{
    private DataSource ds;
    public Object getConnection() throws Exception  {
 try {
    final InitialContextinitCtx = new InitialContext();
    ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/myDataSource");
    return ds.getConnection();
    } catch (NamingException e) {
     e.printStackTrace();
     throw e;
    } catch (SQLException e) {
     e.printStackTrace();
     throw e;
    }
 }
}

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd
    xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee 
    http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" version="1.0">

    <session name="Test1">
     <interface class="com.Test1Remote" binding-name="Test1"/>
    </session>
</ejb-jar-bnd>

If I dont use "java:comp/env/" in data source lookup then it works fine, but that is not a good practice.

UPDATE: Thanks for the replies. My goal is to replace an existing EJB 2.1 to EJB 3.0. The current EJB 2.1 is designed similar to code snippet 2 so I wrote this test. EJB 2.1 is functioning with the resource defined out side of the ejb (but has the resource reference declared in ejb-jar.xml). If I dont follow the same approach then it will have a huge impact which I want to avoid.

P̲̳x͓L̳
  • 3,615
  • 3
  • 29
  • 37
user2104750
  • 21
  • 1
  • 4

2 Answers2

0

You will have to use JNDI name(ie: java:comp/env/jdbc/myDataSource) of the resource residing in the server. JNDI name is a unique identifier of the resource. There is no other way whether it is a standalone java or container driven java. If you are using EJB then you can use annotations and refer the resource but still the resource will be looked up by your binding files where you have mentioned JNDI name. One way or the other, you will have to use JNDI name of the resource.

Answer Updated

If you are using EJB then just use annotation to access resource exactly what you have done first time. What you are doing is a bad practice. Because EJB is loaded and maintained in a container. There is no gaurantee that DataSource POJO will be loaded by class-loader before EJB makes a call to it. Both have different life cycles. So let the container inject the resource for you. It is the right practice. So EJB being dependent on a POJO is a bad practice. Not recommended in Java EE.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Ravi Trivedi
  • 2,340
  • 2
  • 14
  • 20
  • Thanks for the reply.I agree that I have to use JNDI name, but not sure how to do it in the second snippet of code I had. – user2104750 Apr 11 '13 at 14:18
  • If you are using EJB then just use annotation to access resource exactly what you have done first time. What you are doing is a bad practice. Because EJB is loaded and maintained in a container. There is no gaurantee that DataSource POJO will be loaded by class-loader before EJB makes a call to it. Both have different life cycles. So let the container inject the resource for you. It is the right practice. So EJB being dependent on a POJO is a bad practice. Not recommended in J2EEs. Regards, Ravi. – Ravi Trivedi Apr 11 '13 at 14:45
0

Replace @Resource with @Resource(name="jdbc/myDataSource") and it should work.

Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28
  • The code with annotations is working good, problem is with second snippet of code that looks for datasource outside of EJB... – user2104750 Apr 11 '13 at 17:30
  • Yes, and changing the annotation will ensure that the JNDI name is what you expect in the other code snippet. – Andreas Veithen Apr 11 '13 at 18:10
  • I am sorry, I am not sure where you are asking me to replace the annotation. In code snippet 2, I used only @Stateless annotation.If possible can you provide me the code? – user2104750 Apr 11 '13 at 20:54
  • If you want to get rid of the injection altogether, then you need to create an ejb-jar.xml deployment descriptor and declare the resource reference there (as you would have done with EJB 2.1). – Andreas Veithen Apr 12 '13 at 05:20