views:

394

answers:

2

I'm new to EJB 3 and the JPA.

I've created a datasource in the appserver which is jdbc/AppDataSource. The default persistence provider is left as com.ibm.websphere.persistence.PersistenceProviderImpl. And I left the default jta data source JNDI name as AppDataSource itself. I'm actually confused regarding JTA and non-JTA. What differentiates them?

I generated the entities and created an EntityTransaction object in the bean. Upon calling the persist() and commit() methods, I get an error:

javax.ejb.EJBException: See nested exception; nested exception is: <openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal user error> org.apache.openjpa.persistence.ArgumentException: A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property.
Caused by: <openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal user error> org.apache.openjpa.persistence.ArgumentException: A JDBC Driver or DataSource class name must be specified in the ConnectionDriverName property.

How does openjpa comes into picture here?

As of now, my persistence.xml contains the entity class names only.

How can I make it use the default appserver values for data source. Or else how can I provide the details of jpa provider and datasource details in the persistence.xml?

Please provide your inputs.

+2  A: 

This question actually involves many concepts and I won't cover them all in details. For more exhaustive details, I suggest reading the whole Chapter 5 - Entity Managers and Persistence Contexts of the JPA 1.0 specification (and the other relevant sections mentioned at the end of this answer). I will rather try to describe the most common scenario in a Java EE environment.

Within an EJB environment, one would typically use:

  • A container-managed entity manager (must be a JTA entity manager)
    • transaction-scoped in Stateless Session Beans (SLSB)
    • extended in Stateful Session Beans (SFSB)
  • JTA Transaction Management (and not resource-local transactions unless this is really what you want)

Here is how a persistence.xml for a JTA entity manager that uses a data source with a JNDI name java:comp/env/jdbc/AppDataSource can be set up, OpenJPA being the persistence provider used by WebSphere:

<?xml version="1.0" encoding="UTF-8"?>
<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_1_0.xsd"
  version="1.0">
  <persistence-unit name="MyPu" transaction-type="JTA">
    <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
    <jta-data-source>java:comp/env/jdbc/AppDataSource</jta-data-source>
    <class>com.acme.domain.Foo</class>
    <class>com.acme.domain.Bar</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <!-- OpenJPA specific properties -->
      <property name="openjpa.TransactionMode" value="managed"/>
      <property name="openjpa.ConnectionFactoryMode" value="managed"/>
      <property name="openjpa.jdbc.DBDictionary" value="db2"/>
    </properties>
  </persistence-unit>
</persistence>

For the OpenJPA properties, refer to the OpenJPA documentation.

And here is how a SLSB (using Container Managed Transactions) could get a container managed Entity Manager injected:

@Stateless
public class EmployeeServiceBean implements EmployeeService {
    @PersistenceContext(unitName="MyPu")
    private EntityManager em;

    public Employee createEmployee(int id, String name, long salary) {
        Employee emp = new Employee(id);
        emp.setName(name);
        emp.setSalary(salary);
        em.persist(emp);
        return emp;
    }
    ...    
}

And that's all. The life cycle of the entity manager is managed by the container transparently for the application (no createEM/close) and the entity manager participates in the JTA transaction managed by the container (no explicit begin/commit).

As previously hinted, I'm just scratching the surface, my goal is somehow to put you on the right path. To go further, I suggest grabbing a book (e.g. EJB3 in Action). Meanwhile, the references below would be a good reading.

References

  • JPA 1.0 specification
    • Section 5.2.1 "Obtaining an Entity Manager in the Java EE Environment"
    • Section 5.5 "Controlling Transactions"
    • Section 5.6 "Container-managed Persistence Contexts"
    • Section 6.2.1.2 "transaction-type"
    • Section 6.2.1.4 "provider"
    • Section 6.2.1.5 "jta-data-source, non-jta-data-source"

Resources

Pascal Thivent
Really really helpful! I updated my persistence.xml and included the JTA datasource and I'm reading the documentation of openjpa and EJB specs too...
whoopy_whale
@whoopy Glad it was helpful (it's not an topic easy to summarize).
Pascal Thivent
A: 

Hi, I am facing issue to override persistence.xml in jboss and with hibernate JPA provider, I spent couple of nights but i couldn't solve it. I am using jboss + hibernate+mysql + ejb3. my requirement is i will provide the connection url and the persistence unit will connect to the DB but it will be dynamically. so my code below .. if anyone can help it will be appreciated.

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">

org.hibernate.ejb.HibernatePersistence java:/MysqlDS

public static EntityManagerFactory createEMF(String dbName) {

    Map<String, Object> configOverrides = new HashMap<String, Object>();
    configOverrides.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
    configOverrides.put("hibernate.connection.url", "jdbc:mysql://remoteserver/xxxx");
    configOverrides.put("hibernate.connection.username", "root");
    configOverrides.put("hibernate.connection.password", "root");

    return Persistence.createEntityManagerFactory("blayerPU", configOverrides);

but while i run it still connect to mysqlDS configuration (local db server) instead to remoteserver(need to be overridden)

george