1

古き良き戦争プロジェクトでは、 を追加するだけで、ほとんど機能ContextLoaderListenerしますweb.xml-使用できます

WebApplicationContextUtils.getWebApplicationContext(getServlet().getServletContext())

Actionたとえば、Struts 1 クラスからアプリケーション コンテキストにアクセスするには、構成プロセス全体が十分に文書化されています。Bean が他のアプリケーションによって作成されている場合は、JNDI から Bean を検索できます。

しかし、この古き良き Web アプリケーションのアーカイブを Web アプリケーション バンドルに移植し、JNDI の代わりに OSGi サービス参照を使用したい場合はどうすればよいでしょうか。上記の方法は、Web アプリケーション内で Bean を管理することだけを Spring に実行させたい場合でも機能します。上記のユーティリティ メソッドを使用して Bean をインスタンス化し、それらを取得できます。また、OSGi サービス参照を解決するために Gemini Blueprint (以前の Spring DM) を正常にセットアップしました。

問題は、Gemini ブループリントと Spring Struts が並行して実行され、お互いを認識していないように見えることです。上記のユーティリティ メソッドによって返されたコンテキストには、OSGi サービスからインポートされたものなど、Gemini ブループリントによって作成された Bean が含まれておらず、Spring Struts によって解析された XML 構成にブループリント スタイルの OSGi サービス参照を追加すると、ひどく死んでしまいます。

Struts 1 内から Gemini Blueprint アプリケーション コンテキストにアクセスするには、何をする必要がありますActionか?

ログ

ログから厳選された行:

17:12:32,206 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-1) JBAS015876: Starting deployment of "wfadmin-1.0-SNAPSHOT-82a5028.war" (runtime-name: "wfadmin-1.0-SNAPSHOT-82a5028.war")

17:12:36,744 INFO  [io.undertow.servlet] (MSC service thread 1-7) Initializing Spring root WebApplicationContext
17:12:36,745 INFO  [org.springframework.web.context.ContextLoader] (MSC service thread 1-7) Root WebApplicationContext: initialization started
17:12:36,751 INFO  [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC service thread 1-7) Loading XML bean definitions from ServletContext resource [/META-INF/spring/wfadmin-context.xml]
17:12:38,026 FINE  [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC service thread 1-7) Loaded 1 bean definitions from location pattern [/META-INF/spring/wfadmin-context.xml]
17:12:38,026 FINE  [org.springframework.web.context.support.XmlWebApplicationContext] (MSC service thread 1-7) Bean factory for Root WebApplicationContext: org.springframework.beans.factory.support.DefaultListableBeanFactory@440f89d6: defining beans [testBeanInMetaInfSpringWfadmiContextXml]; root of factory hierarchy
17:12:38,027 INFO  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (MSC service thread 1-7) Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@440f89d6: defining beans [testBeanInMetaInfSpringWfadmiContextXml]; root of factory hierarchy
17:12:38,030 FINE  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (MSC service thread 1-7) Finished creating instance of bean 'testBeanInMetaInfSpringWfadmiContextXml'
17:12:38,034 INFO  [org.springframework.web.context.ContextLoader] (MSC service thread 1-7) Root WebApplicationContext: initialization completed in 1289 ms

