Hot questions for Using Enterprise JavaBeans in java ee 7

Question:

Is it acceptable to use types from the java.io and java.nio packages to access the file system and manipulate files in EJB?


Answer:

No, you are not allowed to do that because if the application will be clustered at some point, you never know to what location has your files been saved. So file manipulation in Java EE environment is rather unsafe operation.

The way to do this safely would be probably to have service in JNDI which will take care about your object serialization - see example

ByteArrayOutputStream baos= new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(myObj);

new InitialContext().bind("path/to/FileManipulator", baos.toByteArray());

See also this answer for further explanation. Also here is an article which describes what specification says about using java.io in EJB.

Question:

Can anyone explain me the difference between Enterprise Java Beans and Entity Java Bean?

I know what EJB is but I don't understand their difference in regard to persistence.

We use the same annotations to save it, but then why call it different?


Answer:

In the old days, as the earth was forming, Java EE had two basic kinds of Beans -- the Session Bean, and the Entity Bean.

The Session Bean is an interface to some kind of internal service. Most every framework has some basic parallel to an Session Bean.

The Entity Bean was a persistent element managed by the container.

When people talk about Java EE, and especially when they gripe about it, Entity Beans were a core problem. They simply weren't very good.

With the introduction of the Java Persistence Architecture (JPA), with frameworks like Hibernate and EclipseLink, the Java EE view of managed persistence pivoted dramatically. No longer did we have "heavyweight" constructs such as Entity Beans, but rather light weight POJOs managed by the JPA.

The confusion, however, is that objects that are managed by the JPA are referred to as Entities. A JPA Entity and an EJB Entity Bean are completely different animals. But the reuse of the term is a source of confusion.

With an EJB Entity Bean, and EJB and an Entity are the same thing. A Entity EJB IS an EJB, like a Session Bean.

A JPA Entity, however, is not. Technically, an Entity is not related to EJB at all. The JPA Entity Manager is integrated within the EJB runtime context (and by projection, any Entity managed by that Entity Manager is part of the EJB runtime context), but there's no requirement for JPA to be used within an EJB container. They're separate technologies. That said, they do work quite well within an EJB container.

So.

Today, Entity EJBs still exist, but are deprecated, and will some day go away. But the containers still support them. There is no reason to pay them any mind whatsoever unless you have some blob of legacy code. Excluding the Entity Bean, Java EE supports: Stateless Session Beans, Stateful Session Beans, and Message Driven Beans. These are all first class EJBs which represent the heart of the Java EE component model. The most notable aspect of an EJB at runtime is how they engage with the local transaction space managed within the container. Also, EJBs are a deployable construct within the EJB container, similar to a WAR. (They are also other things, this is hardly exhaustive.)

JPA Entities are not EJBs. They have no transactional context. They have a different state, as to whether they are actively managed or not by their Entity Manager. The Entity Manager is enrolled in the local transaction space (and thus the JPA managed Entities are as well, by proxy).

Finally, with CDI, and the rise of annotations, the embedding of EJBs directly within WARs, the boundaries that distinguish EJBs themselves are getting fuzzier and fuzzier every day.

Question:

I am using Wildfly 10.1.0 and I am trying to change all the EJB's to only use @Transactional annotations, which are provided since Jave EE 7 (because of JTA 1.2). The thing is when my project has 0 EJB's, the PersistenceUnit is not started by the container. If I add an empty class with only the annotation @Stateless then it works again.

This is my persistence.xml

<persistence version="2.1">
  <persistence-unit name="Storage-PU" transaction-type="JTA">
    <jta-data-source>java:/PostGreDS</jta-data-source>
    <class>SomeEntity<class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
  </persistence-unit>
</persistence>

What is the reason why the PersistenceUnit is not started, when there are no EJB's available?


Answer:

What is the reason why the PersistenceUnit is not started, when there are no EJB's available?

The reason is that in a JEE application the Persistence Context (including DB connection, Persistence Units and stuff) is started and managed by the EJB container:

