jersey-spring3实例化Spring管理的bean(null!) [英] jersey-spring3 instantiating Spring-managed bean (null!)

查看:188
本文介绍了jersey-spring3实例化Spring管理的bean(null!)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我首先想指出,这是我在职业生涯中遇到的时间浪费的最大问题。 (过了两天,现在基本上是0进度)。我尝试的每一个解决方案或解决方案都没有起作用,所以我被封锁了,非常绝望的帮助。



简而言之,问题在于,泽西/ HK2似乎总是在Spring已经被Spring实例化之前实例化了Spring管理的bean,它告诉我 jersey-spring3 没有完成任务,或至少没有使用我目前的设置(或者到目前为止我已经尝试过的〜50个设置的任何一个)。 )



请注意,当我使用空构造函数时,这些资源字段在运行时为空。



我不明白为什么我当前的设置不起作用,因为我本质上是复制此在线示例



任何帮助都不胜感激!



配置



- - - - - pom.xml - - - - -

 <! -  ...  - > 

<依赖关系>

<! - Spring依赖关系 - >

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-core< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-context< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-web< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-instrument< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-instrument-tomcat< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-orm< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-tx< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-aop< / artifactId>
< version> $ {spring.version}< / version>
<排除>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-core< / artifactId>
< / exclusion>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-beans< / artifactId>
< / exclusion>
< / exclusions>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-core< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-config< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-ldap< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-parent< / artifactId>
< version> $ {spring.version}< / version>
< classifier> tests< / classifier>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-config< / artifactId>
< version> $ {spring.version}< / version>
< classifier> tests< / classifier>
< / dependency>

