How is threadsafty guranteed with #PersistenceContext? - java

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.

Related

Is it safe to inject #Resource UserTransaction to EJB Singleton bean

Q1:
I am writing an EJB Singleton bean that use BMT so I need to use UserTransaction in my bean. I was wondering that IS IT SAFE to inject #Resource UserTransaction to my EJB singleton bean. I don't know whether container will inject a Proxy of UserTransaction or NOT. Can someone give me some ideas? Thank you!
Q2:
What are difference between #Resource UserTransaction and sessionContext.getUserTransaction(). Are they equivalent?
I was wondering that IS IT SAFE to inject #Resource UserTransaction to my EJB singleton bean.
A Singleton session bean is one of the three beans defined in the ejb3.1 specification: Stateless, Stateful and Singleton.
Therefore, with Singleton, the Container must follow the same contract as other session beans.
The contract says:
4.3.3 The SessionContext Interface.
If the bean specifies a dependency on the SessionContext interface.., the container must provide the session
bean instance with a SessionContext. This gives the session bean instance access to the instance’s context maintained by the container.
.
What are difference between #Resource UserTransaction and sessionContext.getUserTransaction(). Are they equivalent?
Yes, they are. This what the specification says:
4.3.2 Dependency Injection.
Under the EJB 3.1 API, the bean class may acquire the SessionContext interface through dependency injection without having to implement the SessionBean interface. In this case,the Resource annotation (or resource-env-ref deployment descriptor element) is used to denote the bean’s dependency on the SessionContext.
Maybe your doubts comes from the fact that the same Singleton instance can be shared by several simultaneous threads,
which will share the same SessionContext instance. However. this shouldn't be a problem.
I use the conditional form because I have not tried it, but beyond the thread-safe related topic that can arise, take a look to the table on page 117
where explicitly is indicated that the use of UserTransaction method must be supported
Table 3
Operations Allowed in the Methods of a Singleton Session Bean:
Bean-managed transaction demarcation:
SessionContext methods: UserTransaction methods

How to access stateful session bean through remote interface proxy?

I have a testcase which makes use of OpenEjb's #LocalClient annotation (embedded container) and injects EJBs using the #EJB annotation:
#LocalClient
public class MyTestCase {
#EJB
private BoxDao boxDao;
...
}
BoxDao is a remote EJB interface. Now, for testing, I need to access some internal state of BoxDao's implementation BoxDaoBean, which is a stateful session bean. I created a protected method in BoxDaoBean, which exposes the needed internal state, but I found not yet a way to access it in my test case, since the injected BoxDao is a remote interface proxy (an cannot be cast to BoxDaoBean).
Is there a way to access the stateful session bean behind the remote interface BoxDao in the test case? Would not matter if solution is OpenEjb specific.
Update: We can't use EJB 3.1 specific solutions unfortunately, as we have several EJB 3.0 projects running. Using Proxy.getInvocationHandler(boxDao), I can get access to the OpenEjb container, via StatefulEjbObjectHandler. Is it possible to access the stateful bean this way?
You could try having BoxDaoBean also expose an #LocalBean interface. A single EJB can expose a near unlimited number of views from #WebService, #Local, #Remote, JAX-RS and more.
Just update your bean like so:
#Stateful
#LocalBean
public class BoxDaoBean implements BoxDao {
//...
}
Then add another field to your test:
#LocalClient
public class MyTestCase {
#EJB
private BoxDao boxDao;
#EJB
private BoxDaoBean boxDaoBean;
...
}

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;
}

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

Meaning of #PersistenceContext in JSF 1.2 Managed Beans

JSF 1.2 specification allows injection of an entity manager into a managed bean via the #PersistenceContext annotation (JSR 252, p. 5-13).
What is the semantics of such an entity manager regarding transactions and lifecycle?
Is an EAR-scoped JTA-style persistence unit supposed to work here?
#Stateless
public class YourServiceBean implements YourService {
#PersistenceContext(unitName="YourServicePU")
EntityManager em;
// ...
}
This will inject an EntityManager instance that you do not have to dispose of (the container takes care of it) and is supposed to play nice with container-managed transactions.

Categories

Resources