So, just annotating beans methods at the Web tier with @Transactional is not enough to get Persistence Context started. Beware that transactions are also managed by the EJB container, not the Web Container.

See Java Platform, Enterprise Edition: The Java EE Tutorial for further details on JEE architecture.

Question:

I have a task which consists of 3 steps prepare, execute, update. prepare and update need to work within a transaction, whereas execute takes very long (i.e. several minutes up to hours). The task is part of an EJB, i.e.:

@Stateless
public class Task {
    public void doTask() {
        prepare();
        execute();
        update();
    }
}

My question is, is there an (elegant) way to commit and finish the transaction after prepare and start a new one before update? I'd rather use container-managed transactions and possibly not switch to use UserTransaction.

It is possible to split the tasks into single EJBs if it gains any advantage, but note that suspending the transaction for execute (i.e. using @Transactional(TxType.NOT_SUPPORTED) is not enough since this still triggers the timeout.

I tried to split it into a TaskExecute class which has @Asynchronous @Transactional(NOT_SUPPORTED) public void execute() and sending an event when done. But this doesn't seem to work either.

Is there a way to do this?


After some further testing let me conclude: Alexanders reply was absolutely correct. My understanding had to be altered. Foremost, I wasn't aware that @Transactional does not work on EJBs, but only on CDI beans. For EJBs the annotation is called @TransactionAttribute and can be set to basically the same values. A combination of @Asynchronous and @TransactionAttribute(NOT_SUPPORTED) does work (if not waiting for the result).


Answer:

It depends on the version of Java EE you want to use. Here are three possible solutions.

  • use JMS, send an appropriate message and do the execute in the MDB (any version, but full profile required)
  • use Java EE 6.0's Timer Service and schedule a task to perform the execute asynchronously (@Timeout)
  • use Java EE 7.0's Batch Processing API to schedule a proper long running batch job.

The latter is probably what you are looking for, but only available in Java EE 7.0 and up. Otherwise, the JMS solutions is the cleanest, but if JMS is not an option, the Timer Service should work.

Question:

I'm using a Java EE 7 + GlassFish and need to perform some operation against a number of JPA entities from a stateless bean.

@Stateless
public class JobRunner 
{
    public void do()
    {
            for (Entity entity:facade.findAll()) 
            {
                ///do some work against entity
            }
    }
}

This JobRunner bean is injected into the servlet and I invoke do() method from the web UI.

The issue is that all entities are being changed within one transaction so if one fails everything is rolled back what is not desirable. Is there a way to start and close a new transaction for each entity (i.e. for each iteration of the loop)?

I can write an external client and make a loop there calling a stateless bean for each entity but it's not something that completely works for me as I prefer to keep an app monolithic. Can I somehow manage transactions form inside a container?

Maybe JMS helps? If I implement a doer as message listener and will be sending a message for each entity, will it start a new transaction for each one?

@Stateless
public class JobRunner 
{
    public void do()
    {
            for (Entity entity:facade.findAll()) 
            {
                sendMessageToRealDoer(entity);
            }
    }
}

Answer:

Create another bean, specifying @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW), at method or bean level:

import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

@Stateless
public class JobWork {
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void doWork(Entity entity) {
        // do what you would do in the loop with the Entity
        // this runs in a new transaction
    }
}

I wish I could tell you that you only need to annotate a method of the same bean (JobRunner) and simply call it. This is not possible (EDIT)without workarounds - check comment from Steve C(/EDIT) because when calling methods of this object in EJBs and CDI beans the interceptors do not get called. Transactions are implemented with interceptors in both cases.

Some notes:

  • If the total duration of the operations in the loop is expected to be long, you will get a timeout in the outer transaction, that is implicitly started for the JobRunner stateless EJB. You will want to take measure that no "outer" transaction is started.
  • Sending the data to a queue will work too; but queues will process them asynchronously, meaning that the execution will return to the servlet calling JobRunner.do() most probably before all items have been processed.