2

I am new to JPA and developing a webapp(J2EE) where the webapp is in Tomcat so I can't use @PersistenceContext. I decided to use a Helper class and everything was going fine. Then I decided to implement JNDI for connection pooling and I managed to get Datasource.

The Helper Class looks like the following:

try {
    Context initCtx = new InitialContext();
    entityManager =                                   //class cast exception
        (EntityManager)initCtx.lookup(
            "java:/comp/env/jdbc/LCDS"
        );
    DataSource ds= (DataSource)initCtx.lookup(
            "java:/comp/env/jdbc/LCDS"
    ); 
    System.out.println(ds.getConnection()+"Cool");
    //jdbc:mysql://localhost:3306/XXXXXXX, UserName=root@localhost, MySQL-AB JDBC  DriverCool
    emf=(EntityManagerFactory) source.getConnection();      //class cast exception
    emf = Persistence.createEntityManagerFactory("XXXX");   //working version
} 

The error is:

ava.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.BasicDataSource cannot be cast to javax.persistence.EntityManager

I don't know where I am getting wrong. I am not able to get EntityManagerFactory or EntityManager via JNDI lookup. I tried @Resource(name="jdbc/LCDS") and @PersistenceUnit(name="jdbc/LCDS").

Keale
  • 3,924
  • 3
  • 29
  • 46
gopal gupta
  • 119
  • 11
  • Why do you do two calls to the same JNDI element and expect the result to be instances of different classes each time? Check the Tomcat manual to see how a `PersistenceUnit` is deployed to it. – SJuan76 Oct 23 '14 at 10:44
  • `emf=(EntityManagerFactory) source.getConnection()` - here you are getting connection not EMF, so class cast is correct. Why just not use: `@PersistenceUnit(name="UNITNAME") EntityManagerFactory emf;` Unitname is from persistence.xml, it is not datasource jndi name. – Gas Oct 23 '14 at 10:49
  • emf = Persistence.createEntityManagerFactory("UNIT NAME") and from emf i am able to get Entitymanager....then how do we use JNDI in jpa and where...??? – gopal gupta Oct 23 '14 at 10:53
  • You could try: `emf = (EntityManagerFactory) new InitialContext().lookup("java:comp/env/persistence/UNIT NAME");` – Gas Oct 23 '14 at 10:58
  • Should i need to change jdbc/LCDS to jdbc/MyMyPersistenceUnitName...in(Context.xml)also...if not i tried with jdbc/MyMyPersistenceUnitName Or persistence/MyMyPersistenceUnitName – gopal gupta Oct 23 '14 at 11:07
  • Name [persistence/MyMyPersistenceUnitName] is not bound in this Context. Unable to find [persistence]. same error with jdbc/LCDS :( – gopal gupta Oct 23 '14 at 11:16
  • It will not work in Tomcat, sorry. See my answer update. – Gas Oct 23 '14 at 15:48

2 Answers2

0

UPDATE
JNDI access to persistence unit is not possible due to Tomcat limitations. See JPA Tomcat limitations. You will have to use emf = Persistence.createEntityManagerFactory("UNIT NAME").
Sorry for misleading answer. I've tested that on WebSphere Liberty, didn't have Tomcat at hand.

If you need that functionality check WebSphere Liberty, which is as fast and lightweight as Tomcat, but is fully Java EE Web profile compliant. It has lots of useful features like JPA, EJBLite, JAX-RS already available if needed, without fighting with additional libraries configuration.

UPDATE END

I've checked on WebSphere Liberty, you need to create reference to lookup your persistence unit via JNDI. You have two options to create that:

  • Use annotation at the class level
    In any of your servlets you need to define annotation using the follownig:

@PersistenceUnit(name="JPATestRef", unitName="UnitName")
public class JPATester extends HttpServlet {
...

  • Use entry in web.xml
<persistence-unit-ref>
  <persistence-unit-ref-name>JPATestRef</persistence-unit-ref-name>
  <persistence-unit-name>UnitName</persistence-unit-name>
</persistence-unit-ref>

Then you access it using the following code:

try {
    InitialContext ctx = new InitialContext();
    System.out.println("looking EntityManagerFactory:");
    EntityManagerFactory emf2 = (EntityManagerFactory) ctx.lookup("java:comp/env/JPATestRef");
    System.out.println("emf:2" + emf2);

} catch (NamingException e) {
Gas
  • 17,601
  • 4
  • 46
  • 93
0

To use a JNDI datasource in JPA, this should be specified in the persistence.xml, something like:

    <persistence 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" version="2">
        <persistence-unit name="..." transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>java:/comp/env/jdbc/LCDS</non-jta-data-source>
    ...

Then you just have to create your EntityManagerFactory via Persistence#createEntityManagerFactory(String). If you want to recycle the EntityManagerFactory, this should be done outside of JNDI (e.g. as a ServletContext attribute). This is because Tomcat is not a Java EE server, only a servlet container: he is not able to inject the persistence unit.

bdulac
  • 1,686
  • 17
  • 26