Parsing a POJO to JSON using JAX-RS and not using any speific implemnation code - jersey

I was looking at internals of jersey, on how it converts a simple POJO to Json. Jersey has an interface Providers, which will provide list of contextResolvers given the class and mediaType. once we get the contextResolver, we can get the Context and Marshaller from it, which can used to get the json string, like show below.
lets assume we want to serialize the Pojo "obj". the code will look like follows
Providers ps = ...
ContextResolver<JAXBContext> resolver = ps.getContextResolver(obj.getClass(), MediaType.APPLICATION_JSON_TYPE);
JAXBContext ctx = resolver.getContext(obj.getClass());
ctx.createMarshaller().marshal(obj, writer);
By above way we can convery any POJO which has a valid context resolver to json. but the question is how do we get the handler for Providers.
PS: i have not compiled this code, but from what i can see from source this is what jersey does. On why i am doing all this stuff, so that we can convert a object to JSON directly with JAX-RS apis. instead of using any implementation code.

In a JAX-RS resource clas, use the #Context annotation to tell Jersey to inject the producers:
#Context Producers producers;

So your question is : "how to find providers" ?
You have to write code to find classes in the classpath which are Annotated with #Provider.

Related

Is it possible to add a spring interceptor in a spring security filter chain?

I need to retrieve the path param map in my spring boot application and I noticed that the following line of code:
final Map<String, String> pathVariables = (Map<String, String>) request
.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
only works when in a spring boot InterceptorHandler class, I guess because the "path param" abstraction is spring's.
Problem is that I'm using spring security, defining my own filter chain:
http.addFilterBefore(...).addFilterAfter(myFilterNeedingPathParam) //series of filters
And the last filter needs the path params map. My idea would be to put the interceptor before or, if you want, make sure that the last filter is executed after.
Is there a way to do so?
When in the Spring InterceptorHandler, check the actual class of the request, you may need to cast your request to that. Also look into the source code for that class and see if it's pulling that value from a ThreadLocal of some sort.

Why do we need jackson databind?

I am new in Spring MVC. My question is, why do we need jackson databind? Because We can receive the Request Params by #ModelAttribute and requests through http PUT or POST by #RequestBody. I can't find a reason why we need jackson databind to convert json/xml to POJO or vice versa.
Thanks.
Why do we need jackson databind?
Because representing structured data is much easier using XML (or JSON) than using simple name-value pairs.
Because it is more convenient to send and receive JSON from the client side when you are doing AJAX.
Because once you have to deal with sending and receiving JSON or XML in the server side Java app, it is more convenient to deal with structured data as POJOs.
None of the above points mean you have to use a binding. There are other ways of dealing with each of the above. But many Java developers think that data bindings the better way to go: more efficient in terms of developer time, and more reliable. Especially if you are implementing services with a complex APIs. That's why they are popular.
And as other answers/comments point out, if you are using #RequestBody, then that is using a binding library under the hood to give you the POJOs. In the case of Spring, it is Jackson that is being used.
By default, when an endpoint expects a JSON document as input and a given controller method argument is annotated with #RequestBody, Spring will use Jackson databind features to map the incoming JSON document to a Java object. You don't need to use the Jackson's ObjectMapper directly, as Spring does it for you.
For example purposes, consider the following HTTP request to create a comment:
POST /comments HTTP/1.1
Host: example.org
Content-Type: application/json
{
"content": "Lorem ipsum"
}
And the following class which represents a comment:
#Data
public class Comment {
private String content;
}
A #RestController to handle such request would be like:
#RestController
#RequestMapping("/comments")
public class CommentController {
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Foo> createComment(#RequestBody Comment comment) {
// By default, Spring will rely on Jackson databind to map the incoming
// JSON document to the comment argument annotated with #RequestBody
...
}
}
If you are interested in the Spring component that maps the incoming JSON document to a Java object, have a look at the MappingJackson2HttpMessageConverter class:
Implementation of HttpMessageConverter that can read and write JSON using Jackson 2.x's ObjectMapper.
This converter can be used to bind to typed beans, or untyped HashMap instances.
By default, this converter supports application/json and application/*+json with UTF-8 character set. [...]
If you are creating a HTTP API and exposing resources that can be manipulated with JSON representations, it's unlikely you'll use #ModelAtribute. Such annotation is particularly useful when you are dealing with web views.
When you get some request in some data types like json/xml, the Spring MVC platform will try to deserialize this request attributes in some model object of your project.
But the platform itself don't provide a des-serialize implementation out of the box. So it will try to use some des-serializer provider in the classpath like jackson, jersey, gson, etc.
As you said - is possible to use #ModelAttribute - but this annotation is a better option to a request from a form view in the front-end. In cases rest json/xml requests, the #ModelAttribute won't be able to convert correctly the received data to a business class of your program.

Jackson deserializing custom classes in an OSGi environment

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.

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

CXF DynamicClientFactory efficiency

I need to generate Java client for web service. I have two choices to do that one is use Apache CXF DynamicClientFactory class and the other is use JAX-WS Dispatch API.
From CXF documentation I understood that DynamicClientFactory class will generate the web service SEI, data classes at runtime (using wsdl2Java tool). If I want to call any web service method I need to load the appropriate data class name and I needs to set the parameter using reflection like follows.
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("people.wsdl", classLoader);
Object person = Thread.currentThread().getContextClassLoader().loadClass("com.acme.Person").newInstance();
Method m = person.getClass().getMethod("setName", String.class);
m.invoke(person, "Joe Schmoe");
client.invoke("addPerson", person);
In the above code Person class is generated at runtime by CXF and reflection is used to set the property values.
My question here is: if I want to set 20 parameter values, then I needs to make 20 reflection call to do that. Is this an efficient way to do that? Or is there any alternative? Or is better to use Dispatch API from JAX-WS? Please help me.

Resources