복붙노트

[SPRING] Spring DI - REST 서비스에서 Autowired 속성이 null입니다.

SPRING

Spring DI - REST 서비스에서 Autowired 속성이 null입니다.

나는 스프링 DI로 시작하고 있지만, 의존성 주입에 어려움을 겪고 있으며, 나쁘게 느껴진다. 바라건대 너희들이 나를 도울 수 있기를!

문제는 @Autowired로 주석 처리 된 속성은 항상 null이라는 것입니다.

메이븐 (Maven) 구조를 가진 몇 가지 프로젝트가 있습니다.

Tomcat 7에서 예제를 실행 중입니다.

내 pom.xml에서 다음 종속성을 사용하고 있습니다.

간단한 생각은 Dependency Injection을 통해 D : \ configuracion.conf에있는 구성 파일에있는 속성의 값을 인쇄 할 수있는 RESTful 서비스를 갖는 것입니다.

com.diegotutor.utility에서 다음 인터페이스가 있습니다.

package com.diegotutor.utility;

public interface ConfigService {

    public String getProperty(final String propertyName);
}

구현자 :

package com.diegotutor.utility.impl;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;

import com.diegotutor.utility.ConfigService;

public class PropertyFileConfigService implements ConfigService{

Properties prop;

public PropertyFileConfigService (final InputStream input) throws IOException {
    if(input == null) {
        throw new IllegalArgumentException("Input stream can't be null");
    }
    prop = new Properties();
    prop.load(input);
}

public PropertyFileConfigService (final String fileName) throws IOException {
    final FileInputStream input = new FileInputStream(fileName);
    prop = new Properties();
    prop.load(input);
}

public PropertyFileConfigService(final Reader input) throws IOException {
    prop = new Properties();
    prop.load(input);
}

public String getProperty(final String propertyName) {
    return prop.getProperty(propertyName);
}

}

com.diegotutor.lessondeliver에는 ConfigService의 주입 된 인스턴스를 사용하고자하는 RESTful 서비스가 있습니다.

package com.diegotutor.lessondeliver;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.diegotutor.utility.ConfigService;

@Path("/")
@Component
public class HelloWorld {

private static final Log log = LogFactory.getLog(HelloWorld.class);

@Autowired
private ConfigService configService;

@Path("/helloworld")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getHello() {
    String host = configService.getProperty("host");
    return "Hello World! HOST" + host;
            // configService IS NULL!! 
            //SO IT THROWS A NULLPOINTER EXCEPTION WHEN INVOKING getProperty ON IT
}
}

마지막으로 /com.diegotutor.lessondeliver/src/main/webapp/WEB-INF/service-beans.xml 다음 XML 응용 프로그램 컨텍스트 파일이 있습니다. 여기서 ConfigService (PropertyFileConfigService) 구현을 사용하여 읽을 구성 파일 :

<?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.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd">

<bean id="configService" class="com.diegotutor.utility.impl.PropertyFileConfigService">
    <constructor-arg type="java.lang.String"
        value="D:\configuracion.conf" />
</bean>

<context:component-scan base-package="com.diegotutor" />

</beans>

분명히이 com.diegotutor.lessondeliver 웹 응용 프로그램의 web.xml에서 service-beans.xml을 ConfigLocation 및 수신기 ContextLoaderListener로 지정하고 RESTful 서비스는 ServletContainer에 의존한다고 명시했습니다.

컨텍스트를 지정하는 경우 : 여기에 제안 된대로 com.diegotutor에서 구성 요소를 찾으려면 component-scan을 지정하고 여기서 제안한대로 새 Statement를 사용하지 않고 Spring을 통해 객체 생성을 강제합니다. 이유는 주석이 달린 configService를 null로 가져 오는 이유는 무엇입니까? Spring이 com.diegotutor.utility.impl.PropertyFileConfigService의 인스턴스를 삽입 할 수없는 이유는 무엇입니까?

어떤 도움을 많이 주시면 감사하겠습니다!

고맙습니다

편집 :

요청에 따라 web.xml은 다음과 같습니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
id="WebApp_ID" version="3.0">

 <display-name>com.diegotutor.lessondeliver</display-name>

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/service-beans.xml</param-value>
 </context-param>

 <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <servlet>
  <servlet-name>jersey-servlet</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>jersey-servlet</servlet-name>
  <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>
</web-app>

해결법

  1. ==============================

    1.당신이 옳았! 문제는 저지가 완전히 봄을 인식하지 못하고 자체 개체를 인스턴스화하는 것입니다. 저지가 (의존성 주입을 통해) Spring 객체 생성을 인식하게하기 위해 Spring + Jersey를 통합해야했습니다.

    당신이 옳았! 문제는 저지가 완전히 봄을 인식하지 못하고 자체 개체를 인스턴스화하는 것입니다. 저지가 (의존성 주입을 통해) Spring 객체 생성을 인식하게하기 위해 Spring + Jersey를 통합해야했습니다.

    통합하는:

    이제 @Autowired가 제대로 작동하고 객체가 더 이상 null이 아닙니다.

    나는 jersey-spring 의존성을 사용할 때 maven에서 사용해야하는 제외 사항에 대해 다소 혼란 스럽지만 다른 문제가 있습니다. :)

    고맙습니다!

  2. ==============================

    2.저지 2 (org.glassfish. *)와의 통합 스프링 :

    저지 2 (org.glassfish. *)와의 통합 스프링 :

    일부 종속성은 불필요 할 수 있습니다. 작업이 완료되면 확인하고 지우십시오.

        <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>
    
    <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>
    

    Spring을 업그레이드하는 동안 / main / webapp / WEB-INF /에서 / main / resources / (세부 사항)로 이동해야했습니다.

    <?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>
    
    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();
            }
        }
    }
    
  3. ==============================

    3.또는 SpringBeanAutoWiringSupport 클래스를 단순히 확장 할 수 있습니다. 이와 같이 public 클래스 DemoRestService는 SpringBeanAutoWiringSupport를 확장합니다. 이 지원 클래스를 확장하면 서비스 클래스의 등록 정보를 자동으로 연결할 수 있습니다.

    또는 SpringBeanAutoWiringSupport 클래스를 단순히 확장 할 수 있습니다. 이와 같이 public 클래스 DemoRestService는 SpringBeanAutoWiringSupport를 확장합니다. 이 지원 클래스를 확장하면 서비스 클래스의 등록 정보를 자동으로 연결할 수 있습니다.

  4. ==============================

    4.또 다른 가능한 옵션은 저지 자원에서 수동으로 autowiring을 호출하는 것입니다.

    또 다른 가능한 옵션은 저지 자원에서 수동으로 autowiring을 호출하는 것입니다.

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

    흠, 당신은 "수동 autowiring"을 얻을 ...

  5. from https://stackoverflow.com/questions/19745187/spring-di-autowired-property-is-null-in-a-rest-service by cc-by-sa and MIT license