Suppose you have a domain model represented by a set of classes annotated @Entity Beans and you would like to expose this model through a RESTful web service. There are several ways of doing this, including the Java way that goes by the name of Jersey API [19]. Good choice, but as soon as you create your first web service you will notice that Jersey uses JAXB (Java Architecture for XML Binding) to serialize Java objects in XML documents, and you will also realize that JAXB and JPA (Java Persistence API) are not easy to combine. This article demonstrates how to combine JAXB [20] and JPA [21] to transfer data between the database and the web service interface without any adapter code in the middle, while preserving the authorization mechanism for sensitive information.
The article is example-driven, guiding you step-by-step through code snippets and highlighting the adaptation required to produce the confluence between JPA and JAXB annotations. The code sample included in the article is a snapshot of the Footprint Service Project [22], an open source project (LGPL license) that supports the distribution of certificates of participation in conferences. The purpose of using a real project instead of toy examples is to guarantee that you are working with tested software and to give you the opportunity to discuss further questions with the project team. The full source code of the project is available in the Subversion repository [23], but a pre-compiled EAR file is provided to shorten the steps required to run and test the project. Note that code retrieved from the repository will vary as the project developers make new commits. Refer to the Resources section of this article for instructions on running the project.
The full Footprint model is too large to be covered in this
article; instead, I focus in a small subset of the problem, being careful not
to miss the important details. For now, let's concentrate on a 1:n
relationship between the conference attendees and their certificates of
participation, as shown in the Figure 1.

