CDI bean producer inside EJB stateless session bean - java

Let's suppose I have a simple lib named db-utils, which has a CrudService CDI bean (requestScoped) that's used by my web applications to perform CRUD operations.
I also have an EJB project named grad-db, which has the entities mapped from database. Grad-db also has the producer used to set the entityManager in db-utils' CrudService.
I already tried it and apparently it works fine. My question is: is that a bad practice? Is there any consequence of producing a CDI bean inside a stateless session bean and passing the EJB stateless bean as a parameter to the CrudService?
My code:
EJB Bean (grad-db):
#Stateless
public class CrudServiceCae extends AbstractCrud implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName = "cae-pu")
EntityManager em;
#Override
public EntityManager getEntityManager() {
return em;
}
#Produces
#Database(Schema.CAE)
public CrudService createCrudServiceCou() {
return new CrudService(this);
}
}
CrudService (db-utils):
#Named("crudService")
public class CrudService implements Serializable {
private static final long serialVersionUID = -2607003150201349553L;
private AbstractCrud crud;
public CrudService(AbstractCrud abstractCrud) {
this.crud = abstractCrud;
}
...
}
Edit:
Actually it worked only for queries. When I tried to insert data I got javax.persistence.TransactionRequiredException. Apparently I'm going to have to use inheritance instead of CDI in this case.

The EJBs are responsable for business processes/logic (i.e: methods), and are able to orchestrating others CDI controllers, is not so common let the EJB create objects, for that you would prefer a CDI POJO Producer.
In your case is leaner to use a CDI object and produce the object that you need from there, looks like a DAO and could be used (i mean, injected) into the EJB.
Think of EJBs on terms of a Boundary Pattern, using specialized controllers.
Notes:
#Stateless is not required to implements Serializable, these are pooled, and its lifecycle does not allow serialization.
In general you dont want to use a getter to the entity manager of an EJB, you should prefer write a method and use the em internally.
The persistence context is easier to manipulate if uses JTA
Your #Stateless should begins the transactions and let them propagated along the controllers
The em with package visibility is a good idea, lets you mock your facade / boundary easily

Related

CDI Injection and JPA EntityManager

I am seeing two classes:
/**
* This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans
*
*/
public class Resources {
#Produces
#PersistenceContext
private EntityManager em;
#Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
#Produces
#RequestScoped
public FacesContext produceFacesContext() {
return FacesContext.getCurrentInstance();
}
}
and
// The #Stateless annotation eliminates the need for manual transaction demarcation
#Stateless
public class MemberRegistration {
#Inject
private Logger log;
#Inject
private EntityManager em;
#Inject
private Event<Member> memberEventSrc;
public void register(Member member) throws Exception {
log.info("Registering " + member.getName());
em.persist(member);
memberEventSrc.fire(member);
}
}
I have 2 questions on this:
1) MemberRegistration can inject "log" and "em" directly, is that because the Resources already define them by using #Produces annotation? Without the Resources class, would the MemberRegistration class still work? I am trying to understand whether or how the two classes are related, and how the CDI works.
2) In MemberRegistration's register method, there is only a "em.persist()" method used. A complete flow of using EntityManager looks like the following. In the example application, I didn't see methods "commit()" and "close()" are used. So how the transaction is committed and closed?
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( SomeObject );
entityManager.getTransaction().commit();
entityManager.close();
Answering your questions:
1) MemberRegistration can inject "log" and "em" directly, is that because the Resources already define them by using #Produces annotation?
Yes. #Inject will work only for types that are known to CDI (are discovered via class-path scanning or declared manually via #Produces). So without your Resources class, which defines EntityManager and Logger as a CDI managed beans, injection via #Inject would not work.
BTW. For details you can read cdi-spec-1.2 - PDF version is 170 pages long, not that big, but also not so short.
2) So how the transaction is committed and closed?
... you even have a valid comment in your code: the #Stateless annotation eliminates the need for manual transaction demarcation. For details read something about CMT transactions in EJB.
Honestly, I agree with #JBNizet. It is disappointing to see you asking such questions (especially the first one) which can be answered immediately by yourself with just a quick test.

