2013-03-29 89 views
8

我有一個基本的JAXRS服務,我可以很容易地公開,但有一次我希望使用依賴注入API,我懷疑Google Guice會是最好的之一。考慮到這一點,我試圖整合它,但文檔是有點費勁,我已經不得不四處搜尋,試圖找到的如何讓Google Guice與JaxRS(澤西島)合作

  • 在web.xml
  • 語境的正確組合偵聽器(我應該使用ServletContainer或GuiceContainer)
  • 服務
  • 是否與標註@Singleton或@request或沒有服務(我應該跟標註@Singleton - 文檔說我應該,但隨後表示,它默認爲請求範圍)
  • 是否註釋構造函數參數@InjectParam

但是目前我從Google Guice收到錯誤,他們根據我是否使用@InjectParam註釋來更改。

如果我@InjectParam註釋然後我得到

 Mar 29, 2013 9:52:04 PM com.sun.jersey.spi.inject.Errors processErrorMessages 
    SEVERE: The following errors and warnings have been detected with resource and/or provider classes: 
    SEVERE: The class com.hillingar.server.dao.interfaces.UserDao is an interface and cannot be instantiated. 
    SEVERE: Missing dependency for constructor public com.hillingar.server.SessionUtility(com.hillingar.server.dao.interfaces.UserDao) at parameter index 0 

如果我不註釋然後我得到

Mar 29, 2013 9:54:59 PM com.sun.jersey.spi.inject.Errors processErrorMessages 
SEVERE: The following errors and warnings have been detected with resource and/or provider classes: 
    SEVERE: Missing dependency for constructor public com.hillingar.server.rest.UserService(com.hillingar.server.dao.interfaces.UserDao,com.hillingar.server.SessionUtility) at parameter index 0 
    SEVERE: Missing dependency for constructor public com.hillingar.server.rest.UserService(com.hillingar.server.dao.interfaces.UserDao,com.hillingar.server.SessionUtility) at parameter index 1 

這是我的web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 
    <filter> 
     <filter-name>guiceFilter</filter-name> 
     <filter-class>com.google.inject.servlet.GuiceFilter</filter-class> 
    </filter> 

    <filter-mapping> 
     <filter-name>guiceFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <listener> 
     <listener-class>com.hillingar.server.ServletContextListener</listener-class> 
    </listener> 

    <session-config> 
     <session-timeout> 
      30 
     </session-timeout> 
    </session-config> 
</web-app> 

這是我的ServletContextListener

package com.hillingar.server; 

import java.util.logging.Logger; 

import javax.servlet.ServletContextEvent; 

import com.google.inject.Guice; 
import com.google.inject.Singleton; 
import com.hillingar.server.dao.jdbcImpl.UserJdbc; 
import com.hillingar.server.dao.interfaces.UserDao; 
import com.sun.jersey.guice.JerseyServletModule; 
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; 
import com.sun.jersey.spi.container.servlet.ServletContainer; 

public class ServletContextListener implements javax.servlet.ServletContextListener { 

    Logger logger = Logger.getLogger(this.getClass().getName()); 

    @Override 
    public void contextDestroyed(ServletContextEvent arg0) { 
    } 

     /* 
     * Covered in URL 
     * https://code.google.com/p/google-guice/wiki/ServletModule 
     */ 
    @Override 
    public void contextInitialized(ServletContextEvent arg0) { 

      // Note the user of JerseyServletModule instead of ServletModule 
      // otherwise the expected constructor injection doesn't happen 
      // (just the default constructor is called) 
      Guice.createInjector(new JerseyServletModule() { 
       @Override 
       protected void configureServlets() { 

        /* 
        * Note: Every servlet (or filter) is required to be a 
        * @Singleton. If you cannot annotate the class directly, 
        * you must bind it using bind(..).in(Singleton.class), 
        * separate to the filter() or servlet() rules. 
        * Mapping under any other scope is an error. This is to 
        * maintain consistency with the Servlet specification. 
        * Guice Servlet does not support the 
        * deprecated SingleThreadModel. 
        */ 
        bind(SecurityFilter.class).in(Singleton.class); 
        bind(ServletContainer.class).in(Singleton.class); 

        /* 
        * Filter Mapping 
        * 
        * This will route every incoming request through MyFilter, 
        * and then continue to any other matching filters before 
        * finally being dispatched to a servlet for processing. 
        * 
        */ 

        // SECURITY - currently disabled 
        // filter("/*").through(SecurityFilter.class); 

        /* 
        * Registering Servlets 
        * 
        * This registers a servlet (subclass of HttpServlet) called 
        * ServletContainer, the same one that I would have used in 
        * the web.xml file, to serve any web requests with the 
        * path /rest/* i.e. ... 
        * 
         <servlet> 
          <servlet-name>ServletAdaptor</servlet-name> 
          <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
          <load-on-startup>1</load-on-startup> 
         </servlet> 
         <servlet-mapping> 
          <servlet-name>ServletAdaptor</servlet-name> 
          <url-pattern>/rest/*</url-pattern> 
         </servlet-mapping> 

        */ 
        serve("/rest/*").with(ServletContainer.class); // JAX-RS 

        // Using this and it starts bitching about 
        // com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes. 
        // So presumably wants an Application class that enumerates 
        // all my services? 
        //serve("/rest/*").with(GuiceContainer.class); 

        /* 
        * Bindings 
        */ 
        bind(UserDao.class).to(UserJdbc.class); 
        bind(SessionUtility.class); 
       } 
      }); 
    } 

} 