<依赖关系>
< groupId> org.springframework.security< / groupId>
< artifactId> spring-security-acl< / artifactId>
< version> $ {spring.version}< / version>
<排除>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-context< / artifactId>
< / exclusion>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-support< / artifactId>
< / exclusion>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-jdbc< / artifactId>
< / exclusion>
< exclude>
< groupId> org.springframework< / groupId>
< artifactId> spring-dao< / artifactId>
< / exclusion>
< / exclusions>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-webmvc< / artifactId>
< version> $ {spring.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.springframework< / groupId>
< artifactId> spring-test< / artifactId>
< version> $ {spring.version}< / version>
< scope> test< / scope>
< / dependency>

<! - / Spring依赖关系 - >

<! - API依赖关系 - >

<依赖关系>
< groupId> org.glassfish.jersey.core< / groupId>
< artifactId> jersey-client< / artifactId>
< version> $ {jersey.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.glassfish.jersey.containers< / groupId>
< artifactId> jersey-container-servlet< / artifactId>
< version> $ {jersey.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.glassfish.jersey.media< / groupId>
< artifactId> jersey-media-json-processing< / artifactId>
< version> $ {jersey.version}< / version>
< / dependency>

<依赖关系>
< groupId> org.glassfish.jersey.test-framework.providers< / groupId>
< artifactId> jersey-test-framework-provider-grizzly2< / artifactId>
< version> 2.4< / version>
< scope> test< / scope>
< / dependency>

<依赖关系>
< groupId> org.glassfish.jersey.ext< / groupId>
< artifactId> jersey-spring3< / artifactId>
< version> $ {jersey.version}< / version>
< / dependency>

<依赖关系>
< groupId> com.google.code.gson< / groupId>
< artifactId> gson< / artifactId>
< version> $ {gson.version}< / version>
< / dependency>

<! - / API依赖关系 - >

<! - ... - >

< / dependencies>

<! - ... - >

< properties>

<! - ... - >

< spring.version> 3.0.5.RELEASE< /spring.version>

< jersey.version> 2.4.1< /jersey.version>

< gson.version> 2.2.4< /gson.version>

<! - ... - >

< / properties>

<! - ... - >

- - - - - web.xml - - - - - / p>

 < web-app> 

< context-param>
< param-name> contextConfigLocation< / param-name>
< param-value> classpath:/beans.xml< / param-value>
< / context-param>

<! - ... - >

< servlet>
< servlet-name> Jersey REST服务< / servlet-name>
< servlet-class> org.glassfish.jersey.servlet.ServletContainer< / servlet-class>
< init-param>
< param-name> javax.ws.rs.Application< / param-name>
< param-value> fubar.rest.FubarJerseyApplication< / param-value>
< / init-param>
< load-on-startup> 1< / load-on-startup>
< / servlet>

< servlet-mapping>
< servlet-name> Jersey REST服务< / servlet-name>
< url-pattern> / api / *< / url-pattern>
< / servlet-mapping>

<! - ... - >

< / web-app>

- - - - - beans.xml(上下文配置) - - - - / strong>

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation =http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\">

<! - ... - >

<! - beans-outbound-api已经为spring-jersey3配置正常工作了 - >
< import resource =beans-api.xml/>

< / beans>

- - - - - beans-api.xml - - - - -

 <?xml version =1.0encoding =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.xsd>

<! - 服务 - >

< bean id =locationServiceV1class =fubar.rest.v1.services.location.impl.LocationServiceV1/>
< bean id =locationServiceV2class =fubar.rest.v2.services.location.impl.LocationServiceV2/>

< bean id =viewServiceV1class =fubar.rest.v1.services.view.impl.ViewServiceV1/>
< bean id =viewServiceV2class =fubar.rest.v2.services.view.impl.ViewServiceV2/>

<! - 资源 - >

< bean class =fubar.rest.resources.location.impl.LocationResource>
< constructor-arg index =0ref =locationServiceV1/>
< constructor-arg index =1ref =locationServiceV2/>
< / bean>

< bean class =fubar.rest.resources.view.impl.ViewResource>
< constructor-arg index =0ref =viewServiceV1/>
< constructor-arg index =1ref =viewServiceV2/>
< / bean>

< / beans>



代码



- - - - - 资源(JAX-RS) - - - - -

  @Path(RESTLocationResourceV1.PathFields.PATH_ROOT )
@Produces({V1_JSON,APPLICATION_JSON})
public class LocationResource
扩展ResourceBase< LocationResource,ILocationServiceV1,ILocationServiceV2> {

private static final Logger logger = Logger.getLogger(LocationResource.class);

@Inject
public LocationResource(final LocationServiceV1 v1Loc,final LocationServiceV2 v2Loc){
super(v1Loc,v2Loc);
logger.info(format(Messages.INF_INSTANTIATED,LocationResource));


@GET
@Path(PathFields.SUBPATH_LIST)
public LocationListV1 listV1(@HeaderParam(HEADER_API_KEY)String apiKey)
throws ApplicationException {
//实现
}

@GET
@Path(PathFields.SUBPATH_SEARCH)
public LocationListV1 searchV1(@HeaderParam(HEADER_API_KEY)String apiKey,
@QueryParam(QueryFields.QUERY)String likeText)throws ApplicationException {
// Implementation
}
}

- - - - - 服务(Spring Bean) - - - - -

  public class LocationServiceV1扩展ServiceBaseV1< LocationBean,LocationV1,LocationListV1> 
实现
ILocationServiceV1 {

@Autowired
private LocationDao daoLoc;

public LocationServiceV1(){
super(new LocationBeanToJsonTranslatorV1());
}

@Override
public LocationListV1 listV1()throws ApplicationException {
//实现
}

@Override
public LocationListV1 searchV1(String likeText)throws ApplicationException {
//实现
}
}

(与版本2基本相同)



- - - - - 应用程序) - - - - -

  public class FubarJerseyApplication extends ResourceConfig {

private static final class Messages {
static final String INF_STARTING_APPLICATION =Starting%s!;
}

private static final Logger logger = Logger.getLogger(FubarJerseyApplication.class);

public FubarJerseyApplication(){
packages(fubar.rest);
logger.info(format(Messages.INF_STARTING_APPLICATION,this.getClass()。getName()));
}
}



调用(客户端)



  curl http:// my-ip-address / fubar / api / location / list 

(500内部服务器错误)



错误(服务器)



  org.glassfish.hk2.api.UnsatisfiedDependencyException:Injectee中没有可用于注入的对象
(requiredType = LocationServiceV1,parent =
LocationResource,qualifiers = {}),position = 0,optional = false,self = false,
unqualified = null,344016971)
在org.jvnet.hk2.internal.ThreeThirtyResolver.resolve (ThreeThirtyResolver.java:74)
在org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:208)
在org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java :225)
在org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:329)
在org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456)
在org.glassfish.jersey.process.internal.R equestScope.findOrCreate(RequestScope.java:158)
在org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2350)
在org.jvnet.hk2.internal.ServiceLocatorImpl.getService( ServiceLocatorImpl.java:612)
在org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:597)
在org.glassfish.jersey.internal.inject.Injections.getOrCreate(注入。 java:173)
在org.glassfish.jersey.server.model.MethodHandler $ ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
在org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter。应用(PushMethodHandlerRouter.java:103)
在org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:128)
在org.glassfish.jersey.server.internal。 routing.RoutingStage._apply(RoutingStage.java:131)
在org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
在org.glassfish.jersey。 server.internal.routing.RoutingStage._apply(RoutingStage。 java:131)
在org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
在org.glassfish.jersey.server.internal.routing.RoutingStage。应用(RoutingStage.java:110)
在org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:65)
在org.glassfish.jersey.process.internal。 Stages.process(Stages.java:197)
在org.glassfish.jersey.server.ServerRuntime $ 1.run(ServerRuntime.java:250)
在org.glassfish.jersey.internal.Errors $ 1。调用(Errors.java:271)
在org.glassfish.jersey.internal.Errors $ 1.call(Errors.java:267)
在org.glassfish.jersey.internal.Errors.process(错误.java:315)
在org.glassfish.jersey.internal.Errors.process(Errors.java:297)
在org.glassfish.jersey.internal.Errors.process(Errors.java:267 )
在org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
在org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
在org.glassfish.je rsey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
在org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:361)
在org.glassfish.jersey.servlet。 ServletContainer.service(ServletContainer.java:372)
在org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
在org.glassfish.jersey.servlet.ServletContainer.service( ServletContainer.java:218)
在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java: 206)
在fubar.server.springframework.SessionFilter.doFilter(SessionFilter.java:44)
在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
在fubar.server.springframework.loader.ContextLoaderHttpInterceptor $ LoaderState.filter(Co ntextLoaderHttpInterceptor.java:75)
在fubar.server.springframework.loader.ContextLoaderHttpInterceptor $ StartedState.filter(ContextLoaderHttpInterceptor.java:120)
在fubar.server.springframework.loader.ContextLoaderHttpInterceptor.doFilter(ContextLoaderHttpInterceptor。 java:62)
在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
在org.apache .catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
在org.apache.catalina.connector.CoyoteAdapter.service(Co yoteAdapter.java:293)
在org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
在org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java: 311)
在org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:776)
在org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
在org.apache.jk.common.ChannelSocket $ SocketConnection.runIt(ChannelSocket.java:898)
在org.apache.tomcat.util.threads.ThreadPool $ ControlRunnable.run(ThreadPool.java:690)
在java.lang.Thread.run(Thread.java:662)



