Hot questions for Using Enterprise JavaBeans in architecture

Question:

Supposing a classical 3-tier JavaEE architecture like this

  • JSF / JSP / Servlets (Web)
  • EJB (Biz)
  • DB (Persistence)

All JavaEE tutorial examples show the web and biz layers in different containers, but in the same JavaEE server.

Is there any situation where there is an advantage to keep the EJBs apart, in their own machine? In this case, supposing they're going to communicate with the web tier via RMI, is there any kind of JavaEE container that manages EJBs but not JSP and servlets?


Answer:

Is there any situation where there is an advantage to keep the EJBs apart, in their own machine?

Sometimes, specifics non-functional requirements can determine your app design. For example, security: in order to achieve some security norms, the business layer has to reside in a more secure server not exposed directly to Internet.

Availability: if your business layer exposes some services consumed by a different client than the web server, and these services offer some kind of mission-critical functionality, probably they need to run on a 24/7 server.

I'm not sure that think in terms of "advantage" is the correct way to see this kind of decoupled architecture. I think that is more like a price (which is translated in a more complex design) that you have to pay if you need achieve this kind of requirements.

is there any kind of JavaEE container that manages EJBs but not JSP and servlets?

Yes, for example OpenEjb.

Question:

I’d like a controller that is able to seamlessy access the persistence layer and EJB is a nice technology for this purpose. I can do something like this:

@PersistenceContext
EntityManager em;

...    

Cat timmy = em.findById(Cat.class, "Timmy");
timmy.color = "red";

And it feels like timmy is in-memory. The sad part is that this has to be done at business level because beans are only at business level. However transactions should be defined at client level in the MVP. That’s why I would like to have a Presenter that is a @Stateful bean. This way I can start and end transactions at client level. Anyways I have this strange feeling that @Stateful bean are evil and I’d rather not use them.


Answer:

is that:

@PersistenceContext
EntityManager em;

...

Cat timmy = em.findById(Cat.class, "Timmy");
timmy.setColor("red");
em.merge(timmy);

working?

in term of architecture I use @Stateless Dao

@Stateless
public class CatDao extends Dao<Cat> {
    public CatDao () {
        super(Cat.class);
    }
}

public class Dao<E> {

    @PersistenceContext(unitName = "myappPU")
    private EntityManager em;

    private final Class<E> entityClass;

    protected Dao(Class<E> entityClass) {
        this.entityClass = entityClass;
    }

    public E find(Object id) {
        return em.find(entityClass, id);
    }

    public List<E> findAll() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        Query q = entityManager.createQuery(cq) ;
        return q.getResultList();
    }

    public void create(E entity) {
        em.persist(entity);
    }

    public void edit(E entity) {
        em.merge(entity);
    }

    public void remove(E entity) {
        em.remove(entityManager.merge(entity));
    }
}

so in the controller I do

    @Inject
    private CatDao dao;

    //...

    Cat cat = dao.find("Timmy");
    cat.setColor("red");
    dao.edit(cat);

see... statless

Netbeans generate this Dao automatically but called them Facade (new>Other>Entreprise JavaBeans>session beans for entity classes)

Question:

Consider the problem of entities that need to read some database configuration in order set some values : for example :

@entity
public class person{
int age,
String ageCategory;
}

ageCategory will be fetched from the database when age is set. my question what is the best EJB architecture to use in order to read AgeCategoryConfiguration from the databse. currently i am using jndi to inject the AgeCategoryFacade which provide a method to get AgeCategory from age, this method is called in the age setter.

is there a better approach.


Answer:

Maybe you want to look at jpa Events .

You stated that ageCategory will be fetched from the database when age is set this and i think this statement fits @PostLoad annotation.

If you want to know more read this nice article. And usually you should not need jndi paths while injecting ejbs.

Edit I would keep things as simple as possible.

So you should have some bean which is used in JSF with method for updating person:

@Named
@SessionScoped
public class PersonController {

    @Inject
    private PersonService personService;

    private Person selectedPerson;

    /**
     * Method for updating.
     */
    public void updatePerson(ActionEvent actionEvent){
        Person updatedPerson = personService.update(selectedUser);
        // pass updatedPerson to presentation layer..
    }
}

Next you should have PersonService which takes care of Person's CRUD operations:

@Stateless
@LocalBean
public class PersonService {

    @PersistenceContext
    private EntityManager em;

    @Inject
    private AgeCategoryFacade ageCategoryFacade;

    public Person updatePerson(Person person) {
         // use ageCategoryFacade somehow to set ageCategory for example:
         String ageCategory = ageCategoryFacade.getAgeCategory(person.getAge());
         person.setAgeCategory(ageCategory);
         return (Person) em.merge(person);
    }
}

Note that you can use ageCategoryFacade also in other methods like createPerson, findPerson.

Solution with JPA events involves PostLoad(or PrePersist) method in entity Bean:

@Entity
public class Person {
    int age;
    String ageCategory;

    /**
     * Simple setting of ageCategory.
     */
    @PostLoad
    public void postLoadPerson {
        if(age < 10) {
            setAgeCategory("A");
        } else if (age < 30) {
            setAgeCategory("B");
        } else {
            setAgeCategory("C");
        }
    }
}

Question:

A well known constraint is that you should not use java.io in EJB's to access the file system. I need to create a text file and send it via email when a particular method is invoked in my ejb application.

I need an architectural solution on how to do this without using java.io. The only approach I see is to create a separate web service for this job. Also there was a suggestion to use Apache camel, but I don't know how camel can help to achieve this.


Answer:

We found a way to avoid using the file system from ejb's by creating the files as ByteOutputStream in memory and sending them via email. This way we don't need to use the file system. Similar example: Create a Zip File in Memory

Question:

We are a complete SOA workshop(Java only) and we use SOAP for the data transfer. Currently we are in a process of centralizing the database work for a specific component so the other components can fetch data from one application using SOAP.

My argument is that it is good to centralize but it adds a lot of latency when adding soap between database calls. I want a RMI/EJB type of implementation so we get serialized object and it reduces the marshaling overhead. I like the way the Ejbs are implemented and would like to use it. But the data that we return is not at all from one table, so, I cannot return a database table entity, the data might be from 20 other tables or more.

So, in our current system we have custom entities which are created to map to heavy sql queries. (not related to one table)

Can ejbs be used for this type of environment? If so, are there libraries that are readily available to map the result of a query to entities?

Unfortunately our in-house system is very old, we use java 1.4.


Answer:

This can be done, but it is going to be painful. There was a reason EJB 3.0 entity beans were created. It's because dealing with these sorts of complex requirements is really quite difficult to map via the old 2.x entity beans xml files.

If you are really building a new SOA layer to represent your database content, why would you do this with a technology that has been obsolete for almost 10 years?

Worse, building this with EJB 2.x and then using RMI/EJB will bind all of your other applications to this same outdated technology. Very few people would choose to start a new EJB 2.1 project.

I honestly believe that you are better off using SOAP for your service instead of EJB, at least it won't couple you to an obsolete platform. Current best practices prefer REST for entity transfer, and save SOAP for things RPC-style interactions, but there are lots of good libraries for doing your database tables to SOAP mappings, many of which are out-of-the-box for RDMS's.

Finally, if you are determined to do this, I'd suggest you first do a test. Build a test framework to actually see if the SOAP deserialization is a significant cost component. Compare it to the cost of the network transport. Unless these entities are in the megabyte range, deserialization will be a tiny fraction of your overall application time.

Question:

I am new to Java EE. I have read some about web containers and ejb containers, but I do not understand if both logical layer and data persistence layer run in the ejb container or just the logical layer runs there. Could someone explain it to me?


Answer:

EJB container manages different EJB components. EJB components are "logical" components like session beans, persistence units, servlets, etc. So all of them managed by EJB container.