這是我UserService

package com.hillingar.server.rest; 

import com.google.inject.Inject; 
import com.google.inject.Singleton; 
import java.util.List; 

import javax.servlet.http.HttpServletRequest; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.GET; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.SecurityContext; 

import com.hillingar.server.SessionUtility; 
import com.hillingar.server.dao.interfaces.UserDao; 
import com.hillingar.server.model.User; 
import com.hillingar.server.model.dto.AuthenticationResponse; 

@Path("/user") 
@Produces("application/json") 
@Consumes({"application/xml","application/json"}) 
@Singleton // <-- Added Singleton here 
public class UserService { 

    private UserDao userDao; 
    private SessionUtility sessionManager; 

     /* 
      Error if I annotate with @InjectParam... 

      Mar 29, 2013 9:52:04 PM com.sun.jersey.spi.inject.Errors processErrorMessages 
      SEVERE: The following errors and warnings have been detected with resource and/or provider classes: 
      SEVERE: The class com.hillingar.server.dao.interfaces.UserDao is an interface and cannot be instantiated. 
      SEVERE: Missing dependency for constructor public com.hillingar.server.SessionUtility(com.hillingar.server.dao.interfaces.UserDao) at parameter index 0 

      Error If I don't annotate at all... 
      Mar 29, 2013 9:54:59 PM com.sun.jersey.spi.inject.Errors processErrorMessages 
      SEVERE: The following errors and warnings have been detected with resource and/or provider classes: 
       SEVERE: Missing dependency for constructor public com.hillingar.server.rest.UserService(com.hillingar.server.dao.interfaces.UserDao,com.hillingar.server.SessionUtility) at parameter index 0 
       SEVERE: Missing dependency for constructor public com.hillingar.server.rest.UserService(com.hillingar.server.dao.interfaces.UserDao,com.hillingar.server.SessionUtility) at parameter index 1 

      (both output Initiating Jersey application, version 'Jersey: 1.13 06/29/2012 05:14 PM') 
     */ 
    @Inject 
    public UserService(UserDao userDao, SessionUtility sessionManager) { 
     this.userDao = userDao; 
       this.sessionManager = sessionManager; 
    } 

    @GET 
    public List<User> test(@Context HttpServletRequest hsr) { 
       // USER DAO IS ALWAYS NULL - CONSTRUCTOR INJECTION NOT WORKING 
     User loggedInUser = userDao.findBySessionId(hsr.getSession().getId()); 
       ... 
     return users; 
    } 

} 
+0

如果你注入'UserDao'和'SessionUtility'的領域,而不是作爲構造的一部分,會發生什麼? – condit

+0

我將構造函數更改爲無參數(並刪除了@Inject),然後爲UserDao和SessionUtility創建了getter和setter(帶@Inject的setter)。仍然沒有被打電話。 –

+0

今天早上我改變了兩件事,然後它開始按預期工作,1)我更改了我的servlet上下文偵聽器來擴展GuiceServletContextListener並重寫getInjector方法,2)在注入器內改回使用serve(「/ rest/*」 )。隨着(GuiceContainer.class);這一次它工作! –

回答

5

改變了ServletContextListener到

package com.hillingar.server; 

import java.util.logging.Logger; 

import javax.servlet.ServletContextEvent; 

import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.Singleton; 
import com.google.inject.servlet.GuiceServletContextListener; 
import com.hillingar.server.dao.jdbcImpl.UserJdbc; 
import com.hillingar.server.dao.interfaces.UserDao; 
import com.hillingar.server.rest.UserService; 
import com.sun.jersey.guice.JerseyServletModule; 
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; 
import com.sun.jersey.spi.container.servlet.ServletContainer; 

// (1) Extend GuiceServletContextListener 
public class ServletContextListener extends GuiceServletContextListener { 

    Logger logger = Logger.getLogger(this.getClass().getName()); 

    // (1) Override getInjector 
    @Override 
    protected Injector getInjector() { 
     return Guice.createInjector(new JerseyServletModule() { 
      @Override 
      protected void configureServlets() { 
       bind(SecurityFilter.class).in(Singleton.class); 
       bind(UserService.class);// .in(Singleton.class); 
       bind(ServletContainer.class).in(Singleton.class); 

       // (2) Change to using the GuiceContainer 
       serve("/rest/*").with(GuiceContainer.class); // <<<<--- 

       bind(UserDao.class).to(UserJdbc.class); 
       bind(SessionUtility.class); 
      } 
     }); 
    } 
}