I am trying to see how the Struts2 OSGi plugin works so I started by trying to deploy the test application provided with this blog post. I have removed all bundles from the WEB-INF/classes/bundles/2 folder and try adding them one at a time in order to better troubleshoot my problem. The issues I face are the following:
(1) When I try to include the MyOsgi.jar bundle (its an empty bundle containing only one class implementing BundleActivator) I get the following error during the deployment of the application:
[#|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.Activator cannot be cast to org.osgi.framework.BundleActivator at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:3548) at org.apache.felix.framework.Felix._startBundle(Felix.java:1666) at org.apache.felix.framework.Felix.startBundle(Felix.java:1588) at org.apache.felix.framework.Felix.setFrameworkStartLevel(Felix.java:1180) at org.apache.felix.framework.StartLevelImpl.run(StartLevelImpl.java:265) at 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|_ThreadID=105;_ThreadName=Thread-2;| at 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=Thread-2;| at 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=Thread-2;| at 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=Thread-2;| at org.apache.felix.framework.Felix.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;| at org.apache.felix.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;| at java.lang.Thread.run(Thread.java:722)|#]
According to this the above error is due to the fact that there is more than one BundleActivator class loaded in the JVM, which makes sense since felix.jar which contains it is already available in GlassFish and a number of felix jars are included in my application as dependencies of the Struts2 OSGi plugin. I have tried excluding the felix dependencies from the plugin (I am using Maven to build the application) but this doesn't work since the felix jars included as dependencies also include other classes not present in felix.jar.
(2) When I try to include the struts2-osgi-demo-bundle-2.3.1 bundle I get a completely different error for which I have no idea what might be the cause:
[#|2013-01-07T18:30:02.897+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=42;_ThreadName=Thread-2;|WebModule[/osgi]PWC1270: Exception starting filter struts2 java.lang.LinkageError: loader constraint violation: loader (instance of org/apache/felix/framework/searchpolicy/ContentClassLoader) previously initiated loading for a different type with name "org/osgi/framework/BundleContext" at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2442) 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) at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedActionConfigBuilder.java:605) at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedActionConfigBuilder.java:335) at org.apache.struts2.convention.ClasspathPackageProvider.loadPackages(ClasspathPackageProvider.java:53) at org.apache.struts2.osgi.OsgiConfigurationProvider.loadConfigFromBundle(OsgiConfigurationProvider.java:146) at org.apache.struts2.osgi.OsgiConfigurationProvider.loadPackages(OsgiConfigurationProvider.java:96) at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:215) at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:66) at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:390) at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:436) at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:69) at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:51) at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:264) at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:120) at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4685) at org.apache.catalina.core.StandardContext.start(StandardContext.java:5377) at com.sun.enterprise.web.WebModule.start(WebModule.java:498) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:917) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:901) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:733) at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2019) at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1669) at com.sun.enterprise.web.WebApplication.start(WebApplication.java:109) at org.glassfish.internal.data.EngineRef.start(EngineRef.java:130) at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:269) at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:301) at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:461) at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240) at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:389) at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:348) at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:363) at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1085) at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:95) at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1291) at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1259) at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:461) at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:212) at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:179) at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117) at com.sun.enterprise.v3.services.impl.ContainerMapper$Hk2DispatcherCallable.call(ContainerMapper.java:354) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) at com.sun.grizzly.ContextTask.run(ContextTask.java:71) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) at java.lang.Thread.run(Thread.java:722) |#]
I noticed that the struts2-osgi-demo-bundle-2.3.1 bundle has no BundleActivator class, which I'm guessing is the reason why I don't get the previous error, however this doesn't help me in finding a solution.
Finally, I can deploy the application including both bundles without any problems in Tomcat, which leads me to the conclusion that both problems have to do with the presence of GlassFish's felix.jar.
Has anyone used Struts2 OSGi plugin with GlassFish or do you have any idea how to overcome these problems?
UPDATE: The second error above takes place due to the BundlesAction class included in the bundle, which implements BundleContextAware. According to the plugin's documentation the plugin defines the OSGi interceptor, which
will check the action and if it implements org.apache.struts2.osgi.interceptor.BundleContextAware, it will invoke setBundleContext(BundleContext bundleContext) on the action, passing the BundleContext of the OSGi container.
which I am guessing is where the problem starts.
UPDATE 2: As Lukasz and Tang have suggested the plugin needs to be updated in order to use an updated Felix version and (possibly) use the OSGi runtime already available by GlassFish instead of starting a new one. To this regard I have the following questions:
- Is it possible to have two OSGi runtimes in the same application server, ie. can the plugin ignore the server's OSGi runtime and start its own (assuming of course that it is updated to use the same Felix version as GlassFish so as not to have multiple versions of the Felix classes in the classpath)?
- In order to use GlassFish's OSGi runtime the plugin would need to get a reference to it. Can this be done in a web application which is not deployed as an OSGi bundle? If yes, how?