API日志



  2013年12月10日13:36:28 INFO [main] fubar.rest.FubarJerseyApplication 
- 启动fubar。 rest.FubarJerseyApplication!
2013年12月10日13:38:06 INFO [pool-1-thread-1] resources.location.impl.LocationResource
- LocationResource已被实例化
2013年12月10日13:38 :06 INFO [pool-1-thread-1] resources.view.impl.ViewResource
- ViewResource已被实例化






更新 - 找到这个:



Catalina日志



  2013年12月10日1:36:42 PM org.glassfish.jersey.server.ApplicationHandler初始化
INFO:启动泽西申请,版本泽西:2.4。 1 2013-11-08 12:08:47 ...
2013年12月10日1:36:43 PM org.glassfish.jersey.server.spring.SpringComponentProvider初始化
SEVERE:Spring上下文查找失败跳过弹簧组件提供程序初始化。
2013年12月10日下午1:38:00 com.sun.xml.bind.v2.runtime.reflect.opt.Injector注入

...所以在 SpringComponentProvider#initialize

解决方案

我们有一个自定义异步 ContextLoader ,所以临时解决方案需要在 Jersey-Spring3 来源等待应用程序在自定义组件提供程序初始化之前初始化。



PS对于发现自己必须做这样的事情的任何可怜的灵魂,请确保META-INF /设置包含 SpringComponentProvider 配置。






