Table of Contents
Rest Jax-RS
Sample
- Complete JSON:
- Webclient:
Basic
JAXB - JAX-RS
- Book: RESTful Java with JAX-RS 2.0: Designing and Developing Distributed
JAX-RS Concepts
Entity Providers
These providers control the mapping of data representations (like XML, JSON, CSV) to their Java object equivalents.
Context Providers
These providers control the context that resources can access via @Context annotations.
Exception Providers
These providers control the mapping of Java exceptions to a JAX-RS Response instance.
public interface Providers {
<T> MessageBodyReader<T> getMessageBodyReader(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType);
<T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType);
<T extends="" throwable=""> ExceptionMapper<T> getExceptionMapper(Class<T> type);
<T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType);
}
@Path("/something/")
class MyResource {
@Context
javax.ws.rs.ext.Providers providers;
@GET
public Response get() {
ContextResolver<StorageEngine> resolver = providers.getContextResolver(StorageEngine.class, MediaType.WILDCARD_TYPE);
StorageEngine engine = resolver.get(StorageEngine.class);
...
}
}
JAX-RS Request Processing
JSON Support
- Maybe old: http://cxf.apache.org/docs/json-support.html
Polymorphic resolution without annotations
1. Configure Jackson object mapper in CXF Provider
-
2. Custom Provider: Serialization / Deserialization Message body reader writer
- example:
- custom serializer, registation with objectMapper: http://www.baeldung.com/jackson-object-mapper-tutorial
- nested deserialization: https://stackoverflow.com/questions/43911622/nested-custom-deserialization-in-java-with-jackson
- custome provider, registration:
-
2.1 Jersey vs CXF Custom Provider
2.2 CXF vs Jersey and Jackson - Explaination
3. ObjectMapperResolver
4. Custom ObjectMapper for Provider
4.1 Add Jackson maven dependency
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.7</version>
</dependency>
4.2 Include Jackson provider bean into your service providers:
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
<jaxrs:server id="clientService" address="/clientservice">
<jaxrs:serviceBeans>
<ref bean="clientBean" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json"/>
<entry key="xml" value="application/xml"/>
</jaxrs:extensionMappings>
<jaxrs:providers>
<ref bean="jaxbProvider"/>
</jaxrs:providers>
</jaxrs:server>
Now all JSON responces from “clientService” are generated by Jackson.
4.3 Jackson configuration
Enable wrapping entities with root element. Exclude null values from JSON responce. This features are disabled by default. To enable it I created my custom ObjectMapper class, that extends from “org.codehaus.jackson.map.ObjectMapper”
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
public class CustomObjectMapper extends ObjectMapper{
public CustomObjectMapper() {
super();
super.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
super.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
}
}
4.4 Then added CustomObjectMapper to "jsonProvider" constructor:
<bean id="jacksonMapper" class="com.xproject.server.util.CustomObjectMapper" />
<bean id="jaxbProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider">
<constructor-arg ref="jacksonMapper" />
</bean>
5. Fasterxml Polymorphic Type Handling
- JAX-RS:
- Uing mixin with a fresh ObjectMapper instance, globally declared mapper does not work
5.1 Custom Ser/Deser
Jax-RS WebClient
Troubleshooting
Proxy Webclient: service is not an interface
Problem:
Rest service class is not interface so CGLIB proxy will be created by JAXRSClientFactory.
https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxrs/client/JAXRSClientFactory.html
Solution:
Add this to class path
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
</dependency>
WebClient Error 400 JAXB expected..
Error: JAXBException occurred : unexpected element (uri:“”, local:“headers”)
Cause:
xmlrootelement is serialized as wrapper element for json object. CXF JAXB always expects it but some clients only send the object.
Solution:
Ignoring the tags may not works correctly. As suggested: https://stackoverflow.com/a/16390260/707704 . The answers above give more information.
private static JacksonJsonProvider jackson_json_provider = new JacksonJaxbJsonProvider() .configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)
