[SPRING] Spring DI - REST 서비스에서 Autowired 속성이 null입니다.
SPRINGSpring 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.당신이 옳았! 문제는 저지가 완전히 봄을 인식하지 못하고 자체 개체를 인스턴스화하는 것입니다. 저지가 (의존성 주입을 통해) Spring 객체 생성을 인식하게하기 위해 Spring + Jersey를 통합해야했습니다.
당신이 옳았! 문제는 저지가 완전히 봄을 인식하지 못하고 자체 개체를 인스턴스화하는 것입니다. 저지가 (의존성 주입을 통해) Spring 객체 생성을 인식하게하기 위해 Spring + Jersey를 통합해야했습니다.
통합하는:
이제 @Autowired가 제대로 작동하고 객체가 더 이상 null이 아닙니다.
나는 jersey-spring 의존성을 사용할 때 maven에서 사용해야하는 제외 사항에 대해 다소 혼란 스럽지만 다른 문제가 있습니다. :)
고맙습니다!
-
==============================
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.또는 SpringBeanAutoWiringSupport 클래스를 단순히 확장 할 수 있습니다. 이와 같이 public 클래스 DemoRestService는 SpringBeanAutoWiringSupport를 확장합니다. 이 지원 클래스를 확장하면 서비스 클래스의 등록 정보를 자동으로 연결할 수 있습니다.
또는 SpringBeanAutoWiringSupport 클래스를 단순히 확장 할 수 있습니다. 이와 같이 public 클래스 DemoRestService는 SpringBeanAutoWiringSupport를 확장합니다. 이 지원 클래스를 확장하면 서비스 클래스의 등록 정보를 자동으로 연결할 수 있습니다.
-
==============================
4.또 다른 가능한 옵션은 저지 자원에서 수동으로 autowiring을 호출하는 것입니다.
또 다른 가능한 옵션은 저지 자원에서 수동으로 autowiring을 호출하는 것입니다.
@Context private ServletContext servletContext; @PostConstruct public void init() { SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, servletContext); }
흠, 당신은 "수동 autowiring"을 얻을 ...
from https://stackoverflow.com/questions/19745187/spring-di-autowired-property-is-null-in-a-rest-service by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 커스텀 컨트롤러 메소드를위한 Spring Boot에서 HAL 직렬화 사용 (0) | 2018.12.12 |
---|---|
[SPRING] 클라이언트가 보낸 요청은 구문 상 올바르지 않습니다.-Spring MVC + JDBC 템플릿 (0) | 2018.12.12 |
[SPRING] RestTemplate은 스레드로부터 안전한가요? (0) | 2018.12.12 |
[SPRING] 객체 자체에서 AOP 프록시 가져 오기 (0) | 2018.12.12 |
[SPRING] Spring에서 필터에 던져진 예외를 관리하는 방법? (0) | 2018.12.12 |