Jackson Custom Deserializer/Serializer with Spring MongoTemplates - spring

I am having trouble accessing and writing data from/to mongoDB using spring mongoTemplate.
For starters I have a data-model that represents the object that I am trying to retrieve from mongo. I have it annotated with #JsonSerialize and #JsonDeserialize for specifying custom converters.
However when I invoke mongoTemplate.findById(), and try to get this object, I find that my custom deserializer is not invoked at all and I get HttpMessageNotWriteableException.
Is there any other configuration that must be put in place to let mongo know that it needs to use my custom Jackson deserializer?

You can use this for reference: https://gist.github.com/letalvoj/978e6c975398693fc6843c5fe648416d

Related

Multiple Spring Converters for same object

Is it possible to register 2 Converters (#ReadConverter annotated class) in Spring Boot/R2dbc so that I can have:
A service that uses a repository for an object and reads it using 1 converter for example R2dbcEntityTemplate
Another service that uses the other converter, for example using a ReactiveCrudRepository
Reason is because I encrypt/decrypt a field in the read/write converter that it's not needed by one of the service.. Encryption/Decryption seems to be expensive
Thanks

Passing a List of Enum to Spring REST using Get method #QueryParam

I am using Spring and I need to pass a list consisting of enum values using the GET METHOD. Is it possible to use #QueryParam for a List ? If yes, then how and how do we send it through the url.
I used #QueryParam List enumValues and sent data through the url as enumValues=value1&enumVales=value2.
But I get the following error:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface
Please help!
You are facing this issue because you are using JAX-RS annotation #QueryParam with spring. Spring is not compliant to JAX-RS framework, they are completely two different MVC frameworks. If you rather use Spring annotation #RequestParam, the configuration is simple and it will create list of Enum for you:
Your query parameters will look like this: enumValues=value1&enumVales=value2
Your spring RequestMapping will look like: #RequestParam(value="enumValues")List<EnumValues> enumValues

Spring Data REST MongoDB: Joda DateTime representation in REST

My Spring Data MongoDB entity has a property of Joda DateTime type:
#JsonProperty("myDate")
private DateTime myDate;
With Spring Boot 1.3.6, Spring Data 1.8.4, Spring Data REST 2.4.4 this property gets rendered as
"myDate": "2016-09-25T15:58:37.486Z"
in the REST representation of my Spring Data entity.
After I have updated the project dependencies to Spring Boot 1.4.1, Spring Data MongoDB 1.9.3, Spring Data REST 2.5.3 I suddenly get my date field represented as
"myDate": {
"content": "2016-09-25T15:58:37.486Z"
},
It looks like Joda's DateTime started to get treated as data entity again:
https://jira.spring.io/browse/DATAMONGO-624
Now I'm wondering how do I get back to my Spring Boot 1.3.6 DateTime representation in REST without downgrading to that Spring Boot version.
Edit:
Adding Jackson2 #JsonUnwrapped annotation to the property helps to get representation back:
#JsonProperty("myDate")
#JsonUnwrapped
private DateTime myDate;
This is a sub-optimal solution for me though, since my properties get auto-generated from JSON schema and I have limited control over generated annotations.
Edit 2:
The Javadoc for the CustomConversions class states that
These types will be considered simple ones (which means they neither
need deeper inspection nor nested conversion. Thus the
CustomConversions also act as factory for SimpleTypeHolder
Which is in fact not true for Spring Data REST [any more], from what I can tell debugging my code.
The types that are added via default CustomConversions are not treated as simple ones when rendering JSON and properties of those types get serialised as embedded entity objects.
Here is the place in the Spring Data REST PersistentEntityJackson2Module that calls to Spring Data MongoDB PersistentEntity implementation to check whether the property type is simple or not. And since the simpleTypeHolder in the Spring Data Commons AbstractMappingContext does not contain the types for which Spring Boot auto-configuration adds Joda DateTime converters, the DateTime field is treated as complex object.
Edit 3:
Tracking this issue in JIRA:
https://jira.spring.io/browse/DATAREST-907

Spring Boot/JPA not persisting with service layer

I'm using Spring boot along with Spring Data JPA.
I'm stucking in an odd scenario when saving a new entity.
Unsing method from extended CrudRepository class, all works as expected.
If I inject via #Autowired the CrudRepository interface in my service layer, the method still works, but nothing is persisted on db.
The returned object from 'save' method seems ok, since I get an always increasing ID value.
Suggestions?
Cheers
FB
check whether we are populating the data properly in your bean and check it before passing to save method of spring data jpa

When to use #RestController vs #RepositoryRestResource

I have been looking at various examples of how to use Spring with REST. Our end target is a Spring HATEOAS/HAL setup
I have seen two distinct methods for rendering REST within Spring
Via #RestController within a Controller
Via #RepositoryRestResource within a Repository
The thing I am struggling to find is why would you use one over the other. When trying to implement HAL which is best?
Our database backend is Neo4j.
Ok, so the short story is that you want to use the #RepositoryRestResource since this creates a HATEOAS service with Spring JPA.
As you can see here adding this annotation and linking it to your Pojo you have a fully functional HATEOAS service without having to implement the repository method or the REST service methods
If you add the #RestController then you have to implement each method that you want to expose on your own and also it does not export this to a HATEOAS format.
There is a third (and fourth) option that you have not outlined, which is to use either #BasePathAwareController or #RepositoryRestController, depending on whether you are performing entity-specific actions or not.
#RepositoryRestResource is used to set options on the public Repository interface - it will automatically create endpoints as appropriate based on the type of Repository that is being extended (i.e. CrudRepository/PagingAndSortingRepository/etc).
#BasePathAwareController and #RepositoryRestController are used when you want to manually create endpoints, but want to use the Spring Data REST configurations that you have set up.
If you use #RestController, you will create a parallel set of endpoints with different configuration options - i.e. a different message converter, different error handlers, etc - but they will happily coexist (and probably cause confusion).
Specific documentation can be found here.
Well, above answers are correct in their context still I am giving you practical example.
In many scenarios as a part of API we need to provide endpoints for searching an entity based on certain criteria. Now using JPA you don't have to even write queries, just make an interface and methods with specific nomenclature of Spring-JPA. To expose such APIs you will make Service layer which would simply call these repository methods and finally Controllers which will expose endpoints by calling Service layer.
What Spring did here, allow you to expose these endpoints from such interfaces (repositories) which are generally GET calls to search entity and in background generates necessary files to create final endpoints. So if you are using #RepositoryRestResource then there is no need to make Service/Controller layer.
On the other hand #RestController is a controller that specifically deals with json data and rest work as a controller. In short #Controller + #ResponseBody = #RestController.
Hope this helps.
See my working example and blog for the same:
http://sv-technical.blogspot.com/2015/11/spring-boot-and-repositoryrestresource.html
https://github.com/svermaji/Spring-boot-with-hibernate-no-controller
#RepositoryRestController override default generated Spring Data REST controllers from exposed repository.
To take advantage of Spring Data REST’s settings, message converters, exception handling, and more, use the #RepositoryRestController annotation instead of a standard Spring MVC #Controller or #RestController
E.g this controllers use spring.data.rest.basePath Spring Boot setting as base path for routing.
See Overriding Spring Data REST Response Handlers.
Be aware of adding #ResponseBody as it is missed in #RepositoryRestController
If you not exposed repository (marked as #RepositoryRestResource(exported = false)), use #BasePathAwareController annotation instead
Also be aware of bags
ControllerLinkBuilder does not take Spring Data REST's base path into account and #RequestMapping shouldn't be used on class/type level
and
Base path doesn't show up in HAL
Workaround to fix link: https://stackoverflow.com/a/51736503/548473
UPDATE: at last I prefer not to use #RepositoryRestController due to lot of workarounds.

Resources