Creating our first Entity and EJB in JavaEE
Let’s start this post off by briefly explaining what entities and EJBs are. An entity is an object that represents a table and an instance of an entity represents a row within that table. For example, an entity could be a book, a person, or something to do. Since entities tend to be unique, they have something called a “primary key”. Usually, this primary key is represented by a number and is assigned when the entity is persisted to the data source. In other cases, the primary key could be something entirely different.
An EJB, or Enterprise Java bean, is a Java class that is managed by the JavaEE server. You won’t create instances of it nor will you need to worry about setting up references to other parts of the system. You just need to inject what you need and the JavaEE server will set it up for you. This makes EJBs easy to use and very easy to test as well.
In a previous post we created a DTO, or “data transfer object” called Todo.java. This object represents the data that is fed to our application code from the client. We’re going to convert this class into a dual-purpose class. It will be both our entity and our DTO. In complex applications, you will want to keep this functionality separate.
Open Todo.java and change the start of the class to:
@Entity public class Todo implements Serializable { @Id @GeneratedValue private Long id; @Column private String description;
The @Entity annotation indicates this class is now an entity.
We also have to describe our fields to the JavaEE server so it knows what to do with them. Our “id” field is to be the primary key and managed by the data source. Using the @Id annotation indicates the following property will be the primary key. The @GeneratedValue annotation indicates the value will be managed automatically by the datasource.
The @Column annotation indicates the following property is data that should be persisted to the data source.
We add the “implements Serializable” statement since we’ll be passing this object from the service layer to the EJB layer. These are two separate systems within the JavaEE container and the class needs to be able to move between them. Without this, the class will not able to do this and will result in a serialization error.
There are several types of EJBs: Stateless, Stateful, and Singleton. When your application starts up the JavaEE server will create a “pool” of instances for each of your EJBs. When the EJBs are injected, it will pull from this pool. Stateless EJBs are not tied to the class where it is injected. Most often this is what you will use. Stateful EJBs are tied to the class instance where it is injected. Meaning that it is guaranteed that it will always have the same instance of the EJB. This allows the two classes to pass and maintain data state with one another. Singleton EJBs mean there will only ever be a single instance of that EJB and that instance will be shared everywhere it is injected.
Because EJBs are a different system within the JavaEE server, the service layer needs to know about what functions are available to it. We do this by creating a local interface. Let’s create a new class called “TodoEJB.java”. Paste the following into it:
public interface TodoEJB { List<Todo> findAll(); void create(Todo incoming); void update(Long id, Todo incoming); void remove(Long id); }
These are the methods that we’ll invoke from our service layer and they map one-to-one with each of our endpoints. They don’t have to but it keeps things clean. We could also add the @Local annotation to the class to indicate that this interface is the local interface, but it isn’t necessary as it’s assumed. The other kind of EJB interface that exists is a “remote” interface. Remote interfaces are used when we are injecting an EJB from a different JavaEE server. That isn’t the case here, so having only a local interface is fine.
Now, we need to create the implementation class. Create a “TodoEJBImpl.java” file and add the following code to it:
@Stateless public class TodoEJBImpl implements TodoEJB { @PersistenceContext EntityManager em; public List<Todo> findAll() { Query q = em.createQuery("SELECT t FROM Todo t"); return q.getResultList(); } public void create(Todo incoming) { em.persist(incoming); } public void update(Long id, Todo incoming) { Todo entity = em.find(Todo.class, id); entity.setDescription(incoming.getDescription()); em.merge(entity); } public void remove(Long id) { Todo entity = em.find(Todo.class, id); em.remove(entity); } }
Adding the @Stateless annotation tells the JavaEE server to manage this class as a stateless EJB. We also need to tie our implementation class with our interface.
The @PersistenceContext annotation ties our datasource and our EntityManager instance together. An EntityManager will allow us to interact with our datasource using the entities that we have defined. In all cases that I have seen, you will only ever use the @PersistenceContext annotation with an EntityManager. I’ve never seen it used any other way.
The implemented methods use the EntityManager to fetch and store our Todo entity to our datasource.
In the “findAll” method, you’ll notice that we’re generating a query to fetch all of our Todo entities. This query is written using JPQL, or Java Persistence Query Language. It’s very similar to SQL but has one major difference: instead of working with tables it works with entities.
The other methods are fairly straightforward. We “persist” entities when we’re creating them, we “merge” entities usually when we’re updating, and we “remove” entities when we want to delete them.
That’s it for this post. In the next post, we’ll dive into wiring our EJB and our JAX-RS service class together.
Source code is available here: