A Generic CRUD Facade for your @Entity Beans
CRUD (create-read-update-delete) is a repetitive code in
Java EE projects but it can be isolated in a unique class
through the usage of JPA annotations and Generics - a class I call CRUDEntityFacade.
This is not a new pattern and the goal of this blog entry is just to
prepare you to read my next entries about JAXB and JPA together. I am
doing really nice things with Jersey and Glassfish, and before exposing
complicated inventions I decided to register the basics of the
persistence layer (also very nice for my own future reference).
Complete sample projects
The code I am publishing here is just to avoid you to checkout a
full project and to dig to inspect my CRUD strategy. But if you want to
see this technique in action, please be my guest to checkout one of my
open-source projects. The projects are built by Maven and were created
in Eclipse - but you should be able to run it on your preferred IDE
without any problems. Both projects require minimum Java 6.
-
Example #1: the href='https://footprint.dev.java.net/'>Footprint project, what
includes a RESTful service coded with the Jersey framework. Subversion
checkout:svn checkout
https://footprint.dev.java.net/svn/footprint/trunk footprint --username
username - Example #2: the
href='https://cejug-classifieds.dev.java.net/'>Cejug-Classifieds
project, a WSDL first web-service coded with the JAX-WS framework. Subversion
checkout:svn checkout
https://cejug-classifieds.dev.java.net/svn/cejug-classifieds/trunk
cejug-classifieds --username username
username is your java.net login, or you can useguest without password to get a read only copy.
The generic CRUD implemented with generics and JPA annotations
-
Defining the persistence interface containing the persistence
operations we want to share among the entities. Note that I
replicated the runtime exceptions because it is an interface and we
expect interfaces to be the most documented and self-understandable
artifacts in our project.public interface FootprintEntityFacade<T extends
AbstractFootprintEntity> {
T <strong>create</strong>(T entity) throws EntityExistsException, IllegalStateException,
IllegalArgumentException, TransactionRequiredException;
T <strong>read</strong>(Serializable primaryKey) throws IllegalStateException,
IllegalArgumentException;
T <strong>update</strong>(T entity) throws IllegalStateException,
IllegalArgumentException, TransactionRequiredException;
void <strong>delete</strong>O(T entity) throws IllegalStateException,
IllegalArgumentException, TransactionRequiredException,
PersistenceException;
} -
To define a superclass of all entities. This is an important
step, since we want to use generics we must have a unique type to pass
in our interface implementation. The mapped superclass is also useful
to share the ID attribute.@MappedSuperclass
public abstract class AbstractFootprintEntity implements Serializable {
@Transient public static final long serialVersionUID = 196919661993L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
<font color='gray'>// getters & setters</font>
} -
Then we need some entities. I will use an example of the
Footprint entity that represents Events (JUG meetings, courses or conferences).@Entity
public class FpEvent extends AbstractFootprintEntity {
@Transient private static final long serialVersionUID = 196919661993L;
@Column(nullable = false)
private String name;
@Column(nullable = true)
private String website;
@Version
private long updatedTime;
<font color='gray'>// getters & setters</font>
}
-
Now an important step, the realization of our generic CRUD
interface to our Event Entity. In theory this empty interface is not
necessary, but my experiments proved that this is the best way to
go. It opens a chance for the customization of the persistence
interface and - the main reason - it avoids conflicts between different
entity instances using a same interface. You will have 1 empty interface
for each Entity in your project, an oddity I couldn't get rid off - if you
know how to avoid it, please tell me.@Local
public interface EventFacadeLocal extends FootprintEntityFacade<<strong>FpEvent</strong>> {
}
-
Now we just need to implement the CRUD. A special note about the
empty constructor, that uses reflection to get the class of the generic
type - this is the hidden trick that makes the magic possible.@Stateless
public class CRUDEntityFacade<T extends AbstractFootprintEntity> implements FootprintEntityFacade<T> {
private transient final Class<T> entityClass;
@SuppressWarnings("unchecked")
public CRUDEntityFacade() {
entityClass = (Class<T>) ((java.lang.reflect.ParameterizedType) this
.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@PersistenceContext(name = "footprint")
protected transient EntityManager manager;
public T create(final T entity) throws EntityExistsException,
IllegalStateException, IllegalArgumentException,
TransactionRequiredException {
manager.persist(entity);
manager.flush();
return entity;
}
public T read(final Serializable primaryKey) throws IllegalStateException,
IllegalArgumentException {
return manager.find(entityClass, primaryKey);
}
public T update(final T entity) throws IllegalStateException,
IllegalArgumentException, TransactionRequiredException {
manager.merge(entity);
manager.flush();
return entity;
}
public void delete(final T entity) throws IllegalStateException,
IllegalArgumentException, TransactionRequiredException,
PersistenceException {
manager.remove(entity);
manager.flush();
}
}
-
Now we need to create a concrete implementation of the facade interface. Again an empty type, where you can add your customs methods if any. You will never instantiate this type manually, but it will be used by the generics mechanism to have different types for different facades.
@Stateless
public class EventFacade extends CRUDEntityFacade<FpEvent> implements
EventFacadeLocal {
}
-
It is done, now we can persist any entity of the type
AbstractFootprintEntity (remember to create the empty sub-interface for
each new entity you want to persist). Below you find an example of the
CRUD usage in a Jersey resource:@Path("/event")
public class EventResource {
@EJB
private <strong>EventFacadeLocal</strong> eventFacade;
@Produces( { MediaType.APPLICATION_XML })
@Consumes(MediaType.APPLICATION_XML)
@POST
@Path("/test2")
public FpEvent postJAXBElement(FpEvent e) {
return eventFacade.<strong>create</strong>(e);
}
}
In my next entries I will show you how to use dual annotation
(JAXB + JPA) in order to minimize the impedance mismatch between the
persistence layer and the serialization of element used in the services
endpoints - REST or SOAP.
- Printer-friendly version
- felipegaucho's blog
- 4309 reads






Comments
by kschaefe - 2009-04-22 20:03
Sorry, stripped my generic type parameters: public static <T> DAO<T> createDAO(Class<T> entityClass); Karlby kschaefe - 2009-04-22 20:01
You can avoid having a subclass per DAO if you vend the DAOs from a factory. public static DAO createDAO(Class entityClass); Then, you can pass the Class reference in, instead of magicking it from the subclasses generic type arguments. Karlby javaniraj - 2009-04-22 07:10
The Jmatter framework http://jmatter.org/ also uses annotations(@entity) to produce full blown UI in swing and also it has some nice proff of concept to produce UI in Wings and ECHO2.by felipegaucho - 2009-04-20 00:51
Morris: in my current code I already double annotate the entities as JAXB serializable elements, so I can expose the entities directly on the service endpoint ... in a future Java version we can dream with "GUI Annotations", so we can annotate our entities with a something like @GUI(format="masterdetail", role="master"). This will expose an interface used by the GUI renderers (like GWT or JavaFX) to produce the graphical user interface.. nice, isn't it ? :)by mrmorris - 2009-04-20 00:34
Great. So now we just need a UI generater on top, say GWT. ;)by felipegaucho - 2009-04-20 00:26
Laird, thanks.. I missed this detail... I will fix the code here :)by felipegaucho - 2009-04-20 00:26
Antonio: yes, the entity manager may be adopted but we usually don't have only CRUD in our applications. So, one of the goals of my DAO is to centralize the interface, I can know what persistence operation is being done in a unique package. The point is about the robustness and reuse of the code. Creating a centralized persistence code, I can test and verify it is correct once and only once in my project. Spreading the injection of the entity manager all over the code force me to verify every point where I am using the persistence about it correctness. And I have the custom operations also, what will force a second code somewhere.. I prefer to declare this code in a sub-interface then to keep it hidden in a particular type.by agoncal - 2009-04-19 23:50
Hi Felipe, For me the DAO pattern shouldn't be used for CRUD anymore (except if it's complex ones or if there is a real reason to change database). As Adam wrote on his blog (http://www.adam-bien.com/roller/abien/entry/jpa_ejb3_killed_the_dao) the EntityManager acts like a abstract DAO. One line of code and you can persist an entity. Antonioby ljnelson - 2009-04-19 16:53
Ooh, be careful with the update: merge(T) returns a T, which you are going to want to use to avoid exceptions later on. Cheers, Laird