2013-05-28 3 views
4

Я пытаюсь интегрировать Spring DI в существующий проект jaxws. У меня это работает локально на tomcat, но когда я развертываю его в удаленном контейнере, он, похоже, не выполняет сканирование классов. Я вижу в журналах, что на tomcat он регистрирует мои @Components как бобы, но на удаленном сервере они вообще не упоминаются.Весной компонент-сканирование сломанной в контейнере osgi

То, что я вижу, представляет собой стек. Похоже, что это до причудливого веб-контейнера, который я должен использовать. Это «интегрированный сервер приложений для IBM i». http://www-03.ibm.com/systems/i/software/ias/ Я считаю, что это построено на архитектуре затмения, и когда вы устанавливаете военный файл, он конвертирует каждое приложение в пакет. Это здорово, но это разрушает сканирование классов. ? :(

Кто-нибудь есть решение для этого Благодаря

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) 

Глядя на код, который выбрасывает исключение, это проверка, если протокол файла:. //

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 может видеть, что приложение было взорвано в файловой системе. Интересно, есть ли способ переопределить этот загрузчик весной, чтобы не заботиться о протоколе и, очевидно, все еще работал? Мне не нужны функции osgi в контейнере. просто хочу, чтобы мое приложение развернулось.

Отказ, похоже, отбрасывает сканирование классов в зависимости от определения bean-компонентов в xml, но это d-реальный шаг назад imo. :(

+0

Вы можете зарегистрировать свои компоненты в качестве osgi-сервисов на основе каждого пакета. При инъекции зависимостей вам необходимо учитывать зарегистрированные службы osgi. – SpaceTrucker

+0

Вы также должны прочитать [Почему сканирование в стиле классов плохо для вас] (http://lemnik.wordpress.com/2007/09/14/why-classpath-scanning-is-bad-for-you/) – SpaceTrucker

+0

Справедливая точка зрения сканирование классов, но как еще я могу аккуратно подключить мои компоненты? Как мне регистрировать компоненты как службы osgi? Это становится беспорядочным, поскольку я не использую контейнер osgi для локального тестирования.Мне даже не важно, что удаленный сервер osgi, я просто хочу, чтобы иметь возможность развернуть мое приложение. –

ответ

6

Ненавижу идею ответа на свой вопрос, но это лучший способ сообщить, что я сделал. Я до сих пор поддерживал ответы, потому что они помогли мне принять решение.

Прочитав ответы, я немного узнал о том, почему сканирование в стиле классов плохое. Тем не менее, это довольно распространенная часть весеннего каркаса в эти дни. Мое решение состояло в том, чтобы перейти в «старое skool» и вручную определить мои бобы.

Не может это сделать:

<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 /> 

Аннотация конфигурация означает весна будет еще провод ваши бобы вместе, это всего лишь процесс обнаружения боб, выполняемого вручную. Это компромисс.

В идеале я бы предпочел использовать средство для развертывания проекта с помощью сканирования компонентов, но из того, что я могу собрать, требуется изменить способ создания проекта специально для контейнера osgi. Мой ответ означает, что он будет работать как в osgi, так и в обычном контейнере, поэтому он менее специализирован.

Если кто-то найдет способ развернуть военный файл с сканированием весеннего компонента, я с радостью передумаю принятый ответ.

Благодаря

+0

Спасибо за обмен, это позволило мне, наконец, заставить его работать! Кажется, через три года это * все еще * является проблемой. –

+0

Как ни странно, мы только что обновили вчера от IAS 8.1 до 8.5. Старая версия была основана на «ускорителе лотоса», и я никогда не был впечатлен этим, и это было одним из нескольких обходных решений, которые я использовал 8.5, похоже, основывается на WAS и бесконечно лучше. Гораздо быстрее начать/остановить, вы можете легко установить параметры JVM, вы можете выбрать JRE, чтобы больше не фиксироваться на 6, и я уверен, что он будет теперь поддерживаем сканирование классов. Мне нужно протестировать его, но если это b uilt на WAS, тогда он должен это сделать. Если вы находитесь в IBM i, то обязательно изучите обновление. –

1

Classpath сканирование ужасная идея, и она сломается во многих средах выполнения, а не только в OSGi. Реестр OSGi службы является гораздо более эффективным подходом к проблеме развязки.

Вы можете использовать OSGi Service Реестр за пределами самого OSGi, посмотрите на PojoSR.

что касается как зарегистрироваться и потреблять OSGi услуги ... так как вы используете Spring, было бы лучше использовать Blueprint, что эволюция старше проект под названием Весенние динамические модули.

+0

Так что мне все время говорят. Однако это довольно неотъемлемая часть весеннего каркаса. Наверняка есть ли способ запустить эти приложения, не переписывая их в стиле osgi? –

+0

Я не могу ответить на ваш вопрос, потому что давно не использовал Spring; но я был бы очень удивлен, если бы сканирование классов было единственным способом, потому что архитекторы Spring должны были знать лучше. Я думаю, что если вы углубитесь в документацию, вы сможете найти механизм API или расширения, который позволит вам контролировать процесс обнаружения аннотированных компонентов. Удачи ... если вы найдете ответ, обязательно напишите здесь здесь. –

2

Для вашего веб-приложения для запуска с весной вам нужно яровой дм, и поэтому вам нужно иметь что-то вроде следующего:

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

Или для полной выборки взглянуть на весеннюю-OSGi образца в pax- web: Sample web.xml

+0

Это больше похоже на то, что я хотел. Я собираюсь поиграть с этим и посмотреть, смогу ли я заставить его работать. К сожалению, у меня мало времени, поэтому надеюсь, что это не слишком сложно. Приветствия. –

+0

Немедленно сталкиваются с проблемами. Попробовал добавить spring-osgi-web как зависимость от maven, но теперь сборка нарушена, потому что она не может разрешить servlet-api.osgi. Страница maven для этого возвращает 404. :(http://mvnrepository.com/artifact/org.springframework.osgi/servlet-api.osgi –

+0

Я не уверен, что вы пытаетесь сделать, но образец является образцом wab, и если вы хотите протестировать его, вам нужен веб-контейнер с поддержкой osgi, например, Pax-Web. Это не то, что нужно добавить в ваше приложение. –

0

Я сделал этот небольшой скрипт для Linux, так что я распаковать TrackServer.jar и выполнить основной класс, не теряя простоты с весны (Newb до весны здесь, так что не так приятно маневрировать и добавить дополнительный код там)

# 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

Это ответ на другой вопрос? –

+0

Да, я не хотел выполнять ручной поиск, это случилось со мной с контроллерами, но ошибка была такой же, поэтому вместо этого переместил биткод в файловую систему, позже я переместил его в/run/shm/tracker вместо/var /www/.../tracker. Если вы удаляете комментарии, у вас есть всего несколько строк, ах и этот проект запускает собственный комок. Размещено здесь, так как ошибка была одинаковой на низком уровне, и это был ответ, который дал мне Google при поиске ошибки. –

+0

Возможно, у вас была аналогичная ошибка, но я не думаю, что это та же проблема. Моя проблема заключалась в том, чтобы ускорить сканирование весеннего класса, чтобы работать с контейнером OSGi. Мы используем tomcat на наших локальных машинах, и сканирование классов не вызывает проблем. –

1

Я пробовал комментировать начальную запись, однако я не могу этого сделать из-за моего рейтинга в stackoverflow, к сожалению. Не поймите меня неправильно, я не говорю, что у меня есть решение здесь, но я хотел бы поделиться своим обходным решением в новой версии Spring Framework здесь.

Во-первых, у меня большой класс конфигурации, который является сервером как запись в этом заявлении 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"); 
    } 

} 

В принципе, как и @ComponentScan не работает с OSGI плагин (как уже упоминалось в вас ответить на пост, это в основном из-за того, что Spring Framework пытаются сканировать классы, предполагающие артефакты находятся в файловой системе, однако в этом случае OSGI (например, Apache Felix) превратил FILE: // префикс url в свой внутренний пакет: // префикс. 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/*** Тем не менее @Autowired все еще работает. Я показал пример ниже, где DummySpringBean2 имеет зависимость от DummySpringBean1 и @Autowired аннотируется.

//@Component 
class DummySpringBean1 { 

    private final String dummyMessage; 

    DummySpringBean1(String dummyMessage) { 
    this.dummyMessage = dummyMessage; 
    } 
} 

Для DummySpringBean2 он зависит от DummySpringBean1.

//@Component 
class DummySpringBean2 { 

    private final String dummyMessage; 

    @Autowired 
    private DummySpringBean1 bean1; 

    DummySpringBean(String dummyMessage) { 
    this.dummyMessage = dummyMessage; 
    } 
} 

Таким образом, я переместил все объявления bean-компонентов в центральный класс конфигурации выше.

+0

Просто, чтобы вы знали мое мнение об этом: если это обходной путь, это своего рода решение. Кроме того, я не знаю, как бы вы поместили это в комментарий. С другой стороны, мои знания о Весне низки, я не могу много говорить об обходном пути. Могу ли я рекомендовать вам продолжать участвовать в этом сайте. Приветствия. – lrnzcig

+0

@Irnzcig, Спасибо за поддержку. Я сделаю все возможное для этого сайта, и я чувствую необходимость делиться опытом с разработчиками с другими разработчиками, особенно с молодыми разработчиками. – imarchuang

+0

Это по существу то же самое, что и мое решение, за исключением того, что вы используете java @Configuration вместо xml config для регистрации bean-компонентов. Это хорошее предложение. –

Смежные вопросы