users@jersey.java.net

[Jersey] bug candidate when creating jersey endpoint programmatically

From: Stanchevich, Andrei <andrei.stanchevich_at_citi.com>
Date: Tue, 31 May 2016 11:58:42 +0000

Hello,

Unfortunately I couldn't find any way to contribute into the bug-tracker directly, but hopefully this mail will reach the destination.

I am trying to create jersey end-point in runtime, all looks fine except for the method parameters. I use the code below:

    public void add(Object object) {
        Class<? extends Object> clazz = object.getClass();
        final Resource.Builder resourceBuilder = Resource.builder().path(clazz.getSimpleName());

        for (Method method: clazz.getDeclaredMethods()) {
            Builder methodBuilder = resourceBuilder
                .addChildResource(method.getName() + "/{string}")
                .addMethod("GET")
                .produces(MediaType.TEXT_PLAIN_TYPE)
                .handledBy(object, method);


            List<Parameter> parameters = new LinkedList<>();
            int index = 1;
            for(Class<?> type : method.getParameterTypes()) {
                parameters.add(Parameter.create(clazz, clazz, true, type, type, new Annotation[] {new MyPathParam(index++)}));
            }

            methodBuilder
                .handlerParameters(parameters);
        }
        final Resource resource = resourceBuilder.build();
        registerResources(resource);
    }

I expect that the first argument of the method will bear the @PathParam annotation, however getting the below warning in logs:

May 31, 2016 2:51:50 PM org.glassfish.jersey.internal.Errors logErrors
WARNING: The following warnings have been detected: WARNING: A HTTP GET method, public java.lang.String com.example.service.MyService.cool(java.lang.String), should not consume any entity.

I have debugged the code and found that even though the handler passed to the below method has all parameters with right annotations, the invocable instance is missing annotations because the parameters attribute is initialized based on handlerClass and not on the handler instance, resulting in parameters getting lost during the build stage.

    private Invocable(MethodHandler handler, Method definitionMethod, Method handlingMethod, boolean encodedParameters,
                      Type routingResponseType) {
       ...
        this.parameters = Collections.unmodifiableList(Parameter.create(
                handlerClass, definitionMethod.getDeclaringClass(), definitionMethod, encodedParameters));
    }

Kind regards,
Andrei.