FabriceD
FabriceD

Reputation: 167

JAX-RS / Entities best practice

In my project, I use JAX-RS to expose some entities to a javascript front-end framework (AngularJS).

I don't want to eager load my entities relations and I rather have multiple methods to fetch whatever relation the client needs.

To serialize my entity to JSON/XML I use JAXB and add relation's ids to the class. I now end up with my entity being an entity as well as a DTO.

On each POST, I need to set my entity's reference back.

I would like to know if it is the appropriate way to expose entities or are there better ways ?

An example being always clearer than long text, here it is :

@XmlRootElement
@Entity
public class Country {
    @Id
    @GeneratedValue
    private Integer id;

    private String countryName;

    @ManyToOne
    private Region region;

    @Transient
    private Integer regionId;

    // getters & setters

    // AVOID SERIALIZING REGION
    @XmlTransient
    public Region getRegion ...

    // SERIALIZE REGION ID INSTEAD
    public Integer getRegionId() {
        if (region != null)
            return region.getId();
        else
            return null;
    }

    ...

}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
public class Region {
    @Id
    @GeneratedValue
    private Integer id;

    private String regionName;

    // getters & setters

    ...

}

@Stateless
@Path("countries")
public class CountryResource {

    @PersistenceContext
    private EntityManager em;

    @GET
    public List<Country> getAll() {
        return em.createNamedQuery("Country.findAll", Country.class).getResultList();
    }

    @PUT
    public void saveCountry saveCountry(Country country) {
        // UPDATE REFERENCES
        country.setRegion(em.getReference(Region.class, country.getRegionId()));
        em.persist(country);
    }

}

Do you suggest something else ?

Thanks,

F.D

Upvotes: 2

Views: 986

Answers (1)

spencerwi
spencerwi

Reputation: 46

I've found it generally a good idea to use the DTO pattern as an "anti-corruption layer" and a sort of published API for web request/response bodies.

For example, let's take your Country class. If your web API sends down the Country class directly (straight serialized to JSON), you expose parts of your app code that consumers of your web API perhaps shouldn't know about, to prevent them from writing code coupled to points that are prone to change.

So you build a "property bag" class that exists as a representation of the common "language" your web API consumers and collaborators should use.

For example:

public class CountryDTO {
    public final Integer id;
    public final String countryName;
    public final Integer regionId;

    public CountryDTO(Country countryToSerialize){
        this.id = countryToSerialize.getId();
        this.countryName = countryToSerialize.getCountryName();
        this.regionId = countryToSerialize.getRegion().getId();
    }
}

This way, if in the future you change the structure of your Country class, your API consumers are still presented with the same consistent data "shape" (until you deprecate/upgrade/whichever based on your versioning practices).

You also get fine-grained, library-agnostic control over how your domain objects are serialized, because you can pick and choose which fields you use.

Finally, you don't have to worry about pulling entity objects in from requests and the confusion of whether your ORM considers them attached/unattached/transient/whatever as you pass them around your app code. You're then free to add validation steps based on the strictly-transient DTO before ever instantiating a domain entity.

Upvotes: 3

Related Questions