Getting a reference to EntityManager in Java EE applications using CDI

I'm using Java EE 7. I would like to know what is the proper way to inject a JPA EntityManager into an application scoped CDI bean. You can't just inject it using #PersistanceContext annotation, because EntityManager instances are not thread safe. Let's assume that we want our EntityManager to be created at the beginnig of every HTTP request processing and closed after the HTTP request is processed. Two options come into my mind:
1.
Create a request scoped CDI bean which has a reference to an EntityManager and then inject the bean into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#RequestScoped
public class RequestScopedBean {
#PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class ApplicationScopedBean {
#Inject
private RequestScopedBean requestScopedBean;
public void persistEntity(Object entity) {
requestScopedBean.getEntityManager().persist(entity);
}
}
In this example an EntityManager will be created when the RequestScopedBean is created, and will be closed when the RequestScopedBean is destroyed. Now I could move the injection to some abstract class to remove it from the ApplicationScopedBean.
2.
Create a producer that produces instances of EntityManager, and then inject the EntityManager instance into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class EntityManagerProducer {
#PersistenceContext
#Produces
#RequestScoped
private EntityManager entityManager;
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
#ApplicationScoped
public class ApplicationScopedBean {
#Inject
private EntityManager entityManager;
public void persistEntity(Object entity) {
entityManager.persist(entity);
}
}
In this example we will also have an EntityManager which is created every HTTP request, but what about closing the EntityManager? Will it also be closed after the HTTP request is processed? I know that the #PersistanceContext annotation injects container-managed EntityManager. This means that an EntityManager will be closed when a client bean is destroyed. What is a client bean in this situation? Is it the ApplicationScopedBean, which will never be destroyed until the application stops, or is it the EntityManagerProducer? Any advices?
I know I could use a stateless EJB instead of application scoped bean and then just inject EntityManager by #PersistanceContext annotation, but that's not the point :)
You're almost right on with your CDI producer. Only thing is that you should use a producer method instead of a producer field.
If you're using Weld as CDI container (GlassFish 4.1 and WildFly 8.2.0), then your example of combining #Produces, #PersistenceContext and #RequestScoped on a producer field should throw this exception during deployment:
org.jboss.weld.exceptions.DefinitionException: WELD-001502:
Resource producer field [Resource Producer Field [EntityManager] with
qualifiers [#Any #Default] declared as [[BackedAnnotatedField]
#Produces #RequestScoped #PersistenceContext
com.somepackage.EntityManagerProducer.entityManager]] must be
#Dependent scoped
Turns out that the container is not required to support any other scope than #Dependent when using a producer field to lookup Java EE resources.
CDI 1.2, section 3.7. Resources:
The container is not required to support resources with scope other
than #Dependent. Portable applications should not define resources
with any scope other than #Dependent.
This quote was all about producer fields. Using a producer method to lookup a resource is totally legit:
public class EntityManagerProducer {
#PersistenceContext
private EntityManager em;
#Produces
#RequestScoped
public EntityManager getEntityManager() {
return em;
}
}
First, the container will instantiate the producer and a container-managed entity manager reference will be injected into the em field. Then the container will call your producer method and wrap what he returns in a request scoped CDI proxy. This CDI proxy is what your client code get when using #Inject. Because the producer class is #Dependent (default), the underlying container-managed entity manager reference will not be shared by any other CDI proxies produced. Every time another request want the entity manager, a new instance of the producer class will be instantiated and a new entity manager reference will be injected into the producer which in turn is wrapped in a new CDI proxy.
To be technically correct, the underlying and unnamed container who do the resource injection into the field em is allowed to reuse old entity managers (see footnote in JPA 2.1 specification, section "7.9.1 Container Responsibilities", page 357). But so far, we honor the programming model required by JPA.
In the preceding example, it would not matter if you mark EntityManagerProducer #Dependent or #RequestScoped. Using #Dependent is semantically more correct. But if you put a wider scope than request scope on the producer class you risk exposing the underlying entity manager reference to many threads which we both know is not a good thing to do. The underlying entity manager implementation is probably a thread-local object, but portable applications cannot rely on implementation details.
CDI does not know how to close whatever stuff it is that you put into the request bound context. More so than anything else, a container-managed entity manager must not be closed by application code.
JPA 2.1, section "7.9.1 Container Responsibilities":
The container must throw the IllegalStateException if the application
calls EntityManager.close on a container-managed entity manager.
Unfortunately, many people do use a #Disposes method to close the container-managed entity manager. Who can blame them when the official Java EE 7 tutorial provided by Oracle as well as the CDI specification itself use a disposer to close a container-managed entity manager. This is simply wrong and the call to EntityManager.close() will throw a IllegalStateException no matter where you put that call, in a disposer method or somewhere else. The Oracle example is the biggest sinner of the two by declaring the producer class to be a #javax.inject.Singleton. As we learned, this risk exposing the underlying entity manager reference to many different threads.
It has been proven here that by using CDI producers and disposers wrongfully, 1) the not thread-safe entity manager may be leaked to many threads and 2) the disposer has no effect; leaving the entity manager open. What happened was the IllegalStateException which the container swallowed leaving no trace of it (a mysterious log entry is made which says there was an "error destroying an instance").
Generally, using CDI to lookup container-managed entity managers is not a good idea. The application is most likely better off just using #PersistenceContext and be happy with it. But there are always exceptions to the rule like in your example, and CDI can also be useful to abstract away the EntityManagerFactory when handling the life cycle of application-managed entity managers.
To get a complete picture on how to obtain a container-managed entity manager and how to use CDI to lookup entity managers, you might want to read this and this.
I understand your problem. but that is not a real one. Do not get messed up with the CDI declared scope of a containing class, that will propagate the scope of the attributes expect those that use #Inject'ion!
The #Inject'ed will compute their reference in depencency of the CDI-declaration of the implementation class. So you might have Applicationscoped class with a #Inject EntityManager em inside, but each controlflow will find its own em-transaction reference to a disjount em-object, because of the EntityManager CDI declaration of the implementation class behind.
The wrong thing of your code is, that you provide an inner getEntityManager() access method. Do not pass Injected object, if you need one, simply #Inject it .
You should use the #Dispose annotation to close the EntityManager, as in the example below:
#ApplicationScoped
public class Resources {
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
#Produces
#Default
#RequestScoped
public EntityManager create() {
return this.entityManagerFactory.createEntityManager();
}
public void dispose(#Disposes #Default EntityManager entityManager) {
if (entityManager.isOpen()) {
entityManager.close();
}
}
}
You may inject savely EntityManagerFactory, it is thread save
#PersistenceUnit(unitName = "myUnit")
private EntityManagerFactory entityManagerFactory;
then you can retrive EntityManager from entityManagerFactory.