17:12:38,140 INFO  [org.eclipse.gemini.blueprint.extender.support.DefaultOsgiApplicationContextCreator] (MSC service thread 1-7) Discovered configurations {osgibundle:/META-INF/spring/*.xml} in bundle [Sunstone Workflow Admin (se.sunstone.workflow.web)]
17:12:38,208 FINEST [org.eclipse.gemini.blueprint.io.OsgiBundleResourcePatternResolver] (EclipseGeminiBlueprintExtenderThread-15) Resolved location pattern [osgibundle:/META-INF/spring/*.xml] to resources [URL [bundle://se.sunstone.workflow.web-87-1-0/META-INF/spring/wfadmin-context.xml], URL [bundle://se.sunstone.workflow.web-87-1-0/META-INF/spring/wfadmin-osgi-context.xml]]
17:12:38,258 FINE  [org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext] (EclipseGeminiBlueprintExtenderThread-15) Bean factory for OsgiBundleXmlApplicationContext(bundle=se.sunstone.workflow.web, config=osgibundle:/META-INF/spring/*.xml): org.springframework.beans.factory.support.DefaultListableBeanFactory@22eccb06: defining beans [testBeanInMetaInfSpringWfadmiContextXml,testBeanInMetaInfSpringWfadminOsgiContextXml,wfEngine]; root of factory hierarchy
17:12:38,260 FINEST [org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory] (EclipseGeminiBlueprintExtenderThread-15) Discovered single proxy importers [&wfEngine]
17:12:38,266 FINE  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (EclipseGeminiBlueprintExtenderThread-15) Finished creating instance of bean 'wfEngine'
17:12:38,266 FINEST [org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.MandatoryImporterDependencyFactory] (EclipseGeminiBlueprintExtenderThread-15) Eager importer &wfEngine implies dependecy DependencyService[Name=&wfEngine][Filter=(objectClass=se.sunstone.workflow.WorkflowEngine)][Mandatory=true]
17:12:38,266 FINE  [org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyServiceManager] (EclipseGeminiBlueprintExtenderThread-15) OSGi service dependency for importer [&wfEngine] is already satisfied
17:12:38,266 FINEST [org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyServiceManager] (EclipseGeminiBlueprintExtenderThread-15) Total OSGi service dependencies beans [&wfEngine]
17:12:38,292 FINE  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (EclipseGeminiBlueprintExtenderThread-16) Finished creating instance of bean 'testBeanInMetaInfSpringWfadmiContextXml'
17:12:38,293 FINE  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (EclipseGeminiBlueprintExtenderThread-16) Finished creating instance of bean 'testBeanInMetaInfSpringWfadminOsgiContextXml'

17:12:46,978 FINEST [se.sunstone.util.web.AbstractAction] (default task-1) Beans defined in application context Root WebApplicationContext : 
17:12:46,978 FINEST [se.sunstone.util.web.AbstractAction] (default task-1) testBeanInMetaInfSpringWfadmiContextXml
17:12:46,978 FINEST [se.sunstone.util.web.AbstractAction] (default task-1) End of beans defined in application context Root WebApplicationContext
17:12:46,979 FINEST [org.springframework.beans.factory.support.DefaultListableBeanFactory] (default task-1) No bean named 'wfEngine' found in org.springframework.beans.factory.support.DefaultListableBeanFactory@440f89d6: defining beans [testBeanInMetaInfSpringWfadmiContextXml]; root of factory hierarchy
17:12:46,979 SEVERE [se.sunstone.util.web.AbstractAction] (default task-1) A requested bean does not exist.: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wfEngine' is defined
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:568)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1108)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1117)
    at se.sunstone.util.web.AbstractAction.getService(AbstractAction.java:53) [AbstractAction.class:]
    ...

最初のセクション (上部の唯一の行を除く) はContextLoaderListener、Spring ContextLoader を起動してプロセスMETA-INF/spring/wfadmin-context.xmlを実行するように構成されていることを示しています。

2 番目のセクションは、Gemini ブループリントがこれがブループリント バンドルであることを検出し、構成から独自のコンテキストを開始することを示していますMETA-INF/spring/wfadmin-{,osgi-}context.xml。また、BeanwfEngineが OSGi サービスから正常にインポートされたこともわかります。

3 番目のセクションは、Spring Struts アプリケーション コンテキストでse.sunstone.util.web.AbstractActionBean にアクセスしようとしたときにmy がどのように停止するかを示しています。Beanのみが含まれているwfEngineため、これは予想されますが、含める場合workflow-context.xmltestBeanInMetaInfSpringWorkflowContextXml

<osgi:reference id="wfEngineInMetaInfSpringWfAdminContextXml" interface="se.sunstone.workflow.WorkflowEngine"/>

(workflow-context.xml適切なxmlns:osgi定義で) では、Web アプリケーションは起動さえしません。

09:43:30,026 SEVERE [org.springframework.web.context.ContextLoader] (MSC service thread 1-4) Context initialization failed: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/osgi]
Offending resource: ServletContext resource [/META-INF/spring/wfadmin-context.xml]

Spring Strugs プラグインにアプリケーション コンテキストを Gemini ブループリントと共有するように指示する方法があればいいのにと思います。これは可能ですか?

完全を期すために、Spring-Blueprint 構成は次のようになります。

META-INF/spring/wfadmin-context.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:osgi="http://www.springframework.org/schema/osgi"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

  <bean id="testBeanInMetaInfSpringWfadmiContextXml" class="java.lang.Object"/>
  <!--<osgi:reference id="wfEngineInMetaInfSpringWfAdminContextXml" interface="se.sunstone.workflow.WorkflowEngine"/>-->

</beans>

META-INF/spring/wfadmin-osgi-context.xml(Gemini ブループリントによって読み込まれます):

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="testBeanInMetaInfSpringWfadminOsgiContextXml" class="java.lang.Object"/>
  <reference id="wfEngine" interface="se.sunstone.workflow.WorkflowEngine" availability="mandatory"/>

</blueprint>
4

2 に答える 2

1

多少の努力で、私はそれを機能させることができました。ContextLoaderListenerはまだ道のりですが、OSGi を認識させるには、いくつかの調整が必要です。

私の場合の解決策は、いくつかのステップで構成されていました。

ステップ 1: Gemini Blueprint を Spring OSGi に置き換える

プレーンContextLoaderListenerの代わりに create を作成する必要があります。私の知る限り、このクラスを提供する Gemini Blueprint のディストリビューションはまだないため、代わりにspring-osgi-webバンドルを配布した Spring OSGi を使用する必要があります。OsgiBundleXmlWebApplicationContextXmlWebApplicationContext

Gemini Blueprint エクステンダー jar を使用する代わりに、次の Spring OSGi jar を使用しました。

(そしてもちろん、それらの依存関係は、簡潔にするために省略されています)

アプリケーション コンテキスト構成の一部で派手な新しい<blueprint>ルート要素と名前空間を使用していたため、これを Spring OSGi の同等のものと交換する必要がありました (特に、が にavailability="mandatory"なることに注意してcardinality="1..1"ください)。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
    <reference id="wfEngine" interface="se.sunstone.workflow.WorkflowEngine" cardinality="1..1"/>
</beans>

Gemini Blueprintでは名前空間は交換可能ですが、Spring OSGi は Blueprint よりも古いため、Blueprint の名前空間などは Spring OSGi では機能しません。

ステップ 2: Spring OSGi が war を Spring バンドルとして認識しないようにする

これは、アプリケーション コンテキストを から移動し、META-INF/spring代わりに に配置するだけで実現できましたWEB-INF/applicationContext.xml。これは、ContextLoaderListener がアプリケーション コンテキスト構成を探すためのデフォルトの場所です。

ステップ 3: ContextLoaderListener を OSGi 対応にする

次に、こちらの手順に従ってorg.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext、アプリケーション コンテキストの型として使用する ContextLoaderListener を構成しました。これにより、新しいエラーが表示されました。

java.lang.IllegalArgumentException: bundle context should be set before refreshing the application context

いくつかの検索の後、私はこのブログ投稿に出くわし、それを試しました. そこでOsgiWebBundleContext提供されたものは機能しませんでしたが、それでも同じエラーが発生しました。この新しいコンテキスト タイプにトレース出力を追加することで、バンドル コンテキストが実際には存在しないことを確認できました。

17:15:20,233 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) Attributes in servletContext:
17:15:20,233 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) org.apache.jasper.JSP_PROPERTY_GROUPS
17:15:20,233 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) javax.servlet.context.tempdir
17:15:20,233 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) org.apache.jasper.JSP_TAG_LIBRARIES
17:15:20,233 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) javax.websocket.server.ServerContainer
17:15:20,234 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) org.apache.jasper.SERVLET_VERSION
17:15:20,234 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) org.jboss.as.jsf.FACES_ANNOTATIONS
17:15:20,234 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) org.apache.tomcat.InstanceManager
17:15:20,234 FINEST [se.sunstone.workflow.web.osgi.workaround.OsgiBundleXmlWebApplicationContextWithCorrectBundleContextLookupName] (MSC service thread 1-5) End of attributes in servletContext

しかし、少なくとも Spring は OSGi 対応になりました。これが出発点です。

ステップ 4: 不足している BundleContext を回避する

BundleContext が ServletContext に設定されていないか、設定される前に Spring がアクセスを試みているようです。いずれにせよ、この回答FrameworkUtil.getBundle(ClassFromBundle).getBundleContext()は、BundleContext を見つけるために使用するブログ投稿から回避策クラスを変更するように促しました。

public class OsgiBundleXmlWebApplicationContextSettingBundleContextFromFrameworkUtil
        extends OsgiBundleXmlWebApplicationContext {
    @Override
    public void setServletContext(ServletContext servletContext) {
        if(getBundleContext() == null) {
            BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
            if(context != null) {
                setBundleContext(context);
            }
        }

        // to call "this.servletContext = servletContext;" in super
        super.setServletContext(servletContext);
    }

}

そして、それは私のために働いた!これは最も美しい解決策ではないかもしれませんが、これまでのところ私がうまくいった唯一の解決策です.*

(まあ、私も を使っBundleActivatorて動作させましたが、それはおそらくそれほどきれいではありませんでした。)

于 2013-07-04T15:50:22.113 に答える