RESTeasy服务中的Spring自动装配失败

时间:2014-04-17 06:24:53

标签: spring jboss resteasy

我有一个简单的服务,无法自动装配bean。 虽然通过上下文获得相同的bean成功。 因此,存储库中的bean创建和注册正在运行,但自动装配却没有。 更改服务中的字段类(MyRepository - > YourRepository),会抛出这样的bean不存在的错误,因此自动装配机制正在运行。

可能遗漏的任何想法?

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

    @Autowired 
    private MyRepository myRepository; // is not autowired and is null

    @GET
    @Path("/{param}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response printMessage(@PathParam("param") String msg) {
        return Response.ok(
    AppContext.getContext().getBean("myRepository") == myRepository)
              .build(); // false
    }

    public void setMyRepository(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}
上面的

AppContextApplicationContextAware

的简单实现

存储库

@Repository
public interface MyRepository extends MongoRepository<MyEntity, String> {

}

没有.xml配置,并且通过

初始化spring
public class MyInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        container.addListener(new ResteasyBootstrap());

        final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        ContextLoaderListener springListener = new ContextLoaderListener(rootContext);
        rootContext.register(MyConfiguration.class);
        container.addListener(springListener);
    }
}

和配置类

@Configuration
@EnableMongoRepositories("my.package.repository")
@ComponentScan("my.package")
public class MyConfiguration {

    @Bean
    public MongoTemplate mongoTemplate() throws UnknownHostException {
        return new MongoTemplate(new MongoClient("localhost"), "db");
    }
}

2条评论后编辑

我正在使用以下库来进行RESTeasy - spring集成。 我需要其他一些吗?

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-spring</artifactId>
        <version>3.0.8.Final</version>
    </dependency>

我认为JAX-RS和RESTeasy工作正常,因为服务正常,我可以在JBoss上部署时通过Web访问它

编辑解决方法

如果我创建以下构造函数,则服务已正确初始化,但感觉更像是一种解决方法

public RestService() {
    this.myRepository = MyContext.getContext().getBean(MyRepository.class);
}

MyContext类更清晰

@Component
public class MyContext implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;   
    }

    public static ApplicationContext getContext() {
        return context;
    }
}

2 个答案:

答案 0 :(得分:2)

Spring可能设置正确,但这并不意味着正确设置了Spring + RestEasy集成。

我发布的代码是我使用的web.xml配置(使用RestEasy 3.0.6和Spring 3.2.8)并正确设置RestEasy和Spring之间的集成,并设置Spring MVC(/ api由RestEasy处理,其他一切都由Spring MVC处理。

<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>my.package.config.ApplicationConfig</param-value>
    </context-param>

    <context-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>web</param-value>
    </context-param>

    <context-param>
        <param-name>resteasy.servlet.mapping.prefix</param-name>
        <param-value>/api</param-value>
    </context-param>

    <!-- Spring + RESTEasy -->
    <listener>
        <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>

    <listener>
        <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
    </listener>

    <!-- RESTEasy Servlet-->
    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

    <!-- Spring MVC Servlet -->
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>my.package.config.MvcConfig</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file></welcome-file>
    </welcome-file-list>

    <error-page>
        <error-code>404</error-code>
        <location>/WEB-INF/jsp/error404.jsp</location>
    </error-page>
</web-app>

答案 1 :(得分:2)

管理自己解决问题。

正确的解决方案是替换

public class MyInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        container.addListener(new ResteasyBootstrap());

        final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        ContextLoaderListener springListener = new ContextLoaderListener(rootContext);
        rootContext.register(MyConfiguration.class);
        container.addListener(springListener);
    }
}

public class MyInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        container.addListener(new ResteasyBootstrap());

        container.addListener(new SpringContextLoaderListener());
    }
}

但在这种情况下,我失去了使用AnnotationConfigWebApplicationContext的可能性。 此外,可以按如下方式更改初始化程序以保留注释上下文。

public class MyInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        container.addListener(new ResteasyBootstrap());

        final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        ContextLoaderListener springListener = new ContextLoaderListener(rootContext) {
            @Override
            protected ContextLoader createContextLoader() {
                return new SpringContextLoader();
            }
        };
        rootContext.register(MyConfiguration.class);
        container.addListener(springListener);
    }
}