0

Given a User entity with the following attributes mapped:

@Entity
@Table(name = "user")
public class User {

    //...

    @Id
    @GeneratedValue
    @Column(name = "user_id")
    private Long id;

    @Column(name = "user_email")
    private String email;

    @Column(name = "user_password")
    private String password;

    @Column(name = "user_type")
    @Enumerated(EnumType.STRING)
    private UserType type;

    @Column(name = "user_registered_date")
    private Timestamp registeredDate;

    @Column(name = "user_dob")
    @Temporal(TemporalType.DATE)
    private Date dateOfBirth;

    //...getters and setters
}

I have created a controller method that returns a user by ID.

@RestController
public class UserController {

    //...

    @RequestMapping(
            value = "/api/users/{id}", 
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<User> getUser(@PathVariable("id") Long id) {

        User user = userService.findOne(id);

        if (user != null) {
            return new ResponseEntity<User>(user, HttpStatus.OK);
        }

        return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
    }

    //...
}

A service in my business logic layer.

public class UserServiceBean implements UserService {

    //...
    public User findOne(Long id) {
        User user = userRepository.findOne(id);
        return user;
    }

    //...
}

And a repository in my data layer.

public interface UserRepository extends JpaRepository<User, Long> {

}

This works fine, it returns everything about the user, but I use this in several different parts of my application, and have cases when I only want specific fields of the user.

I am learning spring-boot to create web services, and was wondering: Given the current implementation, is there a way of picking the attributes I want to publish in a web service?

If not, what should I change in my implementation to be able to do this?

Thanks.

bruneti12
  • 25
  • 4
  • You already have a security hole as your current setup will dump the password to the outside world. That's basically the poster example of why I never ever expose JPA entities in any kind of interface exposed to the outside world. Before you know it a change to the database and the JPA entity either breaks your API, or you expose data that the outside world really has no business of knowing. – Gimby Nov 25 '15 at 14:24
  • You could use DTO's for diffrent representations (see http://martinfowler.com/eaaCatalog/dataTransferObject.html) – fabwu Nov 25 '15 at 14:25
  • You might want to take a look at the @JsonView annotation of Jackson http://wiki.fasterxml.com/JacksonJsonViews and especially this question https://stackoverflow.com/questions/29838960/how-to-dynamically-remove-fields-from-a-json-response – Thomas Traude Nov 25 '15 at 23:23

1 Answers1

1

Firstly, I agree on using DTOs, but if it just a dummy PoC, you can use @JsonIgnore (jackson annotation) in User attributes to avoid serializing them, for example:

@Entity
@Table(name = "user")
public class User {

    //...

    @Column(name = "user_password")
    @JsonIgnore
    private String password;

But you can see there, since you are not using DTOs, you would be mixing JPA and Jackson annotations (awful!)

More info about jackson: https://github.com/FasterXML/jackson-annotations

Gervasio Amy
  • 285
  • 2
  • 8
  • Thanks for your answer. This is a PoC, yes, but I want to improve it step by step. I will be creating some DTO's and having my Service layer expose them, so my JPA entities don't go further than this. – bruneti12 Nov 25 '15 at 14:44
  • That's ok, it's a really good practice indeed. Anyway, you can annotate with Jackson annotations your DTOs in case you want to specify how to serialize/deserialize your DTO. – Gervasio Amy Nov 25 '15 at 14:52