Spring DI - Autowired property is null in a REST service

前端 未结 4 1146
攒了一身酷
攒了一身酷 2020-11-27 17:49

I\'m getting started with Spring DI, but I\'m struggling with dependency injection and the worse part is that I\'m not even sure why as it seems ok to me. Hopefully you guys

相关标签:
4条回答
  • 2020-11-27 18:37

    Integration Spring with Jersey 2 (org.glassfish.*):

    Maven

    Some dependencies may be unnecessary, please check & clear it after things got working.

        <properties>
            <jersey.version>2.5</jersey.version>
        </properties>
    
        <!-- Jersey -->
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
            <artifactId>jersey-container-servlet</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-inmemory</artifactId>
            <version>${jersey.version}</version>
        </dependency>
    
        <!-- Jersey + Spring -->
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring3</artifactId>
            <version>${jersey.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    

    web.xml

    <servlet>
        <servlet-name>my-rest-service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>my.package.with.rest.services</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>my-rest-service</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>
    

    applicationContext.xml

    During the Spring upgrading I had to move it from /main/webapp/WEB-INF/ to /main/resources/ (details).

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
        <context:annotation-config />
        <context:component-scan base-package="my.package.with.rest.services" />
    </beans>
    

    Example REST service

    public interface MyService
    {
        String work(String s);
    }
    
    ...
    
    @Service
    public class MyServiceImpl implements MyService
    {
        @Override
        public String work(String s)
        {
            return "Hello, " + s;
        }
    }
    
    ...
    
    @Path("demo/")
    @Component
    public class DemoRestService
    {
        @Autowired
        private MyService service;
    
        @GET
        @Path("test")
        public Response test(@FormParam("param") String par)
        {
            try
            {
                String entity = service.work(par);
                return Response.ok(entity).build();
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Epic REST Failure").build();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 18:41

    Another possible option is to manually invoke autowiring in your jersey resource:

    @Context
    private ServletContext servletContext;
    
    @PostConstruct
    public void init() {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext);
    }
    

    Hmm, you get a "manual autowiring"...

    0 讨论(0)
  • 2020-11-27 18:47

    or you can simply extend SpringBeanAutoWiringSupport class. Like this: public class DemoRestService extends SpringBeanAutoWiringSupport. By extending this support class, properties of your service class can be auto-wired.

    0 讨论(0)
  • 2020-11-27 18:48

    You were right! It seems that the problem is that Jersey is totally unaware of Spring and instantiates its own object. In order to make Jersey aware of Spring object creations (through dependency injection) I had to integrate Spring + Jersey.

    To integrate:

    1. Add maven dependencies

      <dependency>
          <groupId>com.sun.jersey.contribs</groupId>
          <artifactId>jersey-spring</artifactId>
          <version>1.17.1</version>
          <exclusions>
              <exclusion>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-core</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-beans</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-context</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-web</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      
    2. Use SpringServlet for jersey-servlet in web.xml

      <servlet>
          <servlet-name>jersey-servlet</servlet-name>
          <servlet-class>
              com.sun.jersey.spi.spring.container.servlet.SpringServlet
          </servlet-class>
          <load-on-startup>1</load-on-startup>
      </servlet>
      

    Now the @Autowired works properly and the object is not null anymore.

    I'm a little bit confused about the exclusions I have to use in maven when using jersey-spring dependency, but that's another issue :)

    Thank you!

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