(2014-04-18)阐述@Scott



请注意,这是一个可怕的黑客,我会只有在所有其他尝试都失败的时候,才试图将这样的事情当作最后的手段,就像我的情况一样。另外,我会在尝试这样的事情之前,向泽西邮政组织咨询你的问题。



这就是说,这是我为解决我的问题所做的: >


  • 将spring-jersey3的源代码复制到我的应用程序/服务器中,按照相应的标签修改每个文件的标题许可证;


  • 创建以下课程 -




===>

  / ** 
* RN-8979的黑客类。
*
* @author ryan
*
* /
public class ContextLoadWaiter {

private static final Logger logger = Logger.getLogger ContextLoadWaiter.class);

public void doWait(){

try {
while(ContextLoaderHttpInterceptor.isNotStarted()){
logger.info(Waiting to ContextLoader to开始...);
Thread.sleep(1000);
}
} catch(InterruptedException e){
logger.error(SpringComponentProvider was interrupt!);
}
}
}

请注意特定于*我们的*代码库作为 ContextLoaderHttpInterceptor 是一个http servlet,其中<​​code> isNotStarted 返回如果我们的自定义 ContextLoader (这恰恰是异步的),则还没有加载。



自定义异步 ContextLoader 由于某种原因而被某人有时被放置在允许UI在服务器上显示加载页面启动(可能不是正确的方式添加这个UI功能,但代码是在那里,UI依赖于它,所以我不得不处理它...)



由于这部​​分不会直接应用于你,关键是通过 SpringComponentProvider (从 here ) code>的ClassPathXmlApplicationContext 。如果它是 null ,就像我们这样,那么你需要弄明白为什么它是 null 并等待在您初始化此组件之前,您可以使用任何 ContextLoader 加载。




  • 放置此中的黑客行> SpringComponentProvider -



==>

  ... 

private final ContextLoadWaiter waiter = new ContextLoadWaiter();

...

