I am attempting to figure out how to use a custom annotation and HK2 to inject something into a Resource method. Because I'm in a Spring webapp environment, I just piled on the existing helloworld-spring-webapp Jersey 2 example. My problem is, is the Resource method is called twice. The first time, the injection happens successfully, the second time, it does not.
InjectionResolver.resolve() method
@Override
public Object resolve(Injectee injectee, ServiceHandle<?> root) {
return "THIS HAS BEEN INJECTED APPROPRIATELY";
}
Binder.configure() method
@Override
protected void configure() {
bind(SampleInjectionResolver.class).to(new TypeLiteral<InjectionResolver<SampleParam>>() {}).in(Singleton.class);
}
ResourceConfig registering of binder
public MyApplication () {
register(new SampleInjectionResolver.Binder());
...
JerseyResource.getHello()
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getHello(@SampleParam String inject) {
System.err.println("EXECUTING!");
System.err.println("*******************************INJECTED: " + inject);
return inject;
}
Server output from a SINGLE call
EXECUTING!
*******************************INJECTED: THIS HAS BEEN INJECTED APPROPRIATELY
EXECUTING!
*******************************INJECTED:
Have I missed a configuration somewhere? I can't figure out why it's being called twice. I'm assuming if I fix that, the issue of the InjectionResolver not working on the 2nd call will be a non-issue.
I faced with the exactly same issue - Twice call of the annotated resource method. After deep investigation, I have found the way, how to use custom annotation in the Jersey 2.x.
Custom annotation class (TestMessage.java):
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
public @interface TestMessage {}
Custom annotation resolver (TestMessageResolver.java):
public class TestMessageResolver {
// InjectionResolver implementation
public static class TestMessageInjectionResolver extends ParamInjectionResolver<TestMessage> {
public TestMessageInjectionResolver() {
super(TestMessageValueFactoryProvider.class);
}
}
// ValueFactoryProvider implementation
@Singleton
public static class TestMessageValueFactoryProvider extends AbstractValueFactoryProvider {
@Inject
public TestMessageValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator injector) {
super(mpep, injector, Parameter.Source.UNKNOWN);
}
@Override
protected Factory<?> createValueFactory(Parameter parameter) {
Class<?> classType = parameter.getRawType();
if (classType == null || (!classType.equals(String.class))) {
return null;
}
return new AbstractContainerRequestValueFactory<String>() {
@Override
public String provide() {
return "testString";
}
};
}
}
// Binder implementation
public static class Binder extends AbstractBinder {
@Override
protected void configure() {
bind(TestMessageValueFactoryProvider.class).
to(ValueFactoryProvider.class).
in(Singleton.class);
bind(TestMessageInjectionResolver.class).
to(new TypeLiteral<InjectionResolver<TestMessage>>(){}).
in(Singleton.class);
}
}
}
Custom annotation usage (JerseyResource.java):
@Path("jersey")
public class JerseyResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getMethod(@TestMessage String message) {
return "getMethod(), message=" + message;
}
}
Resolver registration(SpringJerseyApplication.java):
public class SpringJerseyApplication extends ResourceConfig {
public SpringJerseyApplication() {
register(JerseyResource.class);
register(new TestMessageResolver.Binder());
}
}
Hope it will be helpful :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With