spring-projects / spring-projects/spring-data-rest

@Transient annotation won't deserialize fields on MongoRepository PATCH requests [DATAREST-1524]

Open
#1,881 5 comments 0 reactions 1 assignee View on GitHub

@odrotbohm is already working on this.

Since Dec 31, 2020.

type: bug
Dominant language
Java
Stars
958
Forks
568
PR merge metrics
No merged PRs in 30d

Description

ProtenusBill opened DATAREST-1524 and commented

I encountered this after upgrading from 2.1.x to 2.2.x. We have a class containing a field with a @Transient annotation - we want to read the field from the client's request but not store it in Mongo. 

Here's a nominal example:

 MyBean.java

@Document
public class MyBean {
  @Id
  String id;

  String persist;

  @Transient
  String noPersist;

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public String getPersist() {
    return persist;
  }

  public void setPersist(String persist) {
    this.persist = persist;
  }

  public String getNoPersist() {
    return noPersist;
  }

  public void setNoPersist(String noPersist) {
    this.noPersist = noPersist;
  }
}

MyBeanRepository.java

@RepositoryRestResource(path = "myBeans", collectionResourceRel = "myBean")
public interface MyBeanRepository extends MongoRepository<MyBean, String> {
}

MyBeanController.java

@Component
@RequestMapping("/v1/myBeans/")
public class MyBeanController {

  @Autowired
  MongoTemplate mongo;

  @RequestMapping(method = RequestMethod.PATCH, value = "/modify/{id}")
  public void modify(
    @PathVariable("id") String id,
    @RequestBody EntityModel<MyBean> modifiedResource,
    HttpServletResponse response) {
    if (mongo.findById(id, MyBean.class) == null) {
      response.setStatus(HttpServletResponse.SC_NOT_FOUND);
    } else {
      MyBean modified = modifiedResource.getContent();
      modified.setId(id);
      mongo.save(modified);
      response.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }
  }
}

MyBeanEventListener.java

@Component
public class MyBeanEventListener extends AbstractMongoEventListener<MyBean> {

  @Override
  public void onBeforeConvert(BeforeConvertEvent<MyBean> event) {
    MyBean bean = event.getSource();

    System.out.println("Persist is null? " + (bean.getPersist() == null));
    System.out.println("No persist is null? " + (bean.getNoPersist() == null));
  }
}

Here's the output on the following requests:

Default Create Endpoint
POST http://localhost:3002/services/v1/myBeans

{
  "persist": "foo",
  "noPersist": "bar"
}

Persist is null? false
No persist is null? false

Default Modify Endpoint
PATCH http://localhost:3002/services/v1/myBeans/5ec6ab4eb2c37203c6d546fe

{
  "persist": "foo2",
  "noPersist": "bar2"
}

Persist is null? false
No persist is null? true

Custom Modify Controller
PATCH http://localhost:3002/services/v1/myBeans/modify/5ec6ab4eb2c37203c6d546fe

{
  "persist": "foo3",
  "noPersist": "bar3"
}

Persist is null? false
No persist is null? false

I tried a myriad of combinations of Jackson @JSONX... annotations to no avail. My assumption is that the @Transient annotation should not affect JSON serialization/deserialization so this appears to be a bug


Affects: 3.2.7 (Moore SR7)

Issue Links:

  • DATAREST-1383 Backend read-only properties overridden for PATCH requests

2 votes, 6 watchers

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.