Jackson deserializing custom classes in an OSGi environment - osgi

I have some trouble using Jackson 2.1 in an OSGi environment, when deserializing a class that way:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
class User {
public Class clazz = org.example.MyClass.class;
}
Because Jackson is in a different bundle as my custom classes I want to deserialize, I often get a java.lang.ClassNotFoundException - usually on MyClass1 or MyClass2.
I traced it back to the class com.fasterxml.jackson.databind.util.ClassUtil which uses Class.forName(..) for retrieving a class for deserializing. Because of the different class-loaders on OSGI it only sees the classes of the JRE and of Jackson but not my custom classes.
Is there a simple way to make Jackson find all the required custom classes (I have dozens of them), e.g by adding a class-loader?

As the client of Jackson you have visibility of the classes that you want to deserialize into. The trick is to pass these classes into Jackson, rather than force Jackson to use dynamic reflection to find the classes.
The Jackson documentation indicates that the method ObjectMapper.readValue can take a Class object as its parameter. If you use this method then Jackson should not need to call Class.forName(). The docs give the following example:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
Here, User is the domain class which is visible to your client but not to Jackson. This invocation should work fine in OSGi... if it does not then I would suggest Jackson may have a bug.

Related

How to change Jackson to detect all fields in a POJO, other than only public ones?

When using Spring Boot for a project, Jackson came as default to serialize objects back and from Jsons. I realize that Jackson fails if you don't have public accessors, e.g., getters/setters, or public fields in your POJO.
The behavior is different when I switch to Gson. It detects all fields regardless of their visibility. For this reason, I ended up using Gson.
I felt a little uncomfortable about switching my POJO access rules; It would force some refactoring in the project structure.
So, no problems using Gson, but is there a way of change Jackson's behavior?
Jackson does support reading values from private member fields, but does not do it by default.
You can configure the behavior globally in the Spring Boot config like
jackson:
visibility.field: any
visibility.getter: none
visibility.setter: none
visibility.is-getter: none
(this config will only look for member fields and no longer check get, set and is methods)
You could also use the #JsonAutoDetect annotation to do the same setting for a specific class.
Try to set visibility at ObjectMapper level,
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

Spring Boot - Custom De/Serializer

Want: Create SerDes for Cassandra's LocalDate into String.
Setup: Have a private LocalDateSerDes class with a Serializer and Deserializer internal class that both extend JsonDe/Serializer
Tried the following:
Adding to DTO fields with #JsonSerialize and #JsonDeserialize (Works, but not wanted)
Used #JsonComponent set up via Baeldung's example (does not work)
Created a Module bean on my WebMvcConfigurationSupport configuration (does not work)
Implemented WebMvcConfigurationSupport.extendMessageConverters to add the Module to the instance of MappingJackson2HttpMessageConverter (does not work)
Iterated through the list of converters, removed the instance, and replaced with the default converter builder code but with the module (does not work)
Any idea where I went wrong?

Is there a way to link JAX-RS resource to another resource like in Spring HATEOAS?

In Spring we've got #ExposesResourceFor annotation which can link our resource with other resources. Thanks to this our Value objects (representations) can know nothing of the actual resources.
Is there a way to do it in JAX-RS? I'm using Dropwizard with Jersey and Jackson and all I see is #InjectLinks annotation which I can use in a value object like this:
public class UserGroup {
#JsonProperty
public String name;
#InjectLinks(GroupsResource.class)
public URI myResource;
public UserGroup(String name){
this.name = name;
}
}
But unfortunatelly my Value Objects should know nothing about Resources, so I'm asking can I do such linking on the level of resources - link in spring-hateoas in controllers, as mentioned above.
With #InjectLinks, you don't have to declare the links in your model class. You can create a "wrapper" representation class, as shown in declarative-linking from the Jersey examples (though this solution is not really on the resource class level as you wish).
Another possible solution (rather than declarative linking) is to use the JAX-RS 2.0 Link class, and do the linking programmatically (with no ties to the Jersey implementation/annotations). You can either add the links to your response headers, as see here, or add Links to you model classes, as seen here (or use the wrapper class for this also, so as to not to invade your model classes)
Some Resources
Declarative Hyperlinking
Using Link for headers

Bean Validation for POST requisition in JAX-RS with Jersey implementation

I'm using the Jersey implementation for JAX-RS, and I was looking for an example where I can use the Bean Validation in POST requisitions. I have this operation, for example:
#POST
#Path("document/annotations/save")
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Map<String, Object> saveAnnotation(
#FormParam("user") String userStr,
#FormParam("documentId") String documentId,
#FormParam("documentPage") Integer documentPage,
#FormParam("annotationContent") String annotationContent,
#FormParam("annotationId") Long annotationId,
#FormParam("isMobile") Boolean isMobile) { // the code... }
I wanna use validations constraints (#NotNull, #Pattern, etc) for each method param. I saw this doc where they're using the Seam Framework to do that.
Currently, I'm trying to use the javax.validation implementation to validate my requests, but it doesn't working.
Is there a way to use the JSR-303 specification with JAX-RS?
Tnks.
This is currently not possible using Jersey; one possible alternative is to write a customer resource filter and bind to the #NotNull, etc. annotations.
It would be simpler if it was encapsulated in a resource class because you could then bind to a #Valid annotation on your method and validate the bean in one shot.
Because JSR-303 is designed to deal with beans and not a collection of parameters then it ends up being very verbose when you try to bend it to your will.
IMHO it's better not to keep validation inside your class anyway and to either use the pipes and filters pattern, i.e. ContainerRequestFilter, or to use something like AspectJ as #Willy suggested.
It's possible. See docs for latest Jersey
https://jersey.java.net/documentation/latest/bean-validation.html#d0e9380
https://jersey.java.net/documentation/latest/bean-validation.html

Configure Spring's MappingJacksonHttpMessageConverter

I am using MappingJacksonHttpMessageConverter in Spring MVC to automatically serialize objects like this:
#RequestMapping(value="/*/getAccount", method=RequestMethod.GET)
#ResponseBody
public Account getAccountAction() {
Account account = accountService.getAccount();
return account;
}
Is it possible to configure which properties of the object are serialized? In my example, Account has 3 collections as properties and serializing all these contents would result in a huge object tree. Here I only want to return the flat object.
Sincerely,
Erik
Did you already try to use the Jackson Annotations?
There is the Annotation #JsonIgnoreProperties that can be used to ignore a given list of properties for serialization on class level and there is #JsonIgnore to mark properties to ignore for serialization on field level.
I could figure it out: Configure Jackson with annotatons, it is described in detail in the Jackson configuration.

Resources