在 Eclipse Virgo 中使用 restlet

Use restlet with Eclipse Virgo

我正在尝试将 restlet 集成到使用 Eclipse Virgo 作为应用程序服务器的应用程序中。由于 Virgo 基于 OSGi,我不得不使用 org.restlet.osgi 库和不依赖于 Java 1.7 的最新版本(restlet 2.2.3),因为最新的 Virgo 版本抱怨捆绑依赖于Java1.7.

我尝试让 restlet 使用 Eclipse Virgo Web 服务器来交付 REST API,但似乎我尝试的任何方法都不起作用。当然,我可以在与 Eclipse Virgo 不同的端口上启动 restlet 自己的 Web 服务器,但我没有成功使用它的 Web 服务器。有可能吗?

更新

还有Spring参与到故事中,所以我想这会让事情变得更加有趣。 Spring相关配置如下:

<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/*.xml</param-value>
</context-param>

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

<servlet>
    <servlet-name>springdispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/*.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>springdispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

我现在遇到这个异常:

[2015-03-10 18:35:55.783] ERROR start-signalling-1           org.springframework.web.context.ContextLoader                     Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restletComponent' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Cannot resolve reference to bean 'router' while setting bean property 'defaultTarget'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'router' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Cannot create inner bean 'org.restlet.ext.spring.SpringFinder#5700078' of type [org.restlet.ext.spring.SpringFinder] while setting bean property 'attachments' with key [TypedStringValue: value [/data/dashboard/geppettoprojects], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.restlet.ext.spring.SpringFinder#5700078' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Instantiation of bean failed; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access1(AbstractDelegatedExecutionApplicationContext.java:60)
    at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.run(AbstractDelegatedExecutionApplicationContext.java:168)
    at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
    at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.normalRefresh(AbstractDelegatedExecutionApplicationContext.java:164)
    at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$NoDependenciesWaitRefreshExecutor.refresh(AbstractDelegatedExecutionApplicationContext.java:78)
    at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:157)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
    at org.eclipse.gemini.web.tomcat.internal.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:125)
    at org.eclipse.gemini.web.internal.StandardWebApplication.start(StandardWebApplication.java:109)
    at org.eclipse.virgo.web.core.internal.WebBundleLifecycleListener.onStarted(WebBundleLifecycleListener.java:122)
    at org.eclipse.virgo.kernel.install.artifact.internal.StandardArtifactStateMonitor.onStarted(StandardArtifactStateMonitor.java:271)
    at org.eclipse.virgo.kernel.install.artifact.internal.AbstractInstallArtifact.asyncStartSucceeded(AbstractInstallArtifact.java:319)
    at org.eclipse.virgo.kernel.install.artifact.internal.AbstractInstallArtifact.access[=11=](AbstractInstallArtifact.java:316)
    at org.eclipse.virgo.kernel.install.artifact.internal.AbstractInstallArtifact$StateMonitorSignal.signalSuccessfulCompletion(AbstractInstallArtifact.java:252)
    at org.eclipse.virgo.nano.core.internal.BundleStartTracker.run(BundleStartTracker.java:140)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'router' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Cannot create inner bean 'org.restlet.ext.spring.SpringFinder#5700078' of type [org.restlet.ext.spring.SpringFinder] while setting bean property 'attachments' with key [TypedStringValue: value [/data/dashboard/geppettoprojects], target type [null]]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.restlet.ext.spring.SpringFinder#5700078' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Instantiation of bean failed; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:281)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:120)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:378)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:161)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
    ... 38 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.restlet.ext.spring.SpringFinder#5700078' defined in ServletContext resource [/WEB-INF/spring/app-config.xml]: Instantiation of bean failed; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:997)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:270)
    ... 50 common frames omitted
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy$CglibSubclassCreator.instantiate(CglibSubclassingInstantiationStrategy.java:119)
    at org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy.instantiateWithMethodInjection(CglibSubclassingInstantiationStrategy.java:71)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990)
    ... 54 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
    ... 60 common frames omitted
Caused by: java.lang.NoClassDefFoundError: net/sf/cglib/proxy/Factory
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    ... 66 common frames omitted
Caused by: org.eclipse.virgo.kernel.osgi.framework.ExtendedClassNotFoundException: net.sf.cglib.proxy.Factory in KernelBundleClassLoader: [bundle=org.restlet.ext.spring_2.2.3.v20141127-1706]
    at org.eclipse.virgo.kernel.userregion.internal.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:150)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 68 common frames omitted
Caused by: java.lang.ClassNotFoundException: net.sf.cglib.proxy.Factory
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
    at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
    at org.eclipse.virgo.kernel.userregion.internal.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:146)
    ... 69 common frames omitted

事实上,您不需要扩展 org.restlet.ext.osgi 就可以在 OSGi 容器中运行 Restlet。事实上,对于 OSGi 版本,所有 Restlet jar 都包含有效的 MANIFEST 文件(甚至在版本 2.2 之前)。

Virgo 支持 Web 包,因此您可以利用扩展 org.restlet.ext.servlet 在其中嵌入 Restlet 应用程序。您可以查看以下link了解更多详情:https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.markdown/02_Server_Side/04_Server_Deployment/02_Servlet_Deployment.md.

否则,我有兴趣了解有关您在这种情况下尝试使用 Restlet 时遇到的错误的更多详细信息。

已编辑(按照问题中添加的新元素)

您应该为 Spring 配置 Restlet servlet。此 servlet 将替换 Spring 本身 (DispatcherServlet) 中的那个。侦听器 ContextLoaderListener 必须保留,因为它用于管理 Web 包中的 Spring 应用程序上下文。

这是此 servlet 的配置示例:

<servlet>
    <servlet-name>SpringRestletServlet</servlet-name>
    <servlet-class>org.restlet.ext.spring.SpringServerServlet</servlet-class>
    <init-param>
        <param-name>org.restlet.component</param-name>
        <param-value>myComponent</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>tracker</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

servlet 将在您的 Spring 应用程序上下文中查找名为 myComponent 的 bean。

这是此应用程序上下文中的 Restlet 配置示例:

<bean id="myComponent" class="org.restlet.ext.spring.SpringComponent">
    <property name="defaultTarget" ref="router" />
</bean>

<bean name="router" class="org.restlet.ext.spring.SpringRouter">
    <property name="attachments">
        <map>
            <entry key="/ping">
                <bean class="org.restlet.ext.spring.SpringFinder">
                    <lookup-method name="create" bean="pingServerResource" />
                </bean>
            </entry>
            <entry key="/dir" value-ref="staticsDirectory" />
        </map>
    </property>
</bean>

<bean id="pingServerResource" class="test.TestServerResource"></bean>