Figure 1. The relationship between users and their certificates
Using an open-source project for the examples lets you check out and experiment with a large code set rather than just a few simple cases.
The first step is to design how the persistence layer will be
accessed from the other layers of your Java EE application. Despite the
possibility of using the EntityManager injected in your business layer,
I prefer to follow the classical Design Access Object (DAO) pattern in order to have a
centralized data access layer. The idea is to have a CRUD (Create, Read, Update, Delete) interface
shared by all entities, and to have sub-interfaces extending the CRUD
with specialized business methods. To enable using dependency injection, and
to allow the container to manage the allocation of the DAO classes,
I coded it as an EJB 3.0 Stateless Session Bean, as shown in the steps
below.
package-info.java File
JSR 175 [24]
recommends package-info.java for package-level annotations, and in our
case it is very important to have a namespace applied to all entities.
For example:
@XmlSchema(
namespace = "http://footprint.dev.java.net/service/entity")
@XmlAccessorType(XmlAccessType.FIELD)
package net.java.dev.footprint.service.entity;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSchema;
The choice of the XmlAccessorType should parallel
the JPA annotations. If you are annotating the fields of your
class as JPA columns, use XmlAccessType.FIELD [25];
otherwise use XmlAccessType.PROPERTY [26].
The default value is XmlAccessType.PUBLIC_MEMBER [27]. This causes
problems if you declare a field and create its respective get method.
The JAXB will assume the class has two fields with the same name and
will throw a an exception: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException:
2 counts of IllegalAnnotationExceptions.
All entities should have a version number and a unique identifier, so we start the domain model implementation with a @MappedSuperclass Entity, abstract and serializable as a XML complex type. Here is the complete Footprint entities superclass code:
import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
@XmlType [28]
@MappedSuperclass [29]
public abstract class
AbstractFootprintEntity implements Serializable {
@Transient
public static final long serialVersionUID = 196919661993L;
@XmlAttribute [30]
@Version [31]
private int version;
@XmlElement [32]
@Id [33]
@GeneratedValue [34]
private long id;
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public int getVersion() { return version; }
}
Some important notes about this code:
XmlType to serialize mapped super classes because you
will not use this type as an XML root element. That class will be more
useful as a parameter in Generics [35]
methods.Serializable because Detached Entities must
implement the Serializable interface. When entities
are serialized in XML documents they become detached entities.@Version attribute and
serialize this attribute in the XML documents. This is used by the Optimistic
Concurrency Control [36] of JPA and it is especially relevant to detached
objects exposed through web services. Not only will the entity instance
be detached, but the entity manager instance will be
different between the stateless service calls. The only chance to
detect conflicts between concurrent updates is through the versioning
of the entities. Another important point is the absence of the setVersion(int)
method. This is because the version field reflects its respective
database column, modifiable only by JPA.id as @XmlAttribute
because xml:id [37]
is a defined attribute in XML documents and should be unique.
Another JPA best practice: all entities should have
an ID attribute. As a rule of thumb, never use a name from the XML
specification [38] as an entity's field name. A simple trick if XML is not
your mother tongue: compile
the schema [39] from your annotated classes and check if it passes the W3C XML Schema
Validator [40].@Transient [41]
is redundant in the field serialVersionUID since class
members are neither serialized by JAXB nor persisted by JPA. The
annotation serves to remind you that you can suppress any field from
both persistence and serialization if needed. We declared the serialVersionUID
public to reuse its value in the entity subclasses.@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
to force an alphabetical order, but if you use schemagen [42]
or some other tool to compile those classes in an XSD schema, the order
will reflect your choice. It is more a matter of style than a technical
issue, so I prefer configuring through the fields' order.Below is the code for two
related entities from the Footprint model. First is the entity
that represents the user table:
import java.util.*;
import javax.persistence.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
@Entity
public class FpUser extends FpAbstractUser {
private static final long serialVersionUID =
AbstractFootprintEntity.serialVersionUID;
@XmlElement
@Column(nullable = false)
private String name;
@XmlElement
@Column(nullable = true)
private String email;
@XmlTransient
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<FpCertificate> certificate;
public List<FpCertificate> getCertificate() {
if (certificate == null) {
certificate = new ArrayList<FpCertificate>();
}
return certificate;
}
public void setCertificate(List<FpCertificate> certificate) {
this.certificate = certificate;
}
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
The conversion of simple JPA attributes in JAXB serializable
fields is simple: just add the annotation @XmlElement [32]
or @XmlAttribute [30],
depending on the how you want the information to appear in the output
XML. The trickiest part is to convert the relationship between
entities in JAXB serializable fields, as you can see in the annotation
@XmlTransient [43]
on the certificate field. Before discussing that,
let's check the code from the owner side of the relationship: the
FpCertificate class.
import javax.persistence.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
@Entity
public class FpCertificate extends AbstractFootprintEntity {
private static final long serialVersionUID =
AbstractFootprintEntity.serialVersionUID;
@XmlElement
@ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
private FpAbstractUser user;
@XmlElement
@Column
private String path;
public FpAbstractUser getUser() { return user; }
public void setUser(FpAbstractUser user) {this.user = user; }
public String getPath() { return path; }
public void setPath(String path) {this.path = path; }
}
If you just try to add the @XmlElement annotation on
top of your @Column fields, JAXB will throw a circular
reference exception trying to serialize the objects into XML documents.
The workaround for that problem is to annotate one side of a
relationship with the JAXB @XmlTransient annotation, as we
did in the FpUser class above. Notice that we are removing the
relationship between the entities when we serialize them into XML
documents. That results in two different views on the same domain model:
the full domain model mapped by the JPA Entities and a partial view of
the domain model mapped by the JAXB types. Though scary at first,
that strategy preserves the original domain model and causes no problem
in our application. Another important aspect to observe is the graph of
objects in memory against the data transfer between the service and its
clients. When we think about how to expose the data on the service
interface, we soon realize that the complete object graph representing a
relationship in the domain model may be just too much to serialize in a
service response. Imagine if an instance of FpUser has 200 associated certificates and a service call requests the information about
the user name. In the domain model, a user contains a list of
certificates, but our request needs only the name of the user. So,
the decision of which information our service will expose on which
method is beyond the technical aspects of annotation. A good practice in
RESTful design is to implement complex use cases with several fast
small calls instead of a single slow call that transports large amounts of data.
In our example, the FpCertificate entities will be completely
serialized, but the FpUser entities will be serialized without
information about their certificates. We need to create a second method
to receive the ID of the FpUser and then return the list of the user's
certificates.
Our exercise in defining the visibility of the domain model through the web services starts with the definition of which links we should mark as transient in the JAXB types. The strategy I used to avoid circular references in the JAXB types is summarized in the table below:
| JPA | JAXB | |
|---|---|---|
| Relationship | Owner | Inverse Side |
| @OneToOne | @XmlElement | @XmlTransient |
| @OneToMany | @XmlTransient | @XmlElement |
| @ManyToOne | @XmlElement | @XmlTransient |
| @ManyToMany | @XmlTransient | @XmlTransient |
Another way to manage the visibility of the domain model data on
the service interface is through the JPA
Lazy Loading [44]. The default loading strategy of JPA is Fetch.LAZY,
while the JAXB framework expects a graph of objects already loaded in
memory. So, if you just serialize an @Entity object with JAXB, any lazy-loaded reference to other entities will appear blank on the output XML,
and we want to avoid the use of getters and setters during our magic
conversion between entities and XML elements. The workaround for that is
to change the field loading to EAGER, modifying the JPA annotation, as
shown in the FpCertificate code. It may produce a larger result set and
may impact the application performance, so you should use it only
when you know in advance that the size of the resultant objects graph is
acceptable. Otherwise just leave the Fetch.LAZY and force the client
to do a second service call to compose the object graph by parts.
Now that we have our model annotated by JAXB, we can use the entities both for persistence and for serialization without any other modification. In the next section I show the code of a Data Access Layer [45] used by the web service to expose the domain model on the web.
You can use several strategies to integrate the persistence layer
with the controller layer, including the injection
of the EntityManager in the controller classes [46] or the adoption of the Data
Access Object pattern [47]. I chose the DAO option, and the steps below
enumerate the implementation of the data access layer as a set of EJB
3.0 Stateless Beans.
Define a CRUD interface that can handle the common
persistence operations with our entities. Notice the count
method, useful for pagination.
import java.io.Serializable;
import java.util.*;
import javax.persistence.*;
public interface
FpEntityFacade<T extends AbstractFootprintEntity> {
T create(T entity) throws Exception;
T read(Serializable primaryKey) throws Exception;
T update(T entity) throws Exception;
void delete(T entity) throws Exception;
Collection<T> readAll(int start, int size) throws Exception;
long count() throws Exception;
}
Define the CRUD sub-interface, one for each Entity. Notice that those interfaces can add business operations to the inherited CRUD ones, as suggested in the comments.
@Remote
public interface FpUserFacade extends
FootprintEntityFacade<FpUser> {
// void changeRating(FpEvent event, int newRating);
}
@Remote
public interface FpCertificateFacade extends
FpEntityFacade<FpCertificate> {
}
Now we implement our CRUD interface. Here, the only trick is the
reflection used in the constructor to catch the class of the entity;
this avoids the need to include the type of the entity every time we
construct a new facade. Also observe the EntityManager injected in the
bean, which characterizes those beans more as Entity Manager
Wrapper than DAO, actually.
import java.io.Serializable;
import java.util.*;
import javax.ejb.Stateless;
import javax.persistence.*;
import net.java.dev.footprint.service.entity.*;
@Stateless
public abstract class
CRUDEntityFacade<T extends AbstractFootprintEntity>
implements FpEntityFacade<T> {
private transient final Class<T> entityClass;
@PersistenceContext(name = "footprint")
protected transient EntityManager manager;
@SuppressWarnings("unchecked")
public CRUDEntityFacade() {
entityClass = (Class<T>)
((java.lang.reflect.ParameterizedType)
this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
public T create(final T entity) throws Exception {
manager.merge(entity);
manager.flush();
return entity;
}
public Collection<T> readAll(int offset, int limit)
throws Exception {
if (offset < 0) { offset = 0; }
if (limit <= 0 || limit > 50) { limit = 50; }
Query query;
query = manager.createQuery("select e from "
+ entityClass.getSimpleName() + " e");
query.setFirstResult(offset);
query.setMaxResults(offset + limit);
return doQuery(query);
}
public T read(final Serializable primaryKey)
throws Exception {
return manager.find(entityClass, primaryKey);
}
public void delete(final T entity) throws Exception {
manager.remove(entity);
manager.flush();
}
public T update(final T entity) throws Exception {
return manager.merge(entity);
}
public long count() throws Exception {
Query query =
manager.createQuery("select count(e.id) from "
+ entityClass.getSimpleName() + " e");
Number countResult = (Number) query.getSingleResult();
return countResult.longValue();
}
}
As you notice in the above code, the update method is an important
illustration of exposing domain models through the service interface. All
objects transfered between the client and the service are JPA Detached
Objects, so you can merge the modified data back into the database only if the version of the detached object is the same as the version number
stored in the database. That will not work in two cases:
FpUser entities back in the database, it will
work, but it will delete the relationship between FpUser and
FpCertificate, inserting null into the relationship column.So you will be forced to load the original entity, copy programatically the new data from the incoming object to the original entity object, and finally call the merge operation of JPA. It is an unavoidable procedure, and the general approach for doing that is to use reflection-based APIs like the commons beanutils [48].
Next, implement the CRUD sub-interfaces. It is important to notice
here the safe update method overriding the generic one. The same should
be done to the FpCertificate and the other entities. Another important
aspect is that we exclude the relationship from this safe copy. It
works if your detached entity comes with complete and valid
information from outside the service interface, but for security
reasons it is better to update the relationship between entities only
through specialized business methods. Imagine, for example, if someone
starts to manipulate the entities relationship outside the service
interface and your facade just inserts it back into the database without
filters; it's just too dangerous. Nevertheless, it is important to state
that a merge of relationships works out of the box, and eventually it
can be useful if the client is another service in the same security
zone.
A special remark about the delete operation in the parent-child
relationship between FpCertificate and FpUser: deletion of an
FpCertificate entity (child) requires no extra code, but
deletion of an FpUser entity (parent) requires a bulk operation,
because JPA does not propagate the deletion of a parent to its children.
You need to delete the foreign key references to an FpUser entity
before deleting it; otherwise, the bulk operation will be rolled back.
[Special note: if you apply Hibernate, you can use CascadeType.DELETE_ORPHAN [49];
using TopLink, you have the option to configure the relationships
as private-owned [50].
I didn't apply such features because they are both proprietary, but I
expect such functionality to be included in a next EJB/JPA
specification.]
@Stateless
public class UserFacade extends CRUDEntityFacade<FpUser>
implements FpUserFacade {
@Override
public FpUser update(FpUser entity) throws Exception {
FpUser attached =
manager.find(FpUser.class, entity.getId());
// this can be done with Commons BeanUtils
attached.setEmail(entity.getEmail());
attached.setName(entity.getName());
return manager.merge(attached);
}
@Override
public void delete(long id) throws IllegalStateException,
IllegalArgumentException, TransactionRequiredException,
PersistenceException {
Query query = manager.
createNamedQuery(FpCertificate.BULK_DELETE_CERTIFICATES);
query.setParameter(FpCertificate.USER_ID_PARAM, id);
query.executeUpdate();
FpUser user = manager.find(FpUser.class, new Long(id));
manager.remove(user);
}
}
public class CertificateFacade
extends CRUDEntityFacade<FpCertificate>
implements FpCertificateFacade {
@Override
public FpCertificate update(FpCertificate entity)
throws Exception {
FpCertificate attached =
manager.find(FpCertificate.class, entity.getId());
attached.setPath(entity.getPath());
return manager.merge(attached);
}
}
Our domain model is ready to be exposed on the web. Below you
find an example of a Jersey annotated resource that exposes the FpUser
entities in their service end points (logging and exception handling were
removed for the sake of clarity). Observe how few lines of code are required to
traverse the data directly from the database to the service endpoint
without any copy (unless for the update method explained above). Another
important aspect is the security of the CRUD operations: it is
the responsibility on the service implementation to check if the client or
the authenticated user is allowed to access the referred entities; here
I am just showing the raw code, but in a production environment one should include
business validation on the service interface.
import java.util.*;
import javax.ejb.EJB;
import javax.ws.rs.*;
import javax.xml.bind.*;
import net.java.dev.footprint.service.entity.*;
import static javax.ws.rs.core.MediaType.*;
@Path("/user")
public class UserResource {
@EJB
private FpUserFacade userFacade;
@Produces( { APPLICATION_XML, APPLICATION_JSON })
@Consumes( { APPLICATION_XML, APPLICATION_JSON })
@PUT
@Path("/create")
public FpUser create(FpUser newUser) {
return FpUser user = userFacade.create(newUser);
}
@GET
@Produces( { APPLICATION_XML, APPLICATION_JSON })
@Path("/read/{id}")
public FpUser read(@PathParam("id") String id) {
userFacade.read(new Long(id)));
}
@Produces( { APPLICATION_XML, APPLICATION_JSON })
@Consumes( { APPLICATION_XML, APPLICATION_JSON })
@PUT
@Path("/update")
public FpUser update(FpUser user) {
return userFacade.update(user);
}
@DELETE
@Path("/delete/{id}")
public void delete(@PathParam("id") String id) {
FpUser user = userFacade.read(id);
userFacade.delete(user);
}
@GET
@Produces( { APPLICATION_XML, APPLICATION_JSON })
@Path("/editall/{offset}/{limit}")
public Collection<FpUser> editAll(
@PathParam("offset") int offset
, @PathParam("limit") int limit) {
return userFacade.readAll(offset, limit);
}
}
Observe the nice Jersey feature of exposing the
data in two different formats: XML and JSON. Note that the client should
include the HTTP header Accept:application/json to receive the data in
JSON format.
The code presented in this article is a snapshot of the Footprint Service Project. In order to install and test the sample project, do the following:
asadmin start-database
asadmin start-domain domain1
asadmin deploy --user admin --password adminadmin
footprint-service-ear-1.0-SNAPSHOT.ear
Once you've done this, you can test the application opening the URLs below in a
web browser. To invoke the POST, PUT, and DELETE methods, you can use the
CURL tool on UNIX-based systems. If you are using Windows, you can use CURL
for Windows [54]. Remember: if you set the HTTP Accept header to application/json,
the same code will respond in JSON format.
curl -H "Accept:application/json" -X GET
http://localhost:8080/footprint-service/mock/create
http://localhost:8080/footprint-service/user/editall/0/99 [56]
curl -H "Accept:application/json" -X GET
http://localhost:8080/footprint-service/user/editall/0/99
http://localhost:8080/footprint-service/certificate/readall/0/99 [57]
curl -H "Accept:application/json" -X GET
http://localhost:8080/footprint-service/certificate/readall/0/99
Create a new user. Below you find the content of a sample test.xml file. Notice the ID element is empty, to avoid causing a conflict in the database.
curl -v -H "Content-Type: application/xml" -X
PUT --data-binary @test.xml
http://localhost:8080/footprint-service/user/create
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?> <ns2:fpUser
xmlns:ns2="http://footprint.dev.java.net/service/entity"
version="1"><id></id><name>Your
Name</name><email>email@test.com</email><organization
version="1"><id>3</id><logotype>http://your.company/logo.gif</logotype><name>Your
Company</name><website>http://website.com</website></organization></ns2:fpUser>
Update an existing user. You can use the same test.xml file, but remember to include the ID of the entity that you want to update, and also to modify another field so you can see the changes.
curl -v -H "Content-Type: application/xml" -X
POST --data-binary @test.xml
http://fgaucho.dyndns.org:8080/footprint-service/user/update
Delete a user. Include an existing ID in the URL. Be aware that the only sign of success is the response HTTP code 204.
curl -v -H "Accept:application/json" -X
DELETE http://fgaucho.dyndns.org:8080/footprint-service/user/delete/2
The sample project in this article has no pagination, security, or other advanced
features, but if you want more complete code, you can check out the
Footprint Service from the Subversion
repository [23] and then compile it through Maven as shown below. When
svn asks for a password, just press ENTER.
svn checkout https://footprint.dev.java.net/svn/footprint/trunk [58] footprint --username guest
cd footprint
mvn clean install
You will find the packed EAR file in the target folder. Questions about the service design and how to install it can be posted directly to the Footprint project's dev mailing list [59].
JAXB and JPA can be combined to reduce the boilerplate code of Java EE applications and also to optimize the performance of RESTful web services--a flexible solution, which preserves the original domain model while following the JPA, JAXB, and HTTP standards. Preliminary tests proved that this solution surpasses the performance of traditional techniques based on adapters; nevertheless, our job is not yet complete. Exposing the full domain model through a web service interface is not realistic when you consider production environments. In the second part of this series, I will demonstrate how to control the exposure of the domain model in different service paths, allowing fine-grained management of which parts of the entity beans will be exposed to which group of the application users, providing insight into how to produce robust and scalable RESTful web services based on Java EE technologies.
Several people contributed ideas included in this article: the Footprint project members, friends, and anonymous tips in diverse mailing lists, especially the Jersey [60] and Glassfish [61] mailing lists. I also would like to register special thanks to Roland Huecking and Rudolf Fluetsch for inspirational discussions about Java EE technologies.
Links:
[1] http://www.java.net/author/felipe-gaucho
[2] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1
[3] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#the-domain-model-of-conference-certificates
[4] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#applying-jaxb-xml-annotations-to-the-jpa-entity-beans
[5] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#create-a-package-containing-the-jpa-entities-and-the
[6] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#implement-the-domain-model
[7] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#create-the-entity-beans
[8] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#jaxb-annotations-on-the-relationships-between-jpa-entities
[9] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#a-generic-crud-facade-for-your-entity-beans
[10] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#define-the-crud-interface
[11] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#define-the-crud-sub-interface
[12] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#implement-the-crud-interface
[13] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#implement-the-crud-sub-interfaces
[14] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#exposing-the-domain-model-in-the-restful-interface
[15] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#installing-and-testing-the-sample-service
[16] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#conclusion-and-next-steps
[17] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#acknowledgement
[18] http://www.java.net/article/2009/05/25/exposing-domain-models-through-restful-service-interface-part-1#resources
[19] https://jersey.dev.java.net/
[20] https://jaxb.dev.java.net/tutorial/
[21] http://www.javaworld.com/javaworld/jw-01-2008/jw-01-jpa1.html
[22] https://footprint.dev.java.net/servlets/ProjectProcess?tab=1
[23] https://footprint.dev.java.net/source/browse/footprint/
[24] http://jcp.org/en/jsr/detail?id=175
[25] http://docs.huihoo.com/javadoc/javaee/5/javax/xml/bind/annotation/XmlAccessType.html#FIELD
[26] http://docs.huihoo.com/javadoc/javaee/5/javax/xml/bind/annotation/XmlAccessType.html#PROPERTY
[27] http://docs.huihoo.com/javadoc/javaee/5/javax/xml/bind/annotation/XmlAccessType.html#PUBLIC_MEMBER
[28] http://java.sun.com/javaee/5/docs/api/javax/xml/bind/annotation/XmlType.html
[29] http://java.sun.com/javaee/5/docs/api/javax/persistence/MappedSuperclass.html
[30] http://java.sun.com/javaee/5/docs/api/javax/xml/bind/annotation/XmlAttribute.html
[31] http://java.sun.com/javaee/5/docs/api/javax/persistence/Version.html
[32] http://java.sun.com/javaee/5/docs/api/javax/xml/bind/annotation/XmlElement.html
[33] http://java.sun.com/javaee/5/docs/api/javax/persistence/Id.html
[34] http://java.sun.com/javaee/5/docs/api/javax/persistence/GeneratedValue.html
[35] http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
[36] http://www.oracle.com/technology/tech/java/newsletter/articles/toplink/toplink_caching_locking.html
[37] http://www.w3.org/TR/xml-id/
[38] http://www.w3.org/TR/REC-xml/
[39] http://www.j2ee.me/javaee/5/docs/tutorial/doc/bnbcv.html
[40] http://www.w3.org/2001/03/webdata/xsv
[41] http://java.sun.com/javaee/5/docs/api/javax/persistence/Transient.html
[42] http://java.sun.com/javase/6/docs/technotes/tools/share/schemagen.html
[43] http://java.sun.com/javaee/5/docs/api/javax/xml/bind/annotation/XmlTransient.html
[44] http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html#LazyLoading
[45] http://weblogs.java.net/blog/felipegaucho/archive/2009/04/a_generic_crud.html
[46] http://www.adam-bien.com/roller/abien/entry/jpa_ejb3_killed_the_dao
[47] http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
[48] http://commons.apache.org/beanutils/
[49] http://josian.wordpress.com/2006/09/09/hibernate-annotations-bidirectional-one-to-many/
[50] http://www.nabble.com/TopLink-equivalent-to-Hibernate-delete-orphan-cascade-type-td8164369.html
[51] http://java.sun.com/javase/downloads/index.jsp
[52] https://glassfish.dev.java.net/downloads/v2.1-b60e.html
[53] http://www.java.net/today/2009/06/04/footprint-service-ear-1.0-SNAPSHOT.ear
[54] http://fileforum.betanews.com/detail/cURL-for-Windows/966899018/1
[55] http://localhost:8080/footprint-service/mock/create
[56] http://localhost:8080/footprint-service/user/editall/0/99
[57] http://localhost:8080/footprint-service/certificate/readall/0/99
[58] https://footprint.dev.java.net/svn/footprint/trunk
[59] mailto:dev@footprint.dev.java.net
[60] https://jersey.dev.java.net/servlets/ProjectMailingListList
[61] https://glassfish.dev.java.net/servlets/ProjectMailingListList
[62] http://footprint.dev.java.net/
[63] http://java.sun.com/developer/technicalArticles/J2EE/jpa/
[64] https://jaxb.dev.java.net/
[65] http://forums.oracle.com/forums/forum.jspa?forumID=48