我正在尝试将spring DI集成到现有的jaxws项目中。我已经在tomcat本地工作但是当我部署到远程容器时,它似乎没有进行类路径扫描。我可以在日志中看到,在tomcat上它将我的@Components注册为bean,但是在远程服务器上它们根本就没有被提及。
我看到的是下面的堆栈跟踪。它看起来像是我必须使用的古怪的Web容器。它是“IBM i的集成应用程序服务器”。 http://www-03.ibm.com/systems/i/software/ias/我相信这是建立在eclipse架构上的,当你安装war文件时,它会将每个应用程序转换为一个包。这很棒,但它打破了我的类路径扫描。 :(
有人有解决方案吗?感谢
673 [Thread-6] WARN org.springframework.core.io.support.PathMatchingResourcePatternResolver - Cannot search for matching files underneath URL [bundleresource://32/com/company/application/] because it does not correspond to a directory in the file system
java.io.FileNotFoundException: URL [bundleresource://32/com/company/application/] cannot be resolved to absolute file path because it does not reside in the file system: bundleresource://32/com/company/application/
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:205)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
at org.springframework.core.io.UrlResource.getFile(UrlResource.java:169)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.doFindPathMatchingFileResources(PathMatchingResourcePatternResolver.java:526)
at org.springframework.web.context.support.ServletContextResourcePatternResolver.doFindPathMatchingFileResources(ServletContextResourcePatternResolver.java:92)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:347)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:266)
at org.springframework.context.support.AbstractApplicationContext.getResources(AbstractApplicationContext.java:1269)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:248)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:242)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1438)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1428)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:185)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:139)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:108)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1678)
at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinish(WebApp.java:371)
at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:347)
at com.ibm.ws.webcontainer.webapp.WebGroup.addWebApplication(WebGroup.java:134)
at com.ibm.ws.webcontainer.VirtualHost.addWebApplication(VirtualHost.java:145)
at com.ibm.ws.webcontainer.WebContainer.addWebApp(WebContainer.java:542)
at com.ibm.ws.webcontainer.WebContainer.addWebApplication(WebContainer.java:513)
at com.ibm.pvc.internal.webcontainer.trackers.WebApplicationServiceTracker.addingService(WebApplicationServiceTracker.java:94)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackAdding(ServiceTracker.java:1064)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackInitialServices(ServiceTracker.java:926)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:330)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:274)
at com.ibm.pvc.internal.webcontainer.trackers.XMLParserServiceTracker.initializeTrackers(XMLParserServiceTracker.java:520)
at com.ibm.pvc.internal.webcontainer.trackers.XMLParserServiceTracker.startWebcontainer(XMLParserServiceTracker.java:235)
at com.ibm.pvc.internal.webcontainer.trackers.XMLParserServiceTracker.addingService(XMLParserServiceTracker.java:140)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackAdding(ServiceTracker.java:1064)
at org.osgi.util.tracker.ServiceTracker$Tracked.trackInitialServices(ServiceTracker.java:926)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:330)
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:274)
at com.ibm.pvc.internal.webcontainer.WebContainerActivator.start(WebContainerActivator.java:45)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$2.run(BundleContextImpl.java:1009)
at java.security.AccessController.doPrivileged(AccessController.java:251)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:1003)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:984)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:350)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:279)
at com.ibm.rcp.internal.util.BundleManager.start(BundleManager.java:74)
at com.ibm.rcp.internal.util.BundleManager.start(BundleManager.java:179)
at com.ibm.rcp.lifecycle.internal.application.BundleControlImpl.start(BundleControlImpl.java:125)
at com.ibm.rcp.lifecycle.internal.application.BundleControlImpl.start(BundleControlImpl.java:106)
at com.ibm.rcp.lifecycle.application.BundleControl.start(BundleControl.java:89)
at com.ibm.lwi.application.LWIApplication.run(LWIApplication.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethodWithException(EclipseAppContainer.java:574)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:195)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:561)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:501)
at org.eclipse.equinox.launcher.Main.run(Main.java:1239)
at org.eclipse.equinox.launcher.Main.main(Main.java:1215)
at org.eclipse.core.launcher.Main.main(Main.java:30)
at com.ibm.lwi.LaunchLWI$1.run(LaunchLWI.java:731)
查看抛出异常的代码,检查协议是否为file://。
if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
throw new FileNotFoundException(
description + " cannot be resolved to absolute file path " +
"because it does not reside in the file system: " + resourceUrl);
我可以看到应用程序已经爆炸到文件系统上。我想知道是否有办法在春天覆盖这个加载器而不关心协议,显然仍然有效?我不关心容器的osgi功能。我只想要部署我的应用程序。
后备似乎放弃了类路径扫描,转而支持在xml中定义bean,但这是一个真正的退步imo。 :(
答案 0 :(得分:8)
我讨厌回答我自己的问题,但这似乎是回报我所做的最好的方式。到目前为止,我已经提出了答案,因为它们对我做出决定很有帮助。
通过阅读答案,我已经了解了为什么类路径扫描很糟糕。尽管如此,如今这是弹簧框架的一个非常常见的部分。我的解决方案是去“旧skool”并手动定义我的bean。
不能这样做:
<context:component-scan base-package="com.company.application.services" />
请改为:
<bean id="service1" class="com.company.application.services.impl.Service1" />
<bean id="service2" class="com.company.application.services.impl.Service2" />
你至少可以这样做:
<context:annotation-config />
注释配置意味着spring仍会将您的bean连接在一起,这只是发现手动完成的bean的过程。这是妥协。
理想情况下,我更倾向于使用组件扫描来部署项目,但从我可以收集的内容来看,这需要更改专门为osgi容器构建项目的方式。我的回答意味着它在osgi和普通容器中都可以工作,所以它不太专业。
如果有人找到了使用弹簧组件扫描部署war文件的方法,那么我很乐意重新考虑接受的答案。
由于
答案 1 :(得分:2)
对于使用spring运行的Web应用程序,您需要spring dm,因此您需要具有以下内容:
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
</context-param>
或者对于完整的样本,请查看pax-web上的spring-osgi样本: Sample web.xml
答案 2 :(得分:2)
我尝试评论您的初始帖子,但由于我在stackoverflow中的排名不幸,我无法做到这一点。不要误解我的意思,我不是说我在这里有解决方案,但我想在这里分享我在更新版本的Spring框架中的解决方法。
首先,我有一个很大的配置类,它作为此/**
* This class serves as the entry point from OSGI framework to Spring framework
*
*/
@Configuration
//@ComponentScan
//@SpringBootApplication
public class PseudoSpringBootApplication {
@Autowired
ApplicationContext context;
@Bean
DummySpringBean1 dummySpringBean1() {
return new DummySpringBean("This is a dummy message");
}
@Bean
DummySpringBean2 dummySpringBean2() {
return new DummySpringBean("This is a dummy message");
}
}
语句中的条目服务。
java.io.FileNotFoundException: URL [bundle://21.0:1/com/***] cannot be resolved to absolute file path because it does not reside in the file system: bundle://21.0:1/com/***
基本上,由于@ComponentScan不能与OSGI插件一起使用,(正如你在回答帖子中所提到的,这主要是因为Spring框架尝试扫描类,假设工件在文件系统中,但是,在这种情况下,OSGI(例如,Apache Felix)已将FILE://前缀url转换为其内部bundle:// prefixed。
//@Component
class DummySpringBean1 {
private final String dummyMessage;
DummySpringBean1(String dummyMessage) {
this.dummyMessage = dummyMessage;
}
}
尽管如此,@ Autowired仍在使用。我已经展示了下面的示例代码,其中DummySpringBean2具有DummySpringBean1的依赖关系,并且@Autowired已注释。
//@Component
class DummySpringBean2 {
private final String dummyMessage;
@Autowired
private DummySpringBean1 bean1;
DummySpringBean(String dummyMessage) {
this.dummyMessage = dummyMessage;
}
}
对于DummySpringBean2,它依赖于DummySpringBean1。
ID Var
01 Value1
01 Value2
01 Value3
02 Value4
02 Value2
02 Value3
03 Value1
03 Value2
所以我将所有bean声明移到了上面的中央配置类。
答案 3 :(得分:1)
类路径扫描是一个糟糕的想法,它会在许多运行时中断,而不仅仅是在OSGi中。 OSGi服务注册表是解决问题的一种更有效的方法。
您可以在OSGi本身之外使用OSGi Service Registry,查看PojoSR。
至于如何注册和使用OSGi服务......因为你使用的是Spring,所以最好使用Blueprint,这是一个名为Spring Dynamic的旧项目的演变模块。
答案 4 :(得分:0)
我为linux编写了这个小脚本,所以我解压缩TrackServer.jar并执行主类而不会失去Spring的简单性(newb to spring here,所以不太乐意操作并在那里添加额外的代码)
# Remove any old file before new version
rm -rf tracker;
# Recreate executable folder
mkdir tracker;
# copy main jar to executable folder
cp TrackServer.jar tracker;
# move to executable folder
cd tracker;
# Extract jar on executable folder
jar xf TrackServer.jar;
# Execute main class (at the end of the line)
# with all the jar dependencies that came
# in original TrackerServer.jar
java -cp '.;'`ls -dm *.jar | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' | sed -e 's/,[ \n\r\t]/:/g'` incodemode.mainApp.Main;
# sed bits are for getting .:dependency1.jar:dependency2.jar etc...
# incodemode.mainApp.Main is the full class path of the Main class