Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exposing JPA entities through Service

We are in the process of developing a web application with AngularJS,Rest,JPA. I have read a few articles about how domain entities should not be exposed via services. I understand that this is tight coupling, there could be circular references,separation of concerns and it seems valid to me. But then I see articles about applying both jpa and jaxb mappings to the same model, eclipseLink moxy is one example.

Then there is Spring data REST which exposes jpa entities via a rest api.(May be Spring Data REST is used to solve a different problem at hand)

So I am a little bit confused. Answers to the following 2 questions and scenarios where one is better that the other would be helpful.

  1. What are the advantages in applying both jaxb and JPA annotations to the same domain model ? Is this done only primarily to avoid a DTO in between layers?

  2. Should Spring data REST be used only when you are developing an application which needs to expose CRUD operations and there is really no other business functionality involved?

like image 914
Ajay Iyengar Avatar asked Apr 14 '15 14:04

Ajay Iyengar


1 Answers

Using DTOs requires a certain overhead: the DTO classes must be created; entity classes must be mapped to the DTOs before serialization.

DTO also "feel wrong" in so far as they seem to contravene the "don't repeat yourself" principle. It is frustrating to look at an entity and a DTO and see that they are essentially the same.

So, directly exposing your JPA entities reduces code and reduces mental overhead while working with the code. Your controllers, services, and repositories all deal with the same classes.

There are issues, however:

  • Mismatch between your internal representations and the interface you want to expose to the API user.

    Real-world example: hierarchical documents in which the root document is an article and child documents are sections. Internally, each document has a relation to a parent document which may be null.

    Exposing this entity directly via the REST interface would require the client to send the id (or the url in HATEOAS) as part of their submitted entity to correctly link together the documents.

    Much better is to have the api user POST to /articles/{id}/sections/ when creating a subsection.

  • Exposing internal data.

    Your entities may include identifiers, paths on disk, etc which are not really for public consumption. You'll have to @JsonIgnore these while serializing. When deserializing, you'll also then have fill these from the entity by hand.

  • Performance.

    Similar to the point above; maybe your entity contains a large data object. You want users to be able to POST or PUT these, but they shouldn't be required to download the object just to read the other fields of the entity.

  • Potential serialization issues.

    Lazy-loaded collections are the classic failure case here.

  • More complicated serialized representations than necessary.

    Real world example: a word entity with a collection of synonyms; the synonyms are dependent upon the word. Directly serializing the entities will result in:

    { "id":12, 
      "word": "cat",
      "synonyms": [
        { "id": 23,
          "synonym": "kitty"
        },
        { "id": 34,
          "synonym": "pussycat"
        }
      ]
    }
    

    A better model is:

    { "word": "cat",
      "synonyms": [
        "kitty",
        "pussycat"
      ]
    }
    
  • Lots of annotations on the same class which can reduce clarity.

    Depending on your entity complexity, you might have JPA annotations (@Entity, @Id, @GeneratedValue, @Column, @ManyToMany, @MappedBy, etc), XML annotations (@XmlRootElement, @XmlType, @XmlElement, etc), JSON annotations (@JsonInclude, @JsonIgnore, @JsonProperty, etc), and validation annotations (@NotNull, @Null, etc) all on the same class.

Due to all of these issues, I generally use DTOs. I do the entity to DTO mapping by hand, but there are project which try to make this easier, like Dozer.

I can imagine using spring-data-rest or directly exposing my entities only in the case where I have very simple entities, without too many relations between them, and where there is a high correspondence between the entity model and the model which I wished to expose to the user.

like image 135
beerbajay Avatar answered Oct 06 '22 05:10

beerbajay