JTA controlled transactions in JBoss AS7 using EclipseLink, Transaction is required - jpa

Environment
Application server: JBoss AS7 (7.1.1 Final)
JPA implementation: EclipseLink (2.4.1)
OS: Windows 7 DB: PostgreSQL 8.4
Update 2, solved
The problem was that i instantiated the AccountService class instead of injecting it using #EJB. After fixing that EntityManager was inected correctly in the service and a transaction was available when doing em.persist(account);
Update
I made a minimal project that shows my problems. Posted to Github:
https://github.com/gotling/jboss-eclipselink-problem
I have two problems that are probably related and due to me not understanding the use of EJB's correct.
I can not get EnityManager to be injected in AccountService.java in persistance JAR, resulting in NullPointerException.
If sending EntityManager in constructor to AccountService no tranasaction is found when doing em.persist.
Project structure
EJB
lib/persistanceunit.jar
web-service.war
Problem
I'm trying to get JBoss to manage transactions in my Java EE service. Problem is that EclipseLink does not seem to pick up the transaction managed by JBoss when trying to persist an entity.
I have followed the guide https://community.jboss.org/wiki/HowToUseEclipseLinkWithAS7 (Alternative 1 and Alternative 2 Step 4) on how to configure JBoss with EclipseLink.
Setup
WAR
Entity manager is injected like this in web-service.war:
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
public void notify(Notify notify) {
AccountService accountService = new AccountService(em);
accountService.create(notify);
}
}
There is actually a controller class between the class above and the service class, where transformation of the Account object is done, removed it to shorten code.
Persistance Unit
Entity is created like this
AccountService.java in persistanceunit.jar
#Stateless
public class AccountService {
private EntityManager em;
public AccountService(EntityManager em) {
this.em = em;
}
public void create(Account account) {
em.persist(account);
}
}
Stack trace
When calling a WS that should persist the Account entity I get an exception on em.persist(account);
...
Caused by: javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
at org.jboss.as.jpa.container.AbstractEntityManager.transactionIsRequired(AbstractEntityManager.java:692) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.jpa.container.AbstractEntityManager.persist(AbstractEntityManager.java:562) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at se.magos.service.AccountService.create(AccountService.java:50) [persistenceunit-0.0.1-SNAPSHOT.jar:]
Questions
I've enabled Trace logging. Should not id.au.ringerc.as7.eclipselinkpersistence be visible in the log?
Is it somehow possible to get the EntityManager injected inside the service class inside the persistanceunit.jar?
In which JBoss / EclipseLink version should this wor out of the box?

You should annotate the bean with #TransactionManagement(TransactionManagementType.CONTAINER) and the create method with #TransactionAttribute(TransactionAttributeType.REQUIRED).
The first annotation is required in order to let the application server know that transactions are managed by the container, the latter to let the method start a transaction, if there is no current one, as soon as it is invoked.

The problem was that AccountService class was instantiated instead of injected using #EJB annotation. After fixing that EntityManager was injected correctly in the service and a transaction was available when doing em.persist(account);
Before
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
public void notify(Notify notify) {
AccountService accountService = new AccountService(em);
accountService.create(notify);
}
}
After
#WebService(....)
public class NotificationConsumerImpl implements NotificationConsumer {
#PersistenceContext(unitName="foo")
EntityManager em;
#EJB
AccountService accountService;
public void notify(Notify notify) {
accountService.create(notify);
}
}

Related

Persistence unit not injected in webservice

I have an application that was working on Java 6 + Glassfish 3. I am migrating this project to run on Glassfish 5.1 with oracle java 8.
The application builds without problems. During deployment the only jpa/eclipselink related lines are
Info: EclipseLink, version: Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a
Info: /file:/home/eelke/NetBeansProjects/MplusLicentieService/build/web/WEB-INF/classes/_MplusLicentieServicePU login successful
However when a soap call is performed a NullPointerException is triggered. I have verified with the debugger that the pointer that is null is in fact the persistence unit. Here is the definition of the webservice, the EntitiyManager and one of the methods that failed. Within the method em == null. Left out other statements and variables.
#WebService(serviceName = "LicentieWebService")
public class LicentieWebService {
#PersistenceContext(unitName = "MplusLicentieServicePU")
private EntityManager em;
#Resource
private javax.transaction.UserTransaction utx;
#WebMethod(operationName = "getLicentie2")
public QLicentieAntwoord getLicentie2(
#WebParam(name = "licentieNr") String licentieNr,
#WebParam(name = "filiaalNr") int filiaal,
#WebParam(name = "werkplekNr") int werkplek,
#WebParam(name = "codewoord") String codewoord) {
try {
Licentie lic = em.find(Licentie.class, licentieNr);
...
} catch (ApplicationError ex) {
...
}
}
I also tried redefining the persistence unit in netbeans but this didn't change anything.
Some additional findings
In the same project is also a statelesss EJB which has a function that is called by a timer schedule. Into this EJB a second stateless EJB is injected with #Inject, this works. Into this second EJB the same persistent context is injected as in the webservice. This works, it is injected and queries are executed as expected.
Found some log lines which might be related
Info: JAX-WS RI specific descriptor (WEB-INF/sun-jaxws.xml) is found
in the archive web and hence Enterprise Web Service (109) deployment
is disabled for this archive to avoid duplication of services.

Transaction Error JTA DATASOURCE JPA CDI

data-source with JBoss EAP in my project.
For some reason when i try to persist an object i get the error below.
JBAS011469: Transaction is required to perform this operation (either
use a transaction or extended persistence context):
javax.faces.FacesException: #{back.salvar}:
javax.persistence.TransactionRequiredException: JBAS011469:
Transaction is required to perform this operation (either use a
transaction or extended persistence context)
There is #Transactional method but this method launch the error.
Anyone?
#Stateless
#Named
public class BaseDao implements Serializable
{
private static final long serialVersionUID = -8993128837557701804L;
#PersistenceContext
protected EntityManager manager;
#Transactional
public void persist(Object object)
{
manager.persist(object);
}
}
PS: All objects are injected with CDI, the manager is injected with the object class org.jboss.as.jpa.container.TransactionScopedEntityManager
As your CDI bean is an EJB stateless session bean, you don't have to use #Transactional annotation here since EJB have Container Managed Transaction (CMT) by default.
#Transactional is useful to manage transaction transaction on a CDI managed bean (i.e. POJO).

Unable to create Spring AOP aspect on Spring Data JPA Repository when CGLIB proxies are used

I'm trying to apply an aspect on a Spring Data JPA Repository and it works fine with default Spring AOP config
#EnableAspectJAutoProxy
(when Spring uses standard Java interface-based proxies).
However, when I switch to CGLIB proxies:
#EnableAspectJAutoProxy(proxyTargetClass = true)
I get this exception:
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy59]:
Looks like Spring tries to wrap a CGLIB proxy on a repository class, which is already a CGLIB proxy (generated by Spring Data) and fails.
Any ideas how to make it work?
My Spring Data Repository:
import org.springframework.data.jpa.repository.JpaRepository;
public interface DummyEntityRepository extends JpaRepository<DummyEntity, Integer> {
}
and the aspect:
#Aspect
public class DummyCrudRepositoryAspect {
#After("this(org.springframework.data.repository.CrudRepository)")
public void onCrud(JoinPoint pjp) {
System.out.println("I'm there!");
}
}

NPE when #Inject #Stateless service in a JAX-RS class in JBoss EAP 6.2

I've got that JAX-RS webservice:
#Path("/my")
public class MyWS {
#Inject
private MyService myService;
#POST
#Path("/save")
#Consumes("application/json")
public void save(SaveParam saveParam) {
myService.save(saveParam);
}
}
and that #Stateless service:
#Stateless
public class MyService {
#PersistenceContext
protected EntityManager entityManager;
#TransactionAttribute
public void save(SaveParam saveParam) {
entityManager.persist(saveParam);
}
}
Using JBoss EAP 6.2, myService is always null (not injected) when arriving in the save method.
I've tried to add #ApplicationScoped to MyWS class, but the same behavior is happening (NullPointerException). The only solution is to declare MyWS also as #Stateless, but that's not really have any sens, have it?
Is this a bug in JBoss EAP?
All my classes are in the same war project and I have a WEB-INF/beans.xml using CDI 1.0 spec. I also have a class extending javax.ws.rs.core.Application and declaring the #ApplicationPath.
I guess it is a bug if you configure your REST service in web.xml.
I have the same issue and i was getting crazy about this.
Just clean up the web.xml and it should not have anything related to REST.
#ApplicationPath is good enough for all REST setup.

Glassfish doesn't bring up EntityManager if DAO is not Stateless

I have an EAR application with an EJB module, that contains one persistence unit and many EJBs (as service and DAO layer).
#Stateless
public class BranchDAO {
#PersistenceContext
private EntityManager entityManager;
}
But DAOs as Stateless beans are not recommended. So I create this annotation using CDI:
#Dependent
#Stereotype
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface DAO {
}
After my DAO is changed to not use #Stateless:
#DAO
public class BranchDAO {
#PersistenceContext
private EntityManager entityManager;
}
But the Glassfish doesn't bring up the entity manager when the application starts. And when I call the DAO, the entity manager is in an illegal state.
java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
This error only occurs in Glassfish 3, but not in JBoss AS 6. Using JBoss AS 6 I can see the Hibernate logs in startup (but I don't see them with Glassfish).
As a temporary solution I created an Stateless bean with the content below. It's not beautiful solution, but works fine in Glassfish.
#Stateless
#Startup
public class AutoStartEntityManager {
#PersistenceContext
private EntityManager entityManager;
}
So, how I can force Glassfish to bring up EntityManager when I'm not using #Stateless in my DAO?
Try specifying explicitly the unitName:
#PersistenceContext(unitName="yourJPAUnitName")
private EntityManager manager;
(A sidenote - are you sure you need the DAO in dependent scope? Shouldn't it be singleton?)