Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
spring-projects-issues opened this issue May 21, 2020 · 5 comments
Assignees
Labels
type: bug A general bug

Comments

@spring-projects-issues
Copy link

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

@spring-projects-issues
Copy link
Author

Mark Paluch commented

Moved to Spring Data REST as the issue is related to Spring Data REST

@spring-projects-issues
Copy link
Author

bschoenmaeckers commented

We are experiencing the issues as well since DATAREST-1383 has been fixed. This does not only occur on mongo repo's but also on other types. 2.1.5 is the latest working version

@spring-projects-issues
Copy link
Author

bschoenmaeckers commented

I implemented a fix. ProtenusBill, Could you try it and confirm if this fixes your issue?
#381

@spring-projects-issues
Copy link
Author

Oliver Drotbohm commented

The "fix" is not complete unfortunately as it skips the complex object handling following the introduced guard. I.e. all the Collection and Map merging would not work for those transient properties. All this subsequent code relies on the Spring Data property meta-model that currently drops transient properties eagerly, i.e. this is not going to work at all until more severe restructuring of how the meta model works.

Generally speaking, properly PATCHing a document requires that in-depth processing of the incoming document. Your manually implemented controller actually applies PUT semantics, not PATCH ones. Just leave one field you submit away and see how it nulls that out, something that violates the contract of PATCH

@spring-projects-issues
Copy link
Author

smozely commented

Any workarounds for this? We are trying to get to a later version of Spring and been bitten by this with Transient properties on our JPA models. 

 

 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants