Requirements:
- Installled JDK 1.5 (better 1.6)
- An IDE of your choice e.g. vi, emacs, netbeans 6.1 (SE or EE), Eclipse Genymede (SE or EE)
- @Stateless, @Local, @Entity, @Id Annotations in classpath
- An
Java EE 5 capable application server of your choice. It will work with
Glassfish v1+ (better v2), JBoss 4.2+, WLS 10+ and probably Geronimo
(not tried yed)
What is to do:
- In the IDE
you will have to point to a JAR containing the three annotations. If you
have the Reference Implementation installed (Glassfish), put just:
glassfish\lib\javaee.jar to the classpath. You will need a persistence provider as well. In case of toplink, there is only one jar: (glassfish\lib\toplink-essentials.jar). IDEs with built in EE
support have already everything you need. However for the very first
time I would prefer to develop "from scratch" an EJB.
- Start with the Entity class. Just create a class and put @Entity tag on it:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Book{
@Id
@GeneratedValue
private Long id;
private String title;
public Book() {
}
public Book(String title) {
this.title = title;
}
}
The @Id @GeneratedValue annotations denote the id field as a primary key. An entity should contain a parameterless constructor as well.
- Setup a DataSource at the application. jdbc/sample already exists in every fresh Glassfish installation (so nothing to do here).
- Create an interface with CRUD methods:
import javax.ejb.Local;
@Local
public interface BookService {
Book createOrUpdate(Book book);
void remove(Book book);
Book find(Object id);
} - Create
a class which implements this interface. You will be forced by a good
IDE (probly not by vi or emacs) to implement this interface:
@Stateless
public class BookServiceBean implements BookService {
@PersistenceContext
private EntityManager em;
public Book createOrUpdate(Book book) {
return em.merge(book);
}
public void remove(Book book) {
em.remove(em.merge(book));
}
public Book find(Object id) {
return em.find(com.abien.Book.class, id);
}
}
The method merge creates or updates an entity, all other methods should be self-explanatory. Hint: you cannot remove not-attached entities - you have to find them first. This is the "Seek And Destroy" pattern :-).
- You have to create a small XML file. However - it will not grow:
<persistence-unit name="sample" transaction-type="JTA">
<jta-data-source>jdbc/sample</jta-data-source>
<properties>
<property name="toplink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
There is only one persistence-unit element with the name "sample". EJB 3 Dependency Injection works with the "Convention Over Configuration" principle. This allows us to keep the injection of the EntityManager very lean: if there is only one possibility - you have not to configure it.
- Compile everything and JAR (the persistence.xml into META-INF) the output (in Netbeans just "build", in Eclipse "Export -> JAR")
- Copy
the JAR into the autodeploy folder of WLS 10
(bea10\user_projects\domains\YOUR_DOMAIN\autodeploy), or
glassfish\domains\domain1\autodeploy in the case of Glassfish v2, or
jboss-4.2.2.GA\server\default\deploy in case of JBoss
- Inspect the log files, you are done :-)
What you have gained:
- It's threadsafe (in multicore environments as well)
- Remoting: you can access the interface remotely
- It's transactional - transactions are started for you
- It's pooled - you can control the concurrency and prevent "denial of service" attacks.
- It's monitored: and EJB have to be visible through JMX. Application servers provide additional monitoring services as well.
- Dependency
Injection just works - you can inject persistence, other beans, legacy
pojos (I will cover this in some upcomings posts)
- It's portalble and so vendor-neutral. Deployment to different application servers just works
- There is almost NO XML.
- Its easily accessible (via DI), from Restful services, JSF, Servlets etc.
- Clustering and security are beneficial as well - but not the main reason to use EJBs
- EntityManager is injected in thread-save manner.
- Transactions are managed for you - the EntityManager participates in the transactions (no additional setup etc. necessary)
You know any other framework with less lines of code / configuration effort? :-)
However typing CRUD stuff is boring and 2-3 minutes still too long. Netbeans comes with a nice wizzard which generates the Session Bean for you (then the whole exercise can be performed in about 30 seconds...), and you could think about implementing a generic CRUD-service as well.