Spring component scan damaged in osgi container

I am trying to integrate spring DI into an existing jaxws project. It works for me locally on tomcat, but when I deploy it in a remote container, it does not seem to do a class scan. I see in the logs that on tomcat it registers my @Components as beans, but they are not mentioned at all on the remote server.

What I see is stacktrace below. It looks like it's up to the sophisticated web container I have to use. It is an "integrated application server for IBM i." http://www-03.ibm.com/systems/i/software/ias/ I believe this is based on the eclipse architecture, and when you install the war file, it converts each application into a package. This is great, but it destroys class scans. :(

Does anyone have a solution for this? Thanks

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) 

Looking at the code that throws the exception, it checks to see if the protocol is a 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); 

I see that the application was exploded in the file system. I wonder if there is a way to override this bootloader in spring so as not to care about the protocol and obviously still work? I do not need the osgi functions of the container. I just want my application to be deployed.

The failure, apparently, is the refusal to scan the class in favor of defining beans in xml, but this; d is a real step back imo .: (

+4
source share
5 answers

I hate the idea of ​​answering my question, but this is the best way to communicate what I did. I still supported the answers because they helped me make a decision.

After reading the answers, I learned a little about why scanning in classes is bad. However, this is a fairly common part of the spring structure these days. My solution was to switch to the "old skool" and manually define my beans.

Unable to do this:

 <context:component-scan base-package="com.company.application.services" /> 

Do this instead:

 <bean id="service1" class="com.company.application.services.impl.Service1" /> <bean id="service2" class="com.company.application.services.impl.Service2" /> 

You can at least do this:

 <context:annotation-config /> 

An annotation value means spring will still bind your beans anyway, it's just a beans discovery process that is done manually. This is a compromise.

Ideally, I would prefer a project deployment tool by scanning components, but from what I can build, I need to change the way I create the project specifically for the osgi container. My answer means that it will work both in osgi and in a regular container, so it is less specialized.

If someone finds a way to deploy a war file by scanning for spring components, I will gladly change my mind about the accepted answer.

thanks

+6
source

For your spring web application, you need spring dm, and so you need to have something like the following:

  <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value> </context-param> 

Or for a complete sample, take a look at the spring -osgi sample in pax-web: web.xml example

+2
source

Scanning by class is a terrible idea, and it will break down in many modes of operation, and not just in OSGi. The OSGi service registry is a much more efficient approach to decoupling.

You can use the OSGi Service registry outside OSGi, see PojoSR .

Regarding registering and using OSGi services ... since you are using Spring, it is better to use Blueprint , which is an evolution of an older project called Spring Dynamic Modules.

+1
source

I tried to comment on your initial post, but I cannot do this because of my rating on stackoverflow, unfortunately. Don't get me wrong, I'm not saying that I have a solution here, but I would like to share my workaround in the new Spring framework here.

Firstly, I have a large configuration class that is the server as an entry in this AnnotationConfigApplicationContext(PseudoSpringBootApplication.class) expression AnnotationConfigApplicationContext(PseudoSpringBootApplication.class) .

 /** * 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"); } } 

Basically, since @ComponentScan does not work with the OSGI plugin (as mentioned in your answer to the post, this is mainly due to the fact that the Spring infrastructure is trying to scan classes, assuming that the artifacts are on the file system, in this case OSGI (for example, Apache Felix) turned FILE: // url prefix into its internal package: // prefix. 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/*** bundle: //21.0: 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/*** However, @Autowired still works I showed the sample code below, which has a dependency DummySpringBean2 DummySpringBean1 @Autowired and annotation. Rowan.

 //@Component class DummySpringBean1 { private final String dummyMessage; DummySpringBean1(String dummyMessage) { this.dummyMessage = dummyMessage; } } 

For DummySpringBean2, it has a dependency on DummySpringBean1.

 //@Component class DummySpringBean2 { private final String dummyMessage; @Autowired private DummySpringBean1 bean1; DummySpringBean(String dummyMessage) { this.dummyMessage = dummyMessage; } } 

So, I moved the bean declaration to the main configuration class above.

+1
source

I made this little script for linux, so I unpack TrackServer.jar and execute the main class without losing simplicity from Spring (newb to Spring is here, so it's not very nice to maneuver and add extra code there)

 # 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 
0
source

Source: https://habr.com/ru/post/1483179/


All Articles