0
votes

I'm having a weird issue on my Spring backend, where I am sending a post request with a domain User object from my angular2 frontend that is being recieved by a REST API endpoint and translating it into the Spring User model object. The issue is that the password field from the JSON request seems to not be translating to the password field on the backend. All the other fields (username, name, email, etc.) are coming through fine, but the password is null.

Request payload as seen from network tab in chrome

email : "[email protected]" firstName : "asdfasdjk" lastName : "asdfs" login : "adfsjk" password : "fasdfasdfasdsd"

Response seen from network tab

error: "Internal Server Error" exception: "javax.validation.ConstraintViolationException" message: "Validation failed for classes [domain.User] during persist time for groups [javax.validation.groups.Default, ]

List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=password, rootBeanClass=class domain.User, messageTemplate='{javax.validation.constraints.NotNull.message}'}]" path:"/api/users" status: 500

Spring Rest method:

@RequestMapping(value = "/users",
        method = RequestMethod.POST,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity<User> createUser(@RequestBody User user) throws URISyntaxException {
    User result = userRepository.save(user);
    return ResponseEntity.created(new URI("/api/users/" + result.getId()))
            .headers(HeaderUtil.createEntityCreationAlert("user", result.getId().toString()))
            .body(result);
}

Spring domain object

@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class User extends AbstractAuditingEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotNull
    @Size(max = 100)
    @Column(length = 100, unique = true)
    private String login;

    @JsonIgnore
    @NotNull
    @Size(min = 5, max = 60)
    @Column(length = 60)
    private String password;

    @Size(max = 50)
    @Column(name = "first_name", length = 50)
    private String firstName;

    @Size(max = 50)
    @Column(name = "last_name", length = 50)
    private String lastName;

    @Email
    @Size(max = 100)
    @Column(length = 100, unique = true)
    private String email;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_tag",
        joinColumns = @JoinColumn(name = "users_id", referencedColumnName =     "ID"),
    inverseJoinColumns = @JoinColumn(name = "tags_id", referencedColumnName = "ID"))
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private List<Tag> tags = new ArrayList<>();
}

Angular2 domain object

export class User {

   id: number;
   login: string;
   password: string;
   firstName: string;
   lastName: string;
   email: string;
}
1

1 Answers

0
votes

The problem is with using @JsonIgnore on the password field, this makes the filed ignorable when reading from or writing to JSON message, one solution is to use @JsonProperty with access = Access.WRITE_ONLY as follows

public class User extends AbstractAuditingEntity implements Serializable {

  // Other fileds

  @NotNull
  @JsonProperty(access = Access.WRITE_ONLY)
  @Size(min = 5, max = 60)
  @Column(length = 60)
  private String password;

}

Another solution is to implement a getter and setter for the password field, and annotate the getter with @JsonIgnore and the setter with @JsonProperty, as follows

public class User extends AbstractAuditingEntity implements Serializable {

  // Other fileds

  @NotNull
  @Size(min = 5, max = 60)
  @Column(length = 60)
  private String password;

  @JsonIgnore
  public String getPassword() {
    return password;
  }

  @JsonProperty
  public void setPassword(String password) {
    this.password = password;
  }

}