Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to convert a JPA entity to REST representations using JAX-RS and Jackson

I'm looking for a way to export some JPA entities to a REST API, but instead of sending the whole entity every time I want to share just some specific fields depending of the entry point. Here's a small example:

Say we have an Author class with few fields:

@Entity
public class Author implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = SEQUENCE)
    private Long id;

    @NotNull
    @Size(min = 1, message = "{required.field}")
    private String name;

    @NotNull
    @Size(min = 1, message = "{required.field}")
    private String country;

    private LocalDate birthDate;

    // getters and setters
}

And say we have this REST service (just two methods):

@Path("authors")
public class AuthorREST {

    @Inject
    private AuthorBC bc;

    @GET
    @Produces("application/json")
    public List<Author> find(@QueryParam("q") String query) throws Exception {

        List<Author> result;

        if (Strings.isEmpty(query)) {
            result = bc.findAll();
        } else {
            result =  bc.find(query);
        }
        return result;
    }

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Author load(@PathParam("id") Long id) throws Exception {

        Author result = bc.load(id);

        if (result == null) {
            throw new NotFoundException();
        }

        return result;
    }
}

Now, this way, I'll always have the 4 fields when my API is called.

I understand that if I use Jackson I can set an @JsonIgnore to fields I want to ignore, and they will always be ignored.

But what if I want that, in some cases, my whole entity is returned by one service, and in other service (or other method in the same service), only 2 or 3 fields are returned?

Is there a way to do it?

like image 516
rfsbsb Avatar asked Jul 06 '16 20:07

rfsbsb


1 Answers

@JsonView and mix-in

You already know you can use annotations such as @JsonIgnore and @JsonIgnoreProperties to make Jackson ignore some properties.

You also could check the @JsonView annotation. For some details on how to use @JsonView with JAX-RS, have a look here.

If modifying the JPA entities is not an option, consider mix-in annotations as described in this answer.

Data Transfer Object

Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like webservices. This pattern fits very well in REST APIs and using DTOs you'll have more flexibility in the long run. You can have tailored classes for your needs, once the REST resource representations don't need to have the same attributes as the persistence objects.

To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.

For details on the benefits of using DTOs, check the following answers:

  • Why you should use DTOs in your REST API
  • Using tailored classes of request and response

To give better names to your DTOs, check the following answer:

  • Giving meaningful names to your DTOs
like image 59
cassiomolin Avatar answered Oct 07 '22 14:10

cassiomolin