Looking to wire a concrete class to a parameter for a REST server's @POST
method within blueprint.xml
.
Jackson data binding cannot find the concrete implementation for the method's send
parameter.
The REST server has a single send
method, defined as:
public interface NotificationServer {
@POST
Response send(NotificationRequest notificationRequest);
}
The NotificationRequest
is also an interface:
public interface NotificationRequest {
A concrete implementation of NotificationServer
, called EmailNotificationServerImpl
, implements the interface:
public class EmailNotificationServerImpl implements NotificationServer {
@Override
public Response send(final NotificationRequest request) {
The relevant parts of blueprint.xml
include:
<bean class="EmailNotificationServerImpl" id="emailNotificationServerImpl">...</bean>
<bean class="NotificationRequestImpl" id="notificationRequestImpl" />
<service interface="NotificationRequest" ref="notificationRequestImpl" />
The Jackson error message:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of NotificationRequest: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
It is possible to deserialize the class using:
@JsonDeserialize(as = NotificationRequestImpl.class)
public interface NotificationRequest {
While this works, it doesn't fully decouple the implementation from the interface.
How can the concrete implementation be wired in blueprint.xml
so that the @JsonDeseralize
annotation is not necessary?
Use a custom provider that extends JacksonJsonProvider in JAX-RS server definition within the <jaxrs:providers>
tag.
Or use a custom deserializer that extends StdSerializer:
@JsonDeserialize(using = YourDeserializer.java)
Or use polymorphism and @JsonTypeInfo
+ @JsonSubtypes
annotations.