在GlassFish中使用Struts2 OSGi插件

时间:2013-01-07 16:47:33

标签: struts2 glassfish osgi

我试图了解Struts2 OSGi插件是如何工作的,所以我开始尝试部署this blog post提供的测试应用程序。我已从WEB-INF / classes / bundles / 2文件夹中删除了所有捆绑包,并尝试一次添加一个捆绑包,以便更好地解决我的问题。我面临的问题如下:

(1)当我尝试包含MyOsgi.jar包(它是一个只包含一个实现BundleActivator的类的空包)时,我在部署应用程序时遇到以下错误:

  

[#| 2013-01-07T18:32:14.425 + 0200 |严重| glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | _ThreadID = 105; _ThreadName = Thread- 2; | java.lang.ClassCastException:   myosgi.Activator无法强制转换为org.osgi.framework.BundleActivator         在org.apache.felix.framework.Felix.createBundleActivator(Felix.java:3548)         在org.apache.felix.framework.Felix._startBundle(Felix.java:1666)         在org.apache.felix.framework.Felix.startBundle(Felix.java:1588)         在org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1180)         在org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265)         在java.lang.Thread.run(Thread.java:722)       |#] [#| 2013-01-07T18:32:14.513 + 0200 | SEVERE | glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | _TreadID = 105; _TreadName = Thread- 2; |在   org.apache.felix.framework.Felix.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 =线程2; |在   org.apache.felix.framework.Felix._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 =线程2; |在   org.apache.felix.framework.Felix.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 =线程2; |在   org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1180)|#]
      [#| 2013-01-07T18:32:14.514 + 0200 |严重| glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | _ThreadID = 105; _ThreadName =线程2; |在   org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265)|#]
      [#| 2013-01-07T18:32:14.514 + 0200 |严重| glassfish3.1.2 | javax.enterprise.system.std.com.sun.enterprise.server.logging | _ThreadID = 105; _ThreadName =线程2; |在   java.lang.Thread.run(Thread.java:722)|#]

根据this,上述错误是由于JVM中加载了多个BundleActivator类这一事实,这是有道理的,因为包含它的felix.jar已经可以在GlassFish中使用了felix jar作为Struts2 OSGi插件的依赖项包含在我的应用程序中。我已经尝试从插件中排除felix依赖项(我使用Maven来构建应用程序)但这不起作用,因为作为依赖项包含的felix jar还包括felix.jar中不存在的其他类。

(2)当我尝试包含struts2-osgi-demo-bundle-2.3.1包时,我得到了一个完全不同的错误,我不明白它可能是什么原因:

  

[#| 2013-01-07T18:30:02.897 + 0200 |严重| glassfish3.1.2 | javax.enterprise.system.container.web.com.sun.enterprise.web | _ThreadID = 42; _ThreadName = Thread- 2; | WebModule [/ OSGi的] PWC1270:   异常启动过滤器struts2 java.lang.LinkageError:loader   约束违规:loader(实例)   org / apache / felix / framework / searchpolicy / ContentClassLoader)之前   为名称不同的类型启动加载   "组织/ OSGi的/框架/的BundleContext"在   java.lang.Class.getDeclaredMethods0(Native Method)at   java.lang.Class.privateGetDeclaredMethods(Class.java:2442)at at   java.lang.Class.privateGetPublicMethods(Class.java:2562)at   java.lang.Class.getMethods(Class.java:1427)at   org.apache.struts2.convention.PackageBasedActionConfigBuilder.getActionAnnotations(PackageBasedActionConfigBuilder.java:792)     在   org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedActionConfigBuilder.java:605)     在   org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedActionConfigBuilder.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_PreloadConfiguration(Dispatcher.java:390)org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:436)     在   org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:69)     在   org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.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:5377)     在com.sun.enterprise.web.WebModule.start(WebModule.java:498)at   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.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:179)     在   com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117)     在   com.sun.enterprise.v3.services.impl.ContainerMapper $ Hk2DispatcherCallable.call(ContainerMapper.java:354)     在   com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)     在   com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)     在   com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)     在   com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)     在   com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)     在   com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)     在   com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)     在   com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)     在   com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)     在   com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)     在   com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)     在com.sun.grizzly.ContextTask.run(ContextTask.java:71)at   com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:532)     在   com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:513)     在java.lang.Thread.run(Thread.java:722)|#]

我注意到struts2-osgi-demo-bundle-2.3.1包没有BundleActivator类,我猜测这就是我没有得到上一个错误的原因,但是这并没有#&# 39;帮助我找到解决方案。

最后,我可以在Tomcat中部署包含两个捆绑包的应用程序而没有任何问题,这使我得出结论,这两个问题都与GlassFish的felix.jar的存在有关。

有没有人在GlassFish中使用过Struts2 OSGi插件,或者您是否知道如何克服这些问题?

UPDATE:上面的第二个错误是由于bundle中包含的BundlesAction类实现的,它实现了BundleContextAware。根据插件的文档,插件定义了OSGi拦截器,

  

将检查操作以及是否实现   org.apache.struts2.osgi.interceptor.BundleContextAware,它将调用   setBundleContext(BundleContext bundleContext)上的动作,传递   OSGi容器的BundleContext。

我猜是问题出在哪里。

更新2:由于Lukasz和Tang建议需要更新插件才能使用更新的Felix版本,并且(可能)使用GlassFish已经提供的OSGi运行时而不是启动新的一。对此,我有以下问题:

  1. 是否可以在同一个应用程序服务器中拥有两个OSGi运行时,即。插件可以忽略服务器的OSGi运行时并启动它自己(当然假设它被更新为使用与GlassFish相同的Felix版本,以便在类路径中没有多个版本的Felix类)?
  2. 为了使用GlassFish的OSGi运行时,插件需要获取它的引用。这可以在未部署为OSGi包的Web应用程序中完成吗?如果有,怎么样?

11 个答案:

答案 0 :(得分:1)

我对struts不熟悉。根据我的看法[1],struts2-osgi插件负责两件事:

  1. 创建OSGi框架,
  2. 为OSGi运行时提供Web管理界面。
  3. 这两个功能都已内置在使用OSGi构建的GlassFish中。所以,我没有看到在GlassFish中运行基于osgi的struts2包时需要使用这个插件。因此,请尝试执行以下操作:

    1. 将struts2核心包部署到glassfish
    2. 将您的应用程序包部署到glassfish。
    3. 对于这两个操作,您需要使用GlassFish OSGi Admin界面。要了解有关它们的更多信息,请查看[2]。最简单的选择是将bundle复制到domain1 / autodeploy / bundles / dir,然后更新文件以查看它们在OSGi运行时中的更新。

      希望这有帮助, Sahoo。

      ps:请使用glassfish论坛来解决玻璃鱼问题。

答案 1 :(得分:1)

在Tang Yong的帮助下,我可以升级Struts2 OSGi插件,现在你可以将它与Glassfish 3一起使用。它应该很快就会作为Struts2版本2.3.15的一部分发布。

https://issues.apache.org/jira/browse/WW-3958

答案 2 :(得分:0)

您始终可以将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>

答案 3 :(得分:0)

我的初步调查如下:

1 struts2-osgi-plugin使用StrutsOsgiListener作为Web上下文侦听器,并且在执行StrutsOsgiListener.contextInitialized方法时,struts2-osgi-plugin将启动嵌入式felix运行时,该运行时通常位于WEB-INF / lib下。至于Struts2OSGi,这个嵌入的felix运行时是felix 1.4.1。

2因为glassfish v3 / v4的内核默认基于felix,并且在启动glassfish域之后,在当前系统中,存在来自glassfish本身的osgi运行时。因此,在将struts2-osgi-plugin相关应用程序部署到glassfish v3 / v4时,会有两个osgi运行时,这会导致与部署环境发生冲突,而且在尝试生成bundleactivator时会发生强制转换异常。

然后,如何使它们正常工作?

我的计划是扩展struts2-osgi-plugin, 1)创建一个GlassfishOsgiHost,它实现OsgiHost接口以满足glassfish部署场景。注意:glassfish本身也可以被视为osgi容器。

2)需要一些方法来配置struts2-osgi-plugin以告诉它当前部署的env是否具有osgi运行时以便调用正确的OsgiHost实现

事情并不容易,我会尝试,同时,如果你对我的想法感兴趣,请告诉我,我们可以一起做。

答案 4 :(得分:0)

我已经在github上创建了一个repo 1,我将开始做这样的扩展,一旦完成这样的扩展,我会回复你。

答案 5 :(得分:0)

关于克里斯蒂娜所说的“从WEB-INF / classes / bundles / 2文件夹中删除所有包”,我需要说一旦你部署了demo(包括myosgi包)一次,你从中移除所有包WEB-INF / classes / bundles / 2文件夹并希望再次部署演示,在server.log中,您仍然可以找到myosgi和其他捆绑包相关的异常。

原因是你在第一次部署demo之后,struts2-osgi-plugin将已部署的bundle保存到osgi缓存中,例如。对于Windows,这个缓存是“C:\ DOCUME~1 \ ADMINI~1 \ LOCALS~1 \ Temp.felix-cache”,因此,在部署demo之前(从WEB-INF / classes / bundles / 2中删除所有bundle)文件夹)第二次,请删除缓存。

事实上,我已经确认在删除缓存并再次部署不包含bundle / 2的任何bundle的demo之后,在server.log中,任何异常都不会发生。 并且,我还确认在“C:\ DOCUME~1 \ ADMINI~1 \ LOCALS~1 \ Temp.felix-cache”中,安装了三个软件包,如下所示:

1)org.apache.felix.main 4.0.2

bundle.location:file:/ D:/1214/glassfish2/glassfish3/glassfish/osgi/felix/bin/felix.jar

2)org.apache.felix.shell 1.0.2

bundle.location:file:/ D:/1214/glassfish2/glassfish3/glassfish/domains/domain1/applications/osgi-2.3.1/WEB-INF/lib/org.apache.felix.shell-1.0.2的.jar

3)只有一个bundle.id文件,我想它应该是系统包。

但是,有关上述三个捆绑包需要调查的问题,

1)在demo的WEB-INF / lib中,org.apache.felix.main的版本是1.4.1而不是4.0.2,4.0.2应该是glassfish的felix版本(这一点可以通过bundle位置确认)

2)为什么第三个包只是bundle.id文件而没有其他安装信息。

无论出现这些问题,似乎都可以在同一个应用服务器中运行两个OSGi运行时。

但是,我会看到在添加struts2-osgi-admin-bundle-2.3.1.jar时会发生什么,会发生什么。

所以,可能有两个调查方向:

1)在glassfish中有两个OSGi运行时 2)在oder中扩展struts2-osgi-plugin,让bundle只能由glassfish osgi运行时管理

答案 6 :(得分:0)

深入地说,在server.log中添加struts2-osgi-admin-bundle-2.3.1.jar时,会发生以下两个主要异常,

1)无法解析package = javax.servlet

[#| 2013-01-11T15:22:58.296 + 0900 | SEVERE | glassfish 4.0 | javax.enterprise.logging.stderr | _ThreadID = 85; _TreadName = FelixStartLevel; _TimeMillis = 1357885378296; _LevelValue = 1000; | org。 osgi.framework.BundleException:bundle 1中的未解决约束:package; (包=的javax.servlet)     在org.apache.felix.framework.Felix._resolveBundle(Felix.java:1792)     在org.apache.felix.framework.Felix._startBundle(Felix.java:1652)     在org.apache.felix.framework.Felix.startBundle(Felix.java:1588)     在org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1180)     在org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265)     在java.lang.Thread.run(Thread.java:722) |#]

包由struts2-osgi-admin-bundle-2.3.1.jar导入。

2)无法找到类org.apache.struts2.osgi.admin.actions.BundlesAction

[#| 2013-01-11T15:23:00.578 + 0900 | INFO | glassfish 4.0 | javax.enterprise.logging.stdout | _ThreadID = 79; _TreadName = admin-listener(1); _ TimeMillis = 1357885380578; _LevelValue = 800; | 15:23:00:578 DEBUG(com.opensymphony.xwork2.config.providers.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)     at org.apache.struts2.osgi.DelegatingObjectFactory.getClassInstance(DelegatingObjectFactory.java:77)     在com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.verifyAction(XmlConfigurationProvider.java:416)     在com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addAction(XmlConfigurationProvider.java:370) ...

所以,首先,我们必须调查“C:\ DOCUME~1 \ ADMINI~1 \ LOCALS~1 \ Temp.felix-cache”中包的安装逻辑。

答案 7 :(得分:0)

我认为我已经知道为什么将org.apache.felix.main 4.0.2安装到felix缓存而不是WEB-INF / lib / org.apache.felix.framework-1.4.1.jar中的一些原因。通常,应该安装org.apache.felix.framework-1.4.1.jar,你可以通过tomcat确认这一点。

好的,我开始说原因是:

问题发生在FelixOsgiHost.startFelix()151行,

bundleJarsLevel1.add(getJarUrl(ServiceTracker.class));

在glassfish场景中,getJarUrl(ServiceTracker.class)返回... / glassfish3 / glassfish / osgi / felix / bin / felix.jar而不是glassfish3 / glassfish / domains / domain1 / applications / osgi-2.3.1 / WEB -INF / lib / org.apache.felix.framework-1.4.1.jar因为glassfish osgi运行时,这将导致捆绑部署的许多冲突。

如果我们更新插件的felix版本,也许问题可能会消失,但是,用于插件的osgi嵌入模式应该是好的并且不受glassfish osgi运行时的影响。我们可以想象如果嵌入的osgi运行时来自equinox,同样的问题仍然会发生。

我将通过硬编码getJarUrl(ServiceTracker.class)进行快速测试,以确定问题是否真正由它引起。

答案 8 :(得分:0)

现在,关于将felix 1.4.1更新为4.0.2,我已完成增强,please seeing my fixing here

基本上,felix 1.x和4.x之间的实现差异很大,所以我们需要更新插件的pom和felix嵌入式启动方式的一些地方。

我在tomcat 7下测试过。

答案 9 :(得分:0)

事实证明,根据this post,你可以使用GlasssFish_Platform = Static来启动没有OSGi的GlassFish,在这种情况下,插件可以工作,因为当插件自己启动时没有现有的OSGi运行时。但是我并不认为这是一个解决方案,更多的是解决方法,因为它会导致其他问题(例如GlassFish管理控制台,这是一个OSGi包,不可用)。

答案 10 :(得分:0)

实际上,我昨天已经对问题进行了大量调查,我们必须解决一个关键问题:

在战争中嵌入osgi运行时并在现有的osgi运行时下进行战争时,我们必须小心处理一些系统包。

以下是sahoo回复中的一篇有价值的文章。

我将根据帖子制作一个新的实现,因为现在,我遇到了这个问题。

Jsfiddle