JAX-RS 2.1 parameter type Object.class

552 Views Asked by At

Having this example JAX-RS web-service, the second parameter of the getByAttribute is of the type Object.class.

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/POJOService")
public interface POJOService extends BasicService {

    @GET
    @Path("/getByAttribute")
    SampleObject getByAttribute(@QueryParam("attribute") String attribute, @QueryParam("value") Object value);

}

This will result in an error:

Payload: Parameter Class java.lang.Object has no constructor with single String parameter, static valueOf(String) or fromString(String) methods

I was thinking of adding a provider of javax.ws.rs.ext.ParamConverterProvider which will pass the type in the JSON string. But maybe there is a best practice solutions for this problem?

Migrating the communication layer of an existing enterprise server/client application to JAX-RS 2.1.
Using Apache CXF and Eclipse Rest Client for MicroProfile.

EDIT: The client will call the service with different types:

service.getByAttribute("name", "example"); // string, used for this test which throws the exception
service.getByAttribute("id", 99); // integer
service.getByAttribute("author", user); // object instace of User.class
1

There are 1 best solutions below

0
flavio.donze On

I found manged to configure the ObjectMapper to add the typing information:

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);

There is also other typing configurations:

JAVA_LANG_OBJECT
This value means that only properties that have Object as declared type (including generic types without explicit type) will use default typing.

NON_CONCRETE_AND_ARRAYS
Value that means that default typing will be used for all types covered by OBJECT_AND_NON_CONCRETE plus all array types for them.

NON_FINAL
Value that means that default typing will be used for all non-final types, with exception of small number of "natural" types (String, Boolean, Integer, Double), which can be correctly inferred from JSON; as well as for all arrays of non-final types.

OBJECT_AND_NON_CONCRETE
Value that means that default typing will be used for properties with declared type of Object or an abstract type (abstract class or interface).

I also have to register a ParamConverterProvider which considers the ObjectMapper settings for all parameter passed:

@Provider
public class ObjectMapperParamConverterProvider implements ParamConverterProvider {

    @Override
    public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType, final Annotation[] annotations) {
        ObjectMapper mapper = ...;
        return new ParamConverter<T>() {
            @Override
            public T fromString(final String value) {
                try {
                    T result = mapper.readValue(value, rawType);
                    return result;
                } catch (IOException e) {
                    throw new ProcessingException(e);
                }
            }

            @Override
            public String toString(final T value) {
                try {
                    String result = mapper.writeValueAsString(value);
                    return result;
                } catch (JsonProcessingException e) {
                    throw new ProcessingException(e);
                }
            }
        };
    }
}