@Override
public void initialize(ServiceLocator locator){

waiter.doWait(); //等待我们的异步上下文加载程序。

this.locator = locator;

if(LOGGER.isLoggable(Level.FINE)){
LOGGER.fine(Context lookup started);
}

...




  • 创建此文件: META-INF / services / org.glassfish.jersey.server.spi.ComponentProvider ,其内容是SpringComponentProvider的完全限定类路径,例如 com.company.server.nbi.rest.internal.jspring.SpringComponentProvider


  • 添加了自定义泽西-spring3包作为一个包在应用程序中进行扫描;见下文...




==>

  / ** 
*应用程序配置。
*
* @author ryan
*
* /
public class MyJerseyApplication extends ResourceConfig {

private static final class Messages {
static final String INF_STARTING_APPLICATION =Starting%s!;
}

private static final Logger logger = Logger.getLogger(MyJerseyApplication.class);

public MyJerseyApplication(){

包(
/ *内部提供者* /
com.company.server.nbi.rest.providers ,
/ *内部过滤器* /
com.company.server.nbi.rest.filters,
/ *弹簧注入支持* /
com.company.server .nbi.rest.internal.jspring,// HERE !!!
/ * Json providers * /
com.fasterxml.jackson.jaxrs.json,
/ *杰克逊异常mappers * /
com.fasterxml.jackson.jaxrs.base);

/ *资源* /
注册(ResourceA.class);
注册(ResourceB.class);
注册(ResourceC.class);

/ *其他功能* /
注册(MultiPartFeature.class);
注册(LoggingFilter.class);

logger.info(format(Messages.INF_STARTING_APPLICATION,this.getClass()。getName()));
}
}

这是it。绝对不是一个骄傲的解决方案,但是如果你像我一样在绝望的模式,可能不会伤害给它一个镜头。


I first want to point out that this is by and large the biggest problem in terms of time wasted that I have ever dealt with in my career. (Over two days straight now with essentially 0 progress.) Every single "work-around" or "solution" I have attempted hasn't worked, so I am blocked and pretty desperate for some assistance.

The problem in a nutshell is that Jersey/HK2 seems to always instantiate my Spring-managed beans AFTER they have already been instantiated by Spring, which tells me that jersey-spring3 is not doing its job, or at least not with my current setup (or any of the ~50 permutations of setups I have tried thus far.)

Note that when I use an empty constructor, those resource fields are null at run-time.

I do not understand why my current setup doesn't work as I am essentially copying this online example

Any help is more than appreciated!!

Configuration

- - - - - pom.xml - - - - -

<!-- ... -->

<dependencies>

    <!-- Spring Dependencies -->

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-instrument</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-instrument-tomcat</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-ldap</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-parent</artifactId>
        <version>${spring.version}</version>
        <classifier>tests</classifier>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${spring.version}</version>
        <classifier>tests</classifier>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-acl</artifactId>
        <version>${spring.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-support</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-dao</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>

    <!-- / Spring Dependencies -->

    <!-- API dependencies -->

    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-processing</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
        <version>2.4</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>${jersey.version}</version>
    </dependency>

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>${gson.version}</version>
    </dependency>

    <!-- / API dependencies -->

    <!-- ... -->

</dependencies>

<!-- ... -->

<properties>

    <!-- ... -->

    <spring.version>3.0.5.RELEASE</spring.version>

    <jersey.version>2.4.1</jersey.version>

    <gson.version>2.2.4</gson.version>

    <!-- ... -->

</properties>

<!-- ... -->

- - - - - web.xml - - - - -

<web-app>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/beans.xml</param-value>
    </context-param>

    <!-- ... -->

    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>fubar.rest.FubarJerseyApplication</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

    <!-- ... -->

</web-app>

- - - - - beans.xml (Context Configuration) - - - - -

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- ... -->

<!-- beans-outbound-api has configuration for spring-jersey3 to work properly -->
<import resource="beans-api.xml" />

</beans>

- - - - - beans-api.xml - - - - -

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

    <!-- Services -->

    <bean id="locationServiceV1" class="fubar.rest.v1.services.location.impl.LocationServiceV1" />
    <bean id="locationServiceV2" class="fubar.rest.v2.services.location.impl.LocationServiceV2" />

    <bean id="viewServiceV1" class="fubar.rest.v1.services.view.impl.ViewServiceV1" />
    <bean id="viewServiceV2" class="fubar.rest.v2.services.view.impl.ViewServiceV2" />

    <!-- Resources -->

    <bean class="fubar.rest.resources.location.impl.LocationResource">
        <constructor-arg index="0" ref="locationServiceV1" />
        <constructor-arg index="1" ref="locationServiceV2" />
    </bean>

    <bean class="fubar.rest.resources.view.impl.ViewResource">
        <constructor-arg index="0" ref="viewServiceV1" />
        <constructor-arg index="1" ref="viewServiceV2" />
    </bean>

</beans>

Code

- - - - - Resource (JAX-RS) - - - - -

@Path(RESTLocationResourceV1.PathFields.PATH_ROOT)
@Produces({V1_JSON, APPLICATION_JSON})
public class LocationResource
    extends ResourceBase<LocationResource, ILocationServiceV1, ILocationServiceV2> {

  private static final Logger logger = Logger.getLogger(LocationResource.class);

  @Inject
  public LocationResource(final LocationServiceV1 v1Loc, final LocationServiceV2 v2Loc) {
    super(v1Loc, v2Loc);
    logger.info(format(Messages.INF_INSTANTIATED, "LocationResource"));
  }

  @GET
  @Path(PathFields.SUBPATH_LIST)
  public LocationListV1 listV1(@HeaderParam(HEADER_API_KEY) String apiKey)
      throws ApplicationException {
    // Implementation
  }

  @GET
  @Path(PathFields.SUBPATH_SEARCH)
  public LocationListV1 searchV1(@HeaderParam(HEADER_API_KEY) String apiKey,
      @QueryParam(QueryFields.QUERY) String likeText) throws ApplicationException {
    // Implementation
  }
}

- - - - - Service (Spring Bean) - - - - -

public class LocationServiceV1 extends ServiceBaseV1<LocationBean, LocationV1, LocationListV1>
    implements
      ILocationServiceV1 {

  @Autowired
  private LocationDao daoLoc;

  public LocationServiceV1() {
    super(new LocationBeanToJsonTranslatorV1());
  }

  @Override
  public LocationListV1 listV1() throws ApplicationException {
    // Implementation
  }

  @Override
  public LocationListV1 searchV1(String likeText) throws ApplicationException {
    // Implementation
  }
}

(Essentially the same for version 2)

- - - - - Application (Jersey) - - - - -

public class FubarJerseyApplication extends ResourceConfig {

  private static final class Messages {
    static final String INF_STARTING_APPLICATION = "Starting %s!";
  }

  private static final Logger logger = Logger.getLogger(FubarJerseyApplication.class);

  public FubarJerseyApplication() {
    packages("fubar.rest");
    logger.info(format(Messages.INF_STARTING_APPLICATION, this.getClass().getName()));
  }
}

Invocation (Client)

curl http://my-ip-address/fubar/api/location/list

(500 Internal Server Error)

Error (Server)

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object
available for injection at Injectee(requiredType=LocationServiceV1,parent=
LocationResource,qualifiers={}),position=0,optional=false,self=false,
unqualified=null,344016971)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:208)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:225)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:329)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456)
at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:158)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2350)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:612)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:597)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173)
at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:103)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:128)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:131)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:110)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:65)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:250)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:361)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at fubar.server.springframework.SessionFilter.doFilter(SessionFilter.java:44)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at fubar.server.springframework.loader.ContextLoaderHttpInterceptor$LoaderState.filter(ContextLoaderHttpInterceptor.java:75)
at fubar.server.springframework.loader.ContextLoaderHttpInterceptor$StartedState.filter(ContextLoaderHttpInterceptor.java:120)
at fubar.server.springframework.loader.ContextLoaderHttpInterceptor.doFilter(ContextLoaderHttpInterceptor.java:62)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:311)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:776)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:705)
at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:898)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
at java.lang.Thread.run(Thread.java:662)

