5

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?

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
rfsbsb
  • 519
  • 10
  • 18

5 Answers5

5

@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:

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

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
3

If you want to decouple the parsing from your JPA entities and return only certain attributes you can always use Mixins for this purpose. http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations

One more thing. If you want things to be dynamic in one service to return one representation in another to return another representation. Your option is to write a custom JSON serializer! Check this post for how to create a customer serializer: How do I use a custom Serializer with Jackson?

Alexander Petrov
  • 9,204
  • 31
  • 70
  • I'll try it and see if it is what I'm looking for. Thanks – rfsbsb Jul 06 '16 at 20:43
  • Thanks, I've tested using mixing and I liked it more than using DTO. Also, @JsonViews seems to be a nice alternative, but for the moment I'll stick with Mixin. – rfsbsb Jul 07 '16 at 13:09
  • More about mixInAnnotations https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations – ravthiru Mar 29 '17 at 06:18
  • 1
    I my opinion you should not serialize your entity classes, copy the values to a DTO for better serialization control. Using Mixins to handle different views of an entity sounds like a decoupling that could easily be overlooked by the next developer looking at the code. – Klaus Groenbaek Apr 06 '17 at 16:24
1

For myself I found it quite suitable to use @JsonView annotation. So you can define fields to be rendered in specific view. You can find more info here http://wiki.fasterxml.com/JacksonJsonViews

Stan
  • 1,410
  • 10
  • 14
  • I liked what can be done with @JsonView, but I could make it work with mixins. I don't know yet if there's any advantage/disadvantage using one or another, but for the moment I'll stick with Mixin. Thank you anyway. – rfsbsb Jul 07 '16 at 13:11
0

I think you can write a custom MessageBodyWriter using Jersey framework and you can control the response payload the way you want. Here you have to write few lines of code in-order to manage the response payload. For more information please visit https://jersey.java.net/documentation/latest/message-body-workers.html#d0e6826

Thamizharasu
  • 301
  • 3
  • 13
0

I would use Spring Data REST and then use the ApiModel annotation to hide the attributes you do not want exposed.

Beezer
  • 1,084
  • 13
  • 18