jax-rs plugin custom serializer and deserializer - jax-rs

is there a way in jax-rs to plugin custom serializer and deserializer,
This is kind of important to migrate some of the existing consumers to REST world.

You should define a custom Provider with message body readers/writers:
Entity providers supply serialization and/or deserialization services between resource representations and their associated Java types. An entity provider that supports deserialization of a representation to a Java type implements the MessageBodyReader interface. An entity provider that supports serialization of a Java type to a representation implements the MessageBodyWriter interface.
See http://www.oracle.com/technetwork/articles/javaee/jax-rs-159890.html

Related

JAX-RS: serializing a POJO fails on payara micro

After moving our application war from Glassfish3 to a deployment with Payara Micro, the JAX-RS serialization (jersey + jackson) doesn't work any more.
Thanks to Adam, we solved the issue with serializing pure collections, we now encounter similar errors when returning POJOs:
#GET
#Produces("application/json")
public BirdyTO findAllDaBirdy() {
return getBirdy();
}
where BirdyTO is a POJO which contains other POJOS and/or collections of POJOS.
That one gives us the error:
MessageBodyWriter not found for media type=application/json;charset=utf-8, type=class org.example.BirdyTO, genericType=class org.example.BirdyTO.
Strange thing is that similar interfaces in same application work fine.
Any idea?
Mapping of POJOs to JSON is not standardized in Java EE. Glassfih 4/Payara use MOXy to map POJO to JSON by default, which uses JAXB for the mapping. See [this post by Reza Rahman] (https://blogs.oracle.com/theaquarium/entry/moxy_is_the_new_default). It is possible that BirdyTO cannot be mapped by Moxy.
If you want to use Jackson, you have to:
disable default Moxy feature (by setting jersey.config.server.disableMoxyJson property to true)
add Jackson library into your app (com.fasterxml.jackson.jaxrs)
turn on the JacksonFeature (provided by the Jackson library) in your JAX-RS application
More info how to do it in this answer: Customizing JSON marhsalling with GlassFish v4

How to write single objectMapper for spring-data-rest and to my #RestController class

I wrote a UnwrappingBeanSerializer for my entity. Currently this serializer was registered using ConfigureJacksonObjectMapper
This serializer is working fine for REST APIs generated from spring-data-rest. But I have a custom #RestController for the same entity, But it doesn't know about the serializer registered in spring-data-rest configuration.
I want to serialize my response with UnwrappingBeanSerializer both in spring-data-rest APIs and also to my custom controllers.
How to achieve this?
I also tried with #JsonSerialize on my entity class. But I am unable to create bean for unWrappingBeanSerializer with BeanSerializerBase
Regular #RestController and Spring Data REST controllers have different flows and configuration. If you are using Spring Data REST, you'd better use #RepositoryRestController for custom endpoints of the same resource, this will use the same Spring Data REST chain and its configuration, like the one you used in ConfigureJacksonObjectMapper, otherwise your ObjectMapper is visible only for Spring Data REST.
If you want to have #RestController and use the same ObjectMapper for both - you need to have two configurations: one for Spring Data REST (like you already have) and another for regular controllers, so just register it in Spring context (for instance, if you are using Spring MVC, see Customize the Jackson ObjectMapper).

Request-scoped context field injections into RESTEasy singletons

While trying to embed RESTEasy with singleton resources in OSGi (using something similar to resteasy-osgi-bundle), to my surprise field-injected #Context UriInfo was available and valid on each request.
Digging deeper I found proxy magic and ThreadLocal in ResteasyProviderFactory. All well and good, but I cannot find any reference to such a behavior in docs, neither in RESTEasy's one nor in JAX-RS spec.
In Jersey docs we can find something like:
The exception exists for specific request objects which can injected even into constructor or class fields [of resources with singleton scope — OP]. For these objects the runtime will inject proxies which are able to simultaneously server more request. These request objects are HttpHeaders, Request, UriInfo, SecurityContext. These proxies can be injected using the #Context annotation.
How does it look in RESTEasy? Is the current implementation stable or experimental? What is the set of request-specific classes that can be injected into singletons?
It's not experimental. This behavior (for a set of common objects) is specified in the JAX-RS spec. There aren't any anchors in the spec page to link to a certain section, but where you should look is Chapter 5: Context. I'll post some snippet here.
5.1 Concurrency
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in section 5.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
5.2 Context Types
This section describes the types of context available to resource classes, providers and Application subclasses.
5.2.1 Application
The instance of the application-supplied Application subclass can be injected into a class field or method parameter using the #Context annotation. Access to the Application subclass instance allows configuration information to be centralized in that class. Note that this cannot be injected into the Application subclass itself since this would create a circular dependency.
5.2.2 URIs and URI Templates
An instance of UriInfo can be injected into a class field or method parameter using the #Context annotation. UriInfo provides both static and dynamic, per-request information, about the components of a request URI. E.g. the following would return the names of any query parameters in a request:
5.2.3 Headers
An instance of HttpHeaders can be injected into a class field or method parameter using the #Context annotation. HttpHeaders provides access to request header information either in map form or via strongly typed convenience methods. E.g. the following would return the names of all the headers in a request:
5.2.4 Content Negotiation and Preconditions
JAX-RS simplifies support for content negotiation and preconditions using the Request interface. An instance of Request can be injected into a class field or method parameter using the #Context annotation. The methods of Request allow a caller to determine the best matching representation variant and to evaluate whether the current state of the resource matches any preconditions in the request...
5.2.5 Security Context
The SecurityContext interface provides access to information about the security context of the current request. An instance of SecurityContext can be injected into a class field or method parameter using the #Context annotation. The methods of SecurityContext provide access to the current user principal, information about roles assumed by the requester, whether the request arrived over a secure channel and the authentication scheme used.
5.2.6 Providers
The Providers interface allows for lookup of provider instances based on a set of search criteria. An instance of Providers can be injected into a class field or method parameter using the #Context annotation.
One thing to note is that there may more types that can be injected, but any not listed above would be implementation specific. Here is the list from the RESTeasy documentation in the section Chapter 15. #Context
The #Context annotation allows you to inject instances of javax.ws.rs.core.HttpHeaders, javax.ws.rs.core.UriInfo, javax.ws.rs.core.Request, javax.servlet.HttpServletRequest, javax.servlet.HttpServletResponse, javax.servlet.ServletConfig, javax.servlet.ServletContext, and javax.ws.rs.core.SecurityContext objects.
Though the documentation doesn't make any distinction between field and parameter injection, from what I remember, I think I was able to get HttpServletRequest injected into a field. But I would just test them all to make sure.

How to stop wcf service generating entity framework references

I have a WCF service containing an entity framework project.
I also have DTO classes that I use to expose the data. The entity objects get mapped to DTO objects.
When I generate a service proxy I am seeing both the entity object and the DTO object.
If I have a table called Product I get a Product and a Product1 reference.
This didn't use to happen.
What have I done to cause this and how can I stop my entity objects being exposed?
More Info:
When EF generates a model object from the database, it adds a data contract attribute like this:
[EdmEntityTypeAttribute(NamespaceName="KernMobile_V5Model", Name="JobMaster")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class JobMaster : EntityObject
I assume this means that it will be exposed by the service?
The service only exposes objects that are used in the service operations, or are specified as a known type to be exposed.
If your client proxy is generating an object for these entity framework objects, you must be exposing them through your service somehow. This can be as request or response objects, or as properties on those objects.

WCF Web Service parameter

I have a WCF web service that implements a parameter List<ICustomObject>. In the generated client code, the parameter is List<Object>?!? How can I make it accept the List<ICustomObject>, as an interface, or do I have to use a concrete class? I have the concrete class marked as [KnowType] and [Serializable]
You should use concrete class, because you should set DataMember and DataContract for it to serilize it, and with interface you can't do this.
WCF works with anything that is expressible in XML schema - interfaces per se are not.
You need to define your lists to be lists of concrete types - otherwise the client will not be able to know what to do with the list and will fall back to a List<Object>.