API Log

Dec 10, 2013 13:36:28 INFO  [main] fubar.rest.FubarJerseyApplication
     - Starting fubar.rest.FubarJerseyApplication!
Dec 10, 2013 13:38:06 INFO  [pool-1-thread-1] resources.location.impl.LocationResource
     - LocationResource has been instantiated
Dec 10, 2013 13:38:06 INFO  [pool-1-thread-1] resources.view.impl.ViewResource
     - ViewResource has been instantiated


Update -- found this:

Catalina Log

Dec 10, 2013 1:36:42 PM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.4.1 2013-11-08 12:08:47...
Dec 10, 2013 1:36:43 PM org.glassfish.jersey.server.spring.SpringComponentProvider initialize
SEVERE: Spring context lookup failed, skipping spring component provider initialization.
Dec 10, 2013 1:38:00 PM com.sun.xml.bind.v2.runtime.reflect.opt.Injector inject

... so the ApplicationContext isn't found in SpringComponentProvider#initialize.

解决方案

We have a custom, asynchronous ContextLoader, so the interim solution required placing a total hack in the Jersey-Spring3 source to wait for the application to initialize before the custom component provider initializes.

P.S. For any poor soul who finds themselves having to do something like this, make sure META-INF/settings contains the SpringComponentProvider configuration.


