How to enable CDI inject in web service (jaxrs/jersey) on java se running grizzly?

前端 未结 3 1488
南笙
南笙 2020-12-03 05:38

How do I allow CDI injection of resources into restful web service resources? I am running on standard java using weld 2 (cdi), jersey (jaxrs), and grizzly (web server). H

相关标签:
3条回答
  • 2020-12-03 06:19

    After seeing this stackoverflow post, I implemented the following solution. Not sure if it is the best route to take, but it worked.

    I created an hk2 Binder and registered the Binder:

    public class WebServiceBinder extends AbstractBinder {
    
      @Override
      protected void configure() {
        BeanManager bm = getBeanManager();
        bind(getBean(bm, StudentRepository.class))
            .to(StudentRepository.class);
      }
    
      private BeanManager getBeanManager() {
        // is there a better way to get the bean manager?
        return new Weld().getBeanManager();
      }
    
      private <T> T getBean(BeanManager bm, Class<T> clazz) {
        Bean<T> bean = (Bean<T>) bm.getBeans(clazz).iterator().next();
        CreationalContext<T> ctx = bm.createCreationalContext(bean);
        return (T) bm.getReference(bean, clazz, ctx); 
      }
    }
    

    Then modified the ResourceConfig instantiation from above to:

    final ResourceConfig resourceConfig = new ResourceConfig()
        .packages("training.webservice")
        .register(new JacksonFeature())
        .register(new WebServiceBinder());
    
    0 讨论(0)
  • 2020-12-03 06:24

    The selected answer dates from a while back. It is not practical to declare every binding in a custom HK2 binder. I just had to add one dependency. Even though it was designed for Glassfish it fits perfectly into other containers. I'm using Tomcat / Grizzly.

       <dependency>
            <groupId>org.glassfish.jersey.containers.glassfish</groupId>
            <artifactId>jersey-gf-cdi</artifactId>
            <version>2.14</version>
        </dependency>
    

    Here is an example with JerseyTest (same principle if you run it from a main method). I just had to declare a dependency on weld-se and declare a Weld container before instantiating my resources - as you also did - and it works out of the box.

    public class GrizzlyTest extends JerseyTest {
        private Weld weld;
        private WeldContainer container;
    
        @Override
        protected Application configure() {
            weld = new Weld();
            container = weld.initialize();
            return new ResourceConfig(MyResource.class);
        }
    
        @Test
        public void test() {
            System.out.println(target("myresource").request().get(String.class));
        }
    
        @After
        public void after() {
            weld.shutdown();
        }
    }
    
    0 讨论(0)
  • 2020-12-03 06:31

    Since at least Weld 2.2.0.Final there is no need to mess up with HK2 Binder.

    As official Weld documentation states you just need to register org.jboss.weld.environment.servlet.Listener. Code snipped from doc:

    public class Main {
        public static void main(String[] args) throws ServletException, LifecycleException {
            Tomcat tomcat = new Tomcat();
            Context ctx = tomcat.addContext("/", new File("src/main/resources").getAbsolutePath());
    
            Tomcat.addServlet(ctx, "hello", HelloWorldServlet.class.getName());
            ctx.addServletMapping("/*", "hello");
    
            ctx.addApplicationListener(Listener.class.getName());
    
            tomcat.start();
            tomcat.getServer().await();
        }
    
        public static class HelloWorldServlet extends HttpServlet {
            @Inject
            private BeanManager manager;
    
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                resp.setContentType("text/plain");
                resp.getWriter().append("Hello from " + manager);
            }
        }
    }
    

    Above servlet listener manages the whole lifecycle of the Weld container. So there is no need to:

     Weld weld = new Weld();
     WeldContainer container = weld.initialize();
    

    UPDATE As @EdMelo pointed out, Grizzly HTTP server is not a fully compliant Servlet container. I didn't know this, thanks for this hint. So I'm not sure, if my answer still applies here.

    0 讨论(0)
提交回复
热议问题