我正在尝试了解Struts2OSGi插件是如何工作的,所以我首先尝试部署这篇博客文章中提供的测试应用程序。我已经从WEB-INF/classes/bundles/2文件夹中删除了所有捆绑包,并尝试一次添加一个,以便更好地解决我的问题。我面临的问题如下:
(1) 当我试图包含MyOsgi.jar捆绑包(它是一个空的捆绑包,只包含一个实现BundleActivator的类)时,我在部署应用程序时遇到了以下错误:
[#|2013-01-07T18:32:14.425+0200|SEVERE|glassfish3.1.2.|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|java.lang.ClassCastException:myosgi。激活器无法转换为org.osgi.framework.BundleActivator网址:org.apache.filex.framework.Fix.createBundleActivator(felix.java:3548)网址:org.apache.filex.framework.Fix_startBundle(felix.java:1666)网址:org.apache.filex.framework.Filex.startBundle(felix.java:1588)网址:org.apache.filex.framework.Fix.setFrameworkStartLevel(felix.java:1180)网址:org.apache.filex.framework.StartLevelImpl.run(StartLevelImpl.java:265)在java.lang.Thread.run(线程.java:722)|#][#|2013-01-07T18:32:14.513+0200|SEVERE|glassfish3.1.2.|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atorg.apache.filex.framework.Filex.createBundleActivator(felix.java:3548)|#][#|2013-01-07T18:32:14.513+0200|SEVERE|glassfish3.1.2.|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atorg.apache.filex.framework.Filex._startBundle(felix.java:1666)|#][#|2013-01-07T18:32:14.513+0200|SEVERE|glassfish3.1.2.|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atorg.apache.filex.framework.Filex.startBundle(felix.java:1588)|#][#|2013-01-07T18:32:14.513+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atorg.apache.filex.framework.Filex.setFrameworkStartLevel(felix.java:1180)|#]
[#|2013-01-07T18:32:14.514+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atorg.apache.filex.framework.StartLevelImpl.run(StartLevelImpl.java:265)|#]
[#|2013-01-07T18:32:14.514+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=105;_ThreadName=Thread-2;|atjava.lang.Thread.run(线程.java:722)|#]
根据这一点,上述错误是由于JVM中加载了多个BundleActivator类,这是有道理的,因为包含它的felix.jar已经在GlassFish中可用,并且我的应用程序中包含了许多作为Struts2 OSGi插件依赖项的felixjar。我尝试过从插件中排除felix依赖项(我正在使用Maven构建应用程序),但这不起作用,因为作为依赖项包含的felix jar还包括felix.jar中不存在的其他类。
(2) 当我试图包括struts2-osgi-demo-bundle-2.3.1捆绑包时,我得到了一个完全不同的错误,我不知道可能是什么原因:
[#|2013-01-07T18:30:02.897+0200|SEVERE|glassfish3.1.2.|javax.enterprise.system.contage.web.com.sun.enterprise.web|_ThreadID=42;_ThreadName=Thread-2;|WebModule[/osgi]PWC1270:启动筛选器struts2 java.lang.LinkageError时出现异常:加载程序约束冲突:加载程序(的实例org/apache/filix/framework/searchpolicy/ContentClassLoader)已启动名称为的其他类型的加载"org/osgi/framework/BundleContext"位于的java.lang.Class.getDeclaredMethods0(本机方法)位于的java.lang.Class.privateGetDeclaredMethods(Class.java:2442)位于的java.lang.Class.privateGetPublicMethods(Class.java:2562)java.lang.Class.getMethods(Class.java:1427)位于org.apache.struts2.convention.PackageBasedActionConfigBuilder.getActionAnnotations(PackageBasedAactionConfigBuilder.java:792)在org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedAactionConfigBuilder.java:605)在org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedAactionConfigBuilder.java:335)在org.apache.struts2.convention.ClasspathPackageProvider.loadPackages(ClasspathPackageProvider.java:53)在org.apache.struts2.osgi.OsgiConfigurationProvider.loadConfigFromBundle(OsgiConfigurationProvider.java:146)在org.apache.struts2.osgi.OsgiConfigurationProvider.loadPackages(OsgiConfigurationProvider.java:96)在com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:215)在com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:66)在org.apache.struts2.dispatcher.dispatcher.init_PeloadConfiguration(dispatcher.java:390),网址为org.apache.sstruts2.disptcher.init(dispatcher.java:436)在org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:69)在org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPPrepareAndExecute filter.java:51)在org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:264)在org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:120)在org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4685)在org.apache.catalina.core.StandardContext.start(StandardContext.java:5537)网址:com.sun.enterprise.web.WebModule.start(WebModule.java:498)org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:917)在org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:901)在org.apache.catalina.core.StandardHost.addChild(StandardHost.java:733)在com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2019)在com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1669)在com.sun.enterprise.web.WebApplication.start(WebApplication.java:109)网址:org.glassfish.internal.data.EngineRef.start(EngineRef.java:130)网址:org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:269)在org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:301)在com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:461)在com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240)在org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:389)在com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:348)在com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:363)在com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1085)在com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:95)在com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1291)在com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1259)在com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:461)在com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:212)在com.sun.grazzly.tcp.http11.GrazzlyAdapter.service(GrizzlyAdaptr.java:179)在com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117)在com.sun.enterprise.v3.services.impl.ContainerMaper$Hk2DispatcherCallable.call(ContainerMaper.java:354)在com.sun.enterprise.v3.services.impl.ContainerMaper.service(ContainerMaper.java:195)在com.sun.grazzy.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)在com.sun.grazzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)在com.sun.grazzly.http.ProcessorTask.produce(ProcessorTask.java:1056)在com.sun.grazzy.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)在com.sun.grazzy.DefaultProtocolChain.executeProtocolFilter(DefaultProtocol Chain.java:137)在com.sun.grazzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)在com.sun.grazzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)在com.sun.grazzy.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)在com.sun.grazzy.ProtocolChainTextTask.doCall(ProtocolchainTextTask.java:54)在com.sun.grazzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)在com.sun.grazzy.ContextTask.run(ContextTask.java:71)com.sun.grazzy.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)在com.sun.grazzy.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)在java.lang.Thread.run(线程.java:722)|#]
我注意到struts2-osgi-demo-bundle-2.3.1捆绑包没有BundleActivator类,我猜这就是我没有得到以前错误的原因,但这对我找到解决方案没有帮助。
最后,我可以在Tomcat中部署包括这两个捆绑包的应用程序,而不会出现任何问题,这使我得出结论,这两个问题都与GlassFish的felix.jar的存在有关
有人在GlassFish中使用过Struts2OSGi插件吗?或者你知道如何克服这些问题吗?
UPDATE:上面的第二个错误是由于bundle中包含的BundlesAction类而发生的,该类实现了BundleContextAware。根据插件的文档,插件定义了OSGi拦截器,
将检查操作以及它是否实现org.apache.struts.osgi.interceptor.BundleContextAware,它将调用对操作设置BundleContext(BundleContext BundleContext),传递OSGi容器的BundleContext。
我猜这就是问题的开始。
更新2:正如Lukasz和Tang所建议的,插件需要更新,以便使用更新的Felix版本,并且(可能)使用GlassFish已经提供的OSGi运行时,而不是启动新的运行时。在这方面,我有以下问题:
- 是否可以在同一个应用程序服务器中有两个OSGi运行时,即插件是否可以忽略服务器的OSGi运行时间并启动自己的运行时(当然,假设它被更新为使用与GlassFish相同的Felix版本,这样类路径中就不会有多个版本的Felix类)
- 为了使用GlassFish的OSGi运行时,插件需要获得对它的引用。这可以在没有作为OSGi捆绑包部署的web应用程序中完成吗?如果是,如何
在唐勇的帮助下,我升级了Struts2OSGi插件,现在您可以在Glassfish 3中使用它了。它应作为Struts2 2.3.15版本的一部分尽快发布。
https://issues.apache.org/jira/browse/WW-3958
我不熟悉struts。根据我对[1]的理解,struts2 osgi插件负责两件事:
- 创建一个OSGi框架
- 为OSGi运行时提供web管理接口
这两个函数都已经内置在GlassFish中,GlassFish是使用OSGi构建的。因此,我认为在GlassFish中运行基于osgi的struts2捆绑包时没有必要使用这个插件。因此,尝试执行以下操作:
- 将struts2核心束部署到glassfish
- 将您的应用程序捆绑包部署到glassfish
对于这两种操作,都需要使用GlassFish OSGi管理接口。要了解更多关于它们的信息,请参阅[2]。最简单的选择是将bundle复制到domain1/autodeploy/bundles/dir,然后更新文件以查看它们在OSGi运行时中的更新。
希望这能有所帮助,萨胡。
ps:关于玻璃鱼的问题,请使用玻璃鱼论坛。
- [1]https://cwiki.apache.org/S2WIKI/struts-25-based-on-osgi.html
- [2]http://glassfish.java.net/public/GF-OSGi-Features.pdf
您可以始终排除Felix依赖项,如下所示:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-plugin</artifactId>
<version>2.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.main</artifactId>
<exclusion>
</exclusions>
</dependency>
我的初步调查如下:
1 struts2 osgi插件使用一个StrutsOsgiListener作为web上下文侦听器,在执行StrutsOsgiListener.textInitialized方法时,struts2 oski插件将启动一个嵌入的felix运行时,该运行时通常位于web-INF/lib下。至于Struts2OSGi,这个嵌入的felix运行时是felix 1.4.1。
2因为glassfish v3/v4的内核默认基于felix,并且在启动glassfishdomain之后,在当前系统中,已经存在了来自glassefish本身的osgi运行时。因此,在将struts2 osgi插件相关的应用程序部署到glassfish v3/v4中时,会有两个osgi运行时,这与部署环境产生了一些冲突,而且在尝试强制转换bundleactivator时,会发生强制转换异常。
那么,如何让它们正常工作呢?
我的计划是扩展struts2 osgi插件,1) 创建了一个GlassfishOsgiHost,实现了OsgiHost接口以满足glassfish部署场景。注意:玻璃鱼本身也可以被视为osgi容器。
2) 需要某种方式来配置struts2 osgi插件,以便告诉它当前部署的env是否有osgi运行时,以便调用正确的OsgiHost实现
事情并不容易,我会尝试,同时,如果你对我的想法感兴趣,请告诉我,以便我们一起做。
我在github上创建了一个repo 1,我会开始做这样的扩展,一旦完成这样的扩展我会回复你。
关于Christina所说的"从WEB-INF/classes/bundles/2文件夹中删除了所有捆绑包",我需要说的是,一旦您部署了一次demo(包括myosgi捆绑包),而您从WEB-INF/classes/bundles/2文件夹中删除了全部捆绑包并希望再次部署demo,在server.log中,您仍然可以找到myosgi和其他捆绑包相关的异常。
原因是,在您第一次部署demo后,struts2 osgi插件将部署的捆绑包保存到osgi缓存中,例如,对于windows,该缓存为"C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp.filex缓存",因此,在您第二次部署demo(从WEB-INF/classes/bundles/2文件夹中删除所有捆绑包)之前,请删除该缓存。
事实上,我已经确认,在删除缓存并再次在server.log中部署不包括bundles/2中任何bundle的演示之后,不会发生任何异常。而且,我还确认,在"C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp.filex缓存"中,安装了三个捆绑包,如下所示:
1) org.apache.filex.main 4.0.2
bundle.location:文件:/D:/1214/glassfish2/glassfish3/glassfish/osgi/felix/bin/felix.jar
2) org.apache.filex.shell 1.0.2
bundle.location:文件:/D:/1214/glassfish2/glassfish3/glassfish/domain1/applications/osgi-2.3.1/WEB-INF/lib/org.apache.filex.shell-1.0.2.jar
3) 只有一个bundle.id文件,我想它应该是系统捆绑包。
然而,关于上述三个束,还有一些问题需要研究
1) 在demo的WEB-INF/lib中,org.apache.filex.main的版本是1.4.1而不是4.0.2,4.0.2应该是glassfish的felix版本(这一点可以通过捆绑包的位置来确认)
2) 为什么第三个捆绑包只有bundle.id文件,没有其他安装信息。
不管这些问题如何,在同一个应用程序服务器中拥有两个OSGi运行时似乎是可能的。
然而,我将在添加struts2-osgi-admin-bndle-2.2.3.1.jar时看到会发生什么,会发生什么。
所以,也许有两个调查方向:
1) 在glassfish中有两个OSGi运行时2) 在oder中扩展struts2 osgi插件,使捆绑包仅由glassfish osgi运行时管理
在server.log中添加struts2-osgi-admin-bndle-2.2.3.1.jar时,发生了以下两个主要异常:
1) 无法解析包=javax.servlet
[#|2013-01-11T15:22:58.296+0900|SEVERE|glassfish4.0|javax.enterprise.logging.stderr|_ThreadName=FelixStartLevel;_TimeMillis=1357885378296;_LevelValue=1000;|org.osgi.framework.BundleException:捆绑包1中未解决的约束:package;(package=javax.servlet)网址:org.apache.filex.framework.Fix.resolveBundle(felix.java:1792)网址:org.apache.filex.framework.Fix_startBundle(felix.java:1652)网址:org.apache.filex.framework.Filex.startBundle(felix.java:1588)网址:org.apache.filex.framework.Fix.setFrameworkStartLevel(felix.java:1180)网址:org.apache.filex.framework.StartLevelImpl.run(StartLevelImpl.java:265)在java.lang.Thread.run(线程.java:722)|#]
该包通过struts2-osgi-admin-bndle-2.2.3.1.jar导入。
2) 找不到org.apache.struts2.osgi.admin.actions.BundlesAction类
[#|2013-01-11T15:23:00.578+0900|INFO|glassfish4.0|javax.enterprise.logging.stdout|_ThreadID=79;_ThreadName=admin listener(1);_TimeMillis=1357885380578;_LevelValue=800;|15:23:00:578 DEBUG(com.opensymphony.xwork2.config.provider.XmlConfigurationProvider:72)-找不到操作的类[org.apache.struts2.osgi.admin.actions.BundlesAction]java.lang.ClassNotFoundException:找不到类org.apache.struts2.osgi.admin.actions.BundlesAction网址:org.apache.struts2.osgi.DefaultBundleAccessor.loadClass(DefaultBundleAccessor.java:115)网址:org.apache.struts2.osgi.DelegatingObjectFactory.getClassInstance(DelegatingObjectFactory.java:77)网址:com.opensymphony.xwork2.config.products.XmlConfigurationProvider.verifyAction(XmlConfigurationProvider.java:416)网址:com.opensymphony.xwork2.config.products.XmlConfigurationProvider.addAction(XmlConfigurationProvider.java:370)…
因此,首先,我们必须研究位于"C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp.filix缓存"中的bundle的安装逻辑。
我想我已经知道为什么将org.apache.filex.main 4.0.2安装到felix缓存中而不是WEB-INF/lib/org.apache.fielix.framework-1.4.1.jar的一些原因了。通常情况下,应该安装org.apache.felix.framework-1.4.1.jar,您可以通过tomcat确认这一点。
好吧,我开始说原因是流动的:
问题发生在FelixOsgiHost.startFelix()151行,上
bundleJarsLevel1.add(getJarUrl(ServiceTracker.class));
在玻璃鱼场景中,getJarUrl(ServiceTracker.class)返回/glassfish3/glassfish/osgi/felix/bin/felix.jar而不是glassfish3/glassfish/domains/domain1/applications/osgi-2.3.1/WEB-INF/lib/org.apache.filex.framework-1.4.1.jar由于glassfish-osgi运行时,这将导致捆绑包部署的许多冲突。
如果我们更新插件的felix版本,这个问题可能会消失,但是,用于插件的osgi嵌入模式应该是好的,不受glassfish osgi运行时的影响。我们可以想象,如果嵌入的osgi运行时来自equinox,同样的问题仍然会发生。
我将通过硬编码getJarUrl(ServiceTracker.class)来做一个快速测试,看看问题是否真的是由它引起的
事实证明,根据这篇文章,您可以使用GlassFish_Platform=Static在没有OSGi的情况下启动GlassFish,在这种情况下,插件将工作,因为当插件启动自己的插件时,没有现有的OSGi运行时。然而,我并不认为这是一个解决方案,更多的是一种变通方法,因为它会导致其他问题(例如GlassFish管理控制台,它是一个OSGi捆绑包,不可用)。
现在,关于将felix 1.4.1更新到4.0.2,我已经完成了增强,请在这里查看我的修复
基本上,felix 1.x和4.x之间的实现差异有点大,所以我们需要更新插件的pom和felix嵌入式启动方式的一些地方。
我在tomcat 7下测试合格。
事实上,我昨天已经对这个问题进行了大量调查,我们必须解决一个关键问题:
在嵌入war中的osgi运行库并在现有的osgi执行库下启动war时,我们必须小心处理一些导出的系统包。
以下是sahoo回复之前的一篇有价值的帖子。
我会在帖子的基础上做一个新的实现,因为现在,我已经遇到了问题。
Jsfidle