(2014-04-18) Elaborating for @Scott

Note that this is a terrible hack and I would only attempt such a thing as a last resort when all other attempts have failed, like in my case. Also I would consult the Jersey mailing group about your problem before attempting anything like this.

That said... this is what I did to solve my problem:

  • Literally copied the source code of spring-jersey3 into my application/server, modifying the header of every file with the appropriate tags as per the license;

  • Created the following class --

===>

  /**
   * Hack class for RN-8979.
   *
   * @author ryan
   *
   */
  public class ContextLoadWaiter {

    private static final Logger logger = Logger.getLogger(ContextLoadWaiter.class);

    public void doWait() {

      try {
        while (ContextLoaderHttpInterceptor.isNotStarted()) {
          logger.info("Waiting for ContextLoader to start...");
          Thread.sleep(1000);
        }
      } catch (InterruptedException e) {
        logger.error("SpringComponentProvider was interrupted!");
      }
    }
  }

Note that this is specific to *our* code-base as ContextLoaderHttpInterceptor is an http servlet where isNotStarted returns true if our custom ContextLoader (which happens to be asynchronous) is not yet loaded.

The custom asynchronous ContextLoader was put in place sometime by somebody for some reason along the lines of allowing the UI to display a "loading" page while the server boots up. (Probably not the correct way to add this UI "feature", but the code was there and the UI depended on it, so I had to deal with it...)

Since this part will not apply directly to you, the key thing is to debug through SpringComponentProvider (from here) and look at the value of the ClassPathXmlApplicationContext. If it is null, as it is in our case, then you need to figure out why it is null and wait on whatever ContextLoader you use to load before you initialize this component.

  • Placed this hacky line in SpringComponentProvider --

==>

  ...

  private final ContextLoadWaiter waiter = new ContextLoadWaiter();

  ...

  @Override
  public void initialize(ServiceLocator locator) {

    waiter.doWait(); // Wait on our asynchronous context loader.

    this.locator = locator;

    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.fine("Context lookup started");
    }

    ...

  • Created this file: META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider with the contents being the fully qualified classpath to the SpringComponentProvider, e.g. com.company.server.nbi.rest.internal.jspring.SpringComponentProvider

  • Added the custom Jersey-spring3 package as a package to scan in the application; see below...

==>

/**
 * Application configuration.
 *
 * @author ryan
 *
 */
public class MyJerseyApplication extends ResourceConfig {

  private static final class Messages {
    static final String INF_STARTING_APPLICATION = "Starting %s!";
  }

  private static final Logger logger = Logger.getLogger(MyJerseyApplication.class);

  public MyJerseyApplication() {

    packages(
    /* Internal providers */
    "com.company.server.nbi.rest.providers",
    /* Internal filters */
    "com.company.server.nbi.rest.filters",
    /* Spring injection support */
    "com.company.server.nbi.rest.internal.jspring", // HERE!!!
    /* Json providers */
    "com.fasterxml.jackson.jaxrs.json",
    /* Jackson exception mappers */
    "com.fasterxml.jackson.jaxrs.base");

    /* Resources */
    register(ResourceA.class);
    register(ResourceB.class);
    register(ResourceC.class);

    /* Miscellaneous features */
    register(MultiPartFeature.class);
    register(LoggingFilter.class);

    logger.info(format(Messages.INF_STARTING_APPLICATION, this.getClass().getName()));
  }
}

That's "it". Definitely not a solution to be proud of, but if you are in desperation mode like I was, it probably doesn't hurt to give it a shot.

这篇关于jersey-spring3实例化Spring管理的bean(null!)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