How to use a container-managed transaction (CMT) with JBoss AS 6, Hibernate 3.6, JPA, JTA, and EJB3

I am trying to configure a web application using CMT. It works for me autonomously in Eclipse, and now I'm trying to get it to work in Jboss AS 6 using Struts 1.0. I chose CMT because the doco I read suggests that it is the best and "least verbose to use." Hibernate 3.6 seems to be using a modern / good practical application.

I can load objects from the MySQL database using the following code extracts, but the stored objects are not dumped / synchronized / stored in the database:

Inside Struts 1.0 Action Class:

InitialContext ctx = new InitialContext(); EntityManagerFactory emf = (EntityManagerFactory)ctx.lookup("java:/MyEntityManagerFactory"); 

'emf' is then passed to the method with my DAO class, which summarizes below:

 @PersistenceContext(unitName="purejetJPA") EntityManager em; @TransactionAttribute(TransactionAttributeType.REQUIRED) exampleMethodInMyCustomDAOClass() { EntityManager em = emf.createEntityManager(); em.find(MyCustomEntity.class, 542); // works successfully em.persist(newInstanceOfMyCustomEntity); // this executes ok and generates an ID // however the entity is not saved to database upon completion } 

Content persistence.xml:

  <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.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_1_0.xsd"> <persistence-unit name="myPersistanceUnitName" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/MySqlDS</jta-data-source> <class>my.custom.entity.Classes</class> <properties> <property name="jboss.entity.manager.factory.jndi.name" value="java:/MyEntityManagerFactory"/> <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> <property name="hibernate.connection.autocommit" value="false"/> <property name="hibernate.current_session_context_class" value="jta"/> </properties> </persistence-unit> </persistence> 

The Hibernate EntityManager documentation has a very limited description of how to achieve CMT:


The manager / transaction manager identifier for using the CMT and EJB3 containers is as follows: // CMT idiom via injection @PersistenceContext (name = "sample") EntityManager em;


And this jboss.org article reads:


Transaction demarcation with EJB / CMT

Our goal is to remove any transaction demarcation code from the data access code:

 @TransactionAttribute(TransactionAttributeType.REQUIRED) public void doSomeWork() { // Do some work factory.getCurrentSession().load(...); factory.getCurrentSession().persist(...); } 

My questions:

  • In the line "actory.getCurrentSession (). Load (...);", what type of "factory" and how to create it? Is this Hibernate.SessionFactory? Or a Jboss or HTTP session?

  • In the line "@PersistenceContext (name =" sample ") EntityManager em;" What is a "name"? I found an example on the forum for something using "unitName" instead of "name". Is this line the way I first declare an EntityManager object that I use to call .persist (). Find (), etc.? (and therefore my code that creates the EntityManagerFactory is not required)

  • Should I consider researching and using "Java Context and Dependency Injection" (CDI)?

Any help is greatly appreciated. Please let me know what other bits of code or configuration files I should provide


Update:

If I do not use EntityManagerFactory and do not get EntityManager instead of using @PersistenceContext, then there should be something like this code for my "bean session" (a class that restores + save objects based on each user) be a way to do this?

 @Stateful @TransactionManagement(value=TransactionManagementType.BEAN) public class X implements IX { @PersistenceContext(unitName="MySQL", type=PersistenceContextType.EXTENDED) private EntityManager em; @Resource private UserTransaction tx; public void doStuff() { tx.begin(); em.joinTransaction(); em.find(myEntity); em.perrsist(myEntity); tx.commit(); } 

If this is on the right track, what is needed in persistence.xml? From all my reading of doco and the internet, I'm not sure which one might be required:

 <property name="jboss.entity.manager.factory.jndi.name" value="java:/MyEntityManagerFactory"/> <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.CMTTransactionFactory"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> <property name="hibernate.connection.autocommit" value="false"/> <property name="hibernate.current_session_context_class" value="jta"/> 
+4
source share
2 answers

1) The answer is in the same document that you linked :-)

In the above examples, you can see access to SessionFactory. How do you access factory everywhere in your code? Again, if you are starting the Java EE environment or using the built-in service in JSE, you can simply view it from JNDI, where Hibernate can bind it at startup. Another solution is to save it in a global static singlet after launch.

2) name is a link to the name specified in the persistence-unit tag on your persistence.xml . In your case, this is myPersistanceUnitName .

3) Yes, if you understand that this does not mean replacing anything, it means facilitating the consumption of "beans" (these may be resources from AS).

Also note that in order to get a managed EntityManager (with perks) you should not get EntityManagerFactory from AS. You must get EM. As you mentioned, it is like this:

 @PersistenceContext(name="myPersistanceUnitName") EntityManager em; 

It will only work on things that AS manages, such as servlets, other CDI beans, EJB, ... Not sure if the Action Struts classes will get it :-)

+1
source

I also have this problem. I narrowed it down to using @WebService and we insert the EntityManager through @PersistenceContext , entitymanager is null.

Also, if we delegate access to DAO data and add @TransactionAttribute(TransactionAttributeType.MANDATORY) for the DAO class, it throws javax.ejb.EJBTransactionRequiredException .

I wonder if this is a JBoss error that does not add a beans stateless session that has @WebService annotations for a container-managed transaction.

0
source

Source: https://habr.com/ru/post/1344537/


All Articles