Spring + EJB 3.1 CMT vs BMT transactions - java

We have a simple stateless EJB timer that gets an instance of a spring service injected into it. The spring service has a method marked as transactional. When the EJB uses Transaction Management Type CONTAINER the spring service call results in an IllegalStateException: Operation not allowed. So we set the EJB Transaction Management Type to be BEAN and everything works as advertised. Is this normal? I was under the impression that the spring transaction management would join the CMT.
example EJB
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
#Interceptors(SpringBeanAutowiringInterceptor.class
public class TimerService {
#Autowired
IHelloService helloService;
#Schedule(second="*/1", minute="*",hour="*", persistent=false)
public void doWork(){
helloService.hello();
}
}
example spring service
#Service
public class HelloService implements IHelloService {
#Transactional
public void hello(){
}
}

Probably the problem can be fixed, if you would define propagation level for Spring transaction as SUPPORTS (default is REQUIRED). I do not remember exact value for default settings in EJB, but it seems like EJB method is not starting transaction (propagation is DEFAULT), but 'hello' tries to do so and that is causing conflict.

Related

Jboss EAP 7 CDI JTA #Transactional

I am struggling to understand how I am supposed to deal with JTA and CDI running on a Jboss EAP 7 instance. I can get a transaction manually by injecting a UserTransaction object coming from the container but when I annotate the method with the #Transactional I get an exception regarding no transaction available.... My question is. Is there any config missing? I read briefly that maybe I should create an interceptor myself in order to make it work, but I haven't found any consistent example...
In a default JEE container-managed environment, only enterprise beans (usually #Stateless beans are used) are transactional. Once you enter such a bean from outside, the transaction will be opened. With the #javax.transaction.Transactional annotation you can control the behavior of the transactions, but this is not necessary in default case.
Example bean:
#Stateless
public MyBean {
public void withinTransaction() {
System.out.println("i'm running within a transaction");
}
#Transactional(TxType.NOT_SUPPORTED)
public void outsideTransaction() {
System.out.println("no transaction available...");
}
}
If you call MyBean.withinTransaction from a Servlet (e.g. via REST), a new transaction is created (if not already present).
If you call MyBean.outsideTransaction, no transaction will be created.
If you call this.outsideTransaction() from withinTransaction, you will still have the transaction available in outsideTransaction (because the interceptors are only bound to the bean boundaries)
If you call this.withinTransaction() from outsideTransaction no new transaction is created (because the interceptors are only bound to the bean boundaries)
If outsideTransaction would be part of a second bean AnotherBean, which #Injects MyBean, and you call MyBean.withinTransaction, then a new transaction will be created (if not already present). Because you cross bean boundaries between AnotherBean.outsideTransaction and MyBean.withinTransaction.

Migrating CDI/EJB annotations to Spring annotations

I'm trying to replace my CDI/EJB annotations with Spring ones. But I'm struggeling how to do it right.
This is what I have in CDI/EJB:
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
class Service {
#Inject
EntityManager em;
}
#Named
#RequestScoped
class Facade {
#Inject
Service service;
}
Now I would do the following:
#Stateless
#Transactional
#Repository
class Service {
#Inject
EntityManager em;
}
What about the stateless? What is the aquivalent in spring?
Obvious I cannot just remove this annotation, bc then I'm getting these exception:
javax.el.PropertyNotFoundException: /input.xhtml #15,30 registerButtonAction="#{facade.createNew()}": The class 'Facade$Proxy$_$$_WeldClientProxy' does not have the property ...
Further:
#Named
#Service
class Facade {
#Autowired
Service service;
}
Do I have to simply replace all #Inject annotations with #Autowired?
Is there something in Spring that takes care of EL naming, so that I can remove the #Named?
Do I have to annotate my JPA entities too?
Stateless and Stateful Beans are EJB concepts, but Spring offers similar services through Service Beans. Put the #Service annotation in your Business Logic classes, and if you want your beans to be "Stateless" or "Stateful" just configure your bean scope (like Request or Session).
Spring also has a built-in transaction management API, so your Transaction annotations may need to be changed.
Finally, Spring is compatible with many persistence frameworks including JPA. IF you want to keep JPA it is OK, and feel free to change it for another technology if you desire (maybe Hibernate, or MyBatis)
The stateless and stateful concepts are EJB; Spring doesn't have such a notion. Spring uses POJOs, without any support for stateful beans. You're on your own there.
Spring uses javax.annotation.Resource annotation; I'd prefer that to #Autowired.
Spring supports #Inject and #Named directly. No need to use #Autowired and #Component (Spring's equivalents) if you don't want to. No need to bring in #Resource either.
// This is a singleton by default, which is OK since you previously
// had it marked as stateless
#Named
#Transactional(propagation=Propagation.REQUIRES_NEW)
class Service {
#PersistenceContext // Use JPA's usual annotation
EntityManager em;
}
// You may not still need this, but if you do ...
#Named
#Scope("request")
class Facade {
#Inject
Service service;
}

Adding a dependency to an EJB

I want to add a dependency to an EJB. How do I do this using Spring? The dependent object is a general service object. Based on code below I want to wire myDependency without having to use 'new'.
The EJB runs in weblogic.
#Stateless(mappedName = "MyBean")
public class MyBean implements MyBeanRemote, MyBeanLocal {
#EJB(name = "MyOtherBean")
private MyOtherBean myOtherBean;
private MyDependency myDependency;
...
}
This is well described in the Spring documentation:
For EJB 3 Session Beans and Message-Driven Beans, Spring provides a
convenient interceptor that resolves Spring 2.5's #Autowired
annotation in the EJB component class:
org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.
This interceptor can be applied through an #Interceptors annotation in
the EJB component class, or through an interceptor-binding XML element
in the EJB deployment descriptor.
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
#Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}
Stateless EJBs and Spring beans, however, offer more or less the same possibilities. Mixing them together seems like unnecessary complexity.

CDI #TransactionAttribute for bean

I am experimenting with CDI on a test application. I have a DAO which injects a container managed JTA persistence context like this:
public class TestDAO implements Serializable {
#PersistenceContext
private EntityManager entityManager;
public void insertEntity(Test test) {
entityManager.persist(test);
}
}
Now I have a CDI controller bean like this:
#Named
#SessionScoped
public class TestController implements Serializable {
#Inject
private TestDAO testDAO;
public void finishGame() {
testDAO.insertEntity(new Test(1, 2, 3));
}
}
If I run this, I receive an error in the DAO when trying to insert the entity, because there is no active transaction available. So far so good. I can solve this by making the controller bean a stateful EJB which will wrap the finishGame() in a transaction.
But let assume I don't want an EJB. As a test I annotated the finishGame() with the #TransactionAttribute annotation and it worked(the controller bean is NOT an EJB). So my question is: how does it work? Does the CDI define #TransactionAttribute for plain beans? I know that Seam Persistence Module does this, but I am not using it. Actually I added it to the project, but I removed it after, because I received awkward exceptions.
Could anyone clear my confusion? Do really CDI define #TransactionAttribute for plain beans?
P.S. I have another sort of question. I see the tendencies is to port all EJB annotations to plain beans. So will EJBs become obsolete in the future? I mean I saw in JIRA that #TransactionAttribute will be added in the future for plain beans(the task is still not resolved). So isn't this eclipsing EJBs, sort of duplicating functionality?
Best regards,
Petar
You need do define a transaction interceptor. Basically define a #Transactional annotation and intercept all methods annotated with it. In the interceptor just begin, commit or rollback the transaction. It gets more complicated when transaction propagation comes into the picture. So check if Seam doesn't have anything ready-to-use http://seamframework.org/Seam3/PersistenceModule

How is threadsafty guranteed with #PersistenceContext?

According to many examples it is possible to inject an EntityManager into #Stateless or #Singleton EJBs like this:
#Stateless // or #Singleton
public class MyRepository {
#PersistenceContext
private EntityManager em;
...
}
The EJB 3.1 Spec says that dependency injection is only performed at construction time, so that all callers of MyRepository would use the same instance of EntityManager. How does the EJB container ensure that the correct EntityManager instance is used?
My understanding is that a #Stateless bean will never be used by two clients concurrently; the container will simply create more instances of the same bean if it needs to serve multiple clients.
As for #Singleton beans, the spec says that by default they use Container Managed Concurrency, where the container uses method Locks and could reject clients with a timeout exception if the singleton is busy.
Edit: additionally, the #PersistentContext type is transaction-scoped by default (16.11.1.1 in the spec) so all entities managed by EntityManager are detached at the end of each transaction.

Categories

Resources