3

I'm building a RESTful service where endpoints are supposed to be generated based on resource file description. Registering resources with implicit method builder handler works just fine, however when I try to replace implicit handler with explicit I'm hitting a wall.

In the example below I've replaced implicit handler Inflector with explicit ItemInflector implementation. String result is expected after execution.

final Resource.Builder resourceBuilder = Resource.builder();
resourceBuilder.path("api/myservice/item");
final ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod("GET");

methodBuilder.produces(MediaType.TEXT_PLAIN_TYPE)
    .handledBy(new ItemInflector<ContainerRequestContext, String>(String.class));

final Resource resource = resourceBuilder.build();
registerResources(resource);

ItenInflector implementation:

public class ItemInflector<DATA extends ContainerRequestContext, RESULT> implements Inflector<DATA, RESULT> {

    private Class<RESULT> type;

    public ItemInflector(Class<RESULT> type) {
        this.type = type;
    }

    @Override
    public RESULT apply(DATA data) {
        return type.cast("Half programmatically generated endpoint");
    }
}

At runtime the following error is thrown when I try to hit endpoint.

Caused by: java.lang.IllegalArgumentException: Type parameter RESULT not a class or parameterized type whose raw type is a class

Could someone clear out what am I doing wrong in the Inflector implementation? How to parametrize or define RESULT type?

Maxim
  • 3,996
  • 8
  • 45
  • 73

1 Answers1

2

The type parameter (<ContainerRequestContext, String>), specified during the ItemInflector instance creation, is lost at runtime. The reason is Javas type erasure behaviour. You have to specify the type in a subclass or use anonymous classes here.

option 1, anonymous class (yes, now the compiler keeps the type information):

methodBuilder.produces(MediaType.TEXT_PLAIN_TYPE)
    .handledBy(new Inflector<ContainerRequestContext, String>(){
        ...
    });

option 2, specify type in a sublcass:

public class ItemInflector implements Inflector<ContainerRequestContext, String> {
....
}

Here is a very detailed information regarding type erasure behaviour: Java generics - type erasure - when and what happens

Community
  • 1
  • 1
Meiko Rachimow
  • 4,196
  • 2
  • 21
  • 41