Dependency Injection Using CDI with Jersey with / without Abstract Binding

First of all, this is not a stubborn question, and I read most of the related questions in SO. I am looking for advice if a solution is implemented below - the correct approach / method.

I read a lot of tutorials on how to implement DI in a jersey-based web application, and most of them recommend it to create a beans.xml in WEB-INF/* to enable CDI, but I am wondering if using Jersey AbstractBinder to achieve that same result?

I have a jersey-webapp that has web.xml

  <servlet> <servlet-name>Test Jersey</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>com.test.config.AppConfig</param-value> </init-param> 

And com.test.config.AppConfig as it should

 public class AppConfig extends ResourceConfig { public AppConfig() { AbstractBinder binder = new AbstractBinder() { @Override protected void configure() { bind(Impl.class).to(Interface.class).in(Singleton.class); } }; register(binder); register(MultiPartFeature.class); packages("..."); //packages } } 

and then I annotate the interfaces and the implementation is injected

 @Inject private SomeInterface someInterface; 

The work is just fine. No matter what I want to be entered, I include it in the binder , and then I specify the injection point , and it is entered.

There is no beans.xml directory in the WEB-INF/ directory, and I wonder if AbstractBinder uses the AppConfig inside, which extends ResourceConfig , to eliminate the need to declare beans.xml ?

Adding beans.xml will probably allow you to scan classes that would pave the way for DI when we annotate classes using @Component or @ManagedBean .

Despite this, I would be glad to hear your feedback / recommendations / suggestions / recommendations on whether

  • Stick to the existing solution (shown above) for DI in Jersey, because ....?
  • Switch to annotating classes (which you must enter) and use beans.xml annotation-discovery, because ...?
  • Jersey uses HK2 by default, is it worth using a different DI container or is HK2 good enough?
  • What is your opinion on Jersey Spring DI versus JavaEE 6 CDI for DI purposes only?

Are there many guides that state that CDI is not supported by Tomcat? but worked above using AbstractBinder , and I assume it is because I programmatically bind? Any comments.

0
source share
1 answer

I don't have clear answers, and maybe they don't exist. Not least because Weld SE Support was introduced in version 2.15 of the Jersey , and this, of course, is not without reason. But I would like to try:

  • The presented solution is perfect for non-complex project structures, but declaring each binding may not be the best solution.
  • You do not need to use beans.xml . Annotations and auto-linking work fine with some extra effort (see below).
  • I'm not sure about this, but would say that Seld seems to be more advanced. And, of course, you could mix a little CDI.
  • (no answer here)

Here is an example that I think might be interesting:

Dependencies (Maven):

 <dependency> <groupId>org.glassfish.hk2</groupId> <artifactId>hk2-metadata-generator</artifactId> <version>2.5.0-b05</version> <!-- HK2 version int. used by Jersey 2.23.2 --> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> </dependency> 

Application event listener:

 import org.glassfish.hk2.api.*; import org.glassfish.jersey.server.*; @Provider public class ApplicationListener implements ApplicationEventListener { @Inject ServiceLocator serviceLocator; @Override public void onEvent(ApplicationEvent event) { switch (event.getType()) { case INITIALIZATION_FINISHED: onInitFinished(); break; case DESTROY_FINISHED: case INITIALIZATION_APP_FINISHED: case INITIALIZATION_START: case RELOAD_FINISHED: default: break; } } @Override public RequestEventListener onRequest(RequestEvent requestEvent) { return null; } public void onInitFinished() { populate(serviceLocator); } private void populate(ServiceLocator serviceLocator) { DynamicConfigurationService dcs = serviceLocator.getService(DynamicConfigurationService.class); Populator populator = dcs.getPopulator(); try { populator.populate(); } catch (IOException | MultiException e) { throw new MultiException(e); } } } 

The contract:

 import org.jvnet.hk2.annotations.Contract; @Contract public interface ExampleService { void executeSomething(); } 

One or more services:

 import javax.inject.Named; import org.jvnet.hk2.annotations.Service; @Service @Named("bar") public class BarService implements ExampleService { @Override public void executeSomething() { /* doBar */ } } 

Using:

 @Path("/") public class TestResource { // either ... @Inject @Named("bar") private ExampleService bar; // or ... @Inject private IterableProvider<ExampleService> services; } 

Just an option to get rid of beans.xml (which I never used or never saw) or declarations inside ResourceConfig , but it may find interested parties :)

Also, it looks like Jersey 3.0 is being sent ^^

Have a nice day!

0
source

Source: https://habr.com/ru/post/976351/


All Articles