#EJB workflowDao is null in service layer

I'm trying to figure out how to setup a Service/Dao layer in my application. I've found a few dozen resources all with different ways on how to do it and decided to follow the model found here: How should EntityManager be used in a nicely decoupled service layer and data access layer?
I can't figure out what I'm missing that's causing this NPE.
Usage:
#Path("/helloworld")
public class MyController {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
My Dao:
#Stateless
public class WorkflowDao {
#PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
My Service:
#Stateless
public class WorkflowService {
#EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
This is my first time setting up a Java project (only have worked on 1 before and it used Spring) so please keep that in mind if this looks horribly wrong.
WorkflowDao is not an EJB, it's a POJO with a#Stateless annotation. So naturally, injecting it with #EJB fails, creating a null workflowDao attribute and eventually producing a NullPointerException.
To make WorkflowDao into a full-fledged EJB, besides having a #Stateless or #Stateful annotation it needs to implement a local, remote or both interfaces, and those interfaces must be annotated respectively with #Local and #Remote. Please refer to the tutorial for details.
Also, quite possibly (this can be application server-dependent) you'll have to register the EJB in the application's xml descriptor files - for instance, in web.xml's <ejb-local-ref> element.
As a side note - it's not a good idea to use an EJB as a DAO, an EJB is typically used for implementing business logic (true, persist/merge operations can be called from here) but the actual persistence layer nowadays is implemented using JPA. In other words, WorkflowService should be the EJB service, there's no need to inject an EJB into it, and there's no need for a separate DAO layer - JPA entities fulfill this role.
If you instantiate your WorkflowService manually, the container wont perform any injection, since your WorkflowService is not managed by the Container.
I suggest you:
Annotate your Jax-RS Resource #Stateless
Inject your WorkfloService via #EJB as a member
Implementing a Local or Remote Interface is not necessary anymore
#Path("workflows")
#Stateless
public class WorkFlowResource{
#EJB
WorkflowService workflowService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}

Best way to interact with EJBs in Java EE

I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.

Seam-managed transactions how-to

Seam advises using an Extended persistent context in a Stateful Session Bean, in order to have Seam-managed persistence.
I am not clear on whether the above advice casts any implications on the way we want to have Seam-managed transactions. This is because our architecture is different. We have the following persistence context in a Stateless EJB:
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class CrudServiceBean implements CrudService {
#PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager em;
...
}
Our DAOs invoke the above CrudServiceBean are Stateless EJBs (some of them are also Seam components) with #TransactionAttribute(TransactionAttributeType.REQUIRED). So, our transactions are handled by the container (WebLogic) and not Seam.
However, we now need to satisfy the following scenario: We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction. If I understand correctly, we need to have Seam-managed transactions.
Can we have Seam-managed transactions as in the scenario I described, without having a Seam-managed persistence context? Or are the two irrelevant?
As said
We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction
But
Our transactions are handled by the container - Also called Container Managed Transaction (The container Takes care of calling begin and commit method used by each underlying resource-manager Transaction)
The first issue is that you have a scenario where a non-EJB invokes multiple DAOs, each one an EJB. You could think of
#Name("nonEjbComponent")
public class NonEjbComponent {
private #In DaoEjbComponent daoEjbComponent;
private #In OtherDaoEjbComponent otherDaoEjbComponent;
private #In AnotherDaoEjbComponent anotherDaoEjbComponent;
private #In UserTransaction userTransation;
public void wrapperAllOfThem() {
userTransation.begin();
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
userTransation.commit();
}
}
But the Java EE specification 3.0 states
The enterprise bean with Either bean-managed or container-managed transaction demarcation must be a session bean or a message-driven bean.
So you can not use the scenario above. And because all of your DAOs are using container-managed transactions, the Java EE specification does not allow you to use container-managed and bean-managed Transaction at the same time
So the solution is
Wrap all of the DAOs in an EJB Stateless session bean whose transaction is container-managed. It will behave like a delegate component
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
#Name("wrapperStateless")
public class WrapperStatelessImpl implements WrapperStateless {
private #In DaoEjbComponent daoEjbComponent;
private #In OtherDaoEjbComponent otherDaoEjbComponent;
private #In AnotherDaoEjbComponent anotherDaoEjbComponent;
public void wrapperAllOfThem() {
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
}
}
And inside your non-EJB component, use
#Name("nonEjbComponent")
public class NonEjbComponent {
private #In WrapperStateless wrapperStateless;
public void wrapperAllOfThem() {
wrapperStateless.wrapperAllOfThem();
}
}

Categories