Announcement Announcement Module
Collapse

Spring Dynamic Modules forum decommissioned in favor of Eclipse Gemini Blueprint

With the official first release of Eclipse Gemini Blueprint shipped, the migration of the Spring Dynamic Modules code base to the Eclipse Foundation, as part of the Gemini project, has been completed.

As such, this forum has been decommissioned in favour of the Eclipse Gemini forums.
See more
See less
Struts 2 Integration with Spring DM Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Struts 2 Integration with Spring DM

    Hi,

    Our application is based on struts2 and spring. We have a need to deploy the application in OSGI environment. I have succeeded in migrating the spring layered components (services) to the OSGI environment, however I am not sure how to transform struts2 components (action handlers) to the OSGI environment.

    I have read about struts2-osgi plugin however it works on deployment of the web application inside the servlet container and embedding the osgi container within the servlet container. However I am looking for a solution wherein I can deploy the struts action bundles within the OSGI container along with the servlet container bundle.

    Please let me know of any pointer you have.

    Thanks in advance,
    Shashi

  • #2
    Hi,

    Could somebody please share the thoughts on this?

    I am able to exchange few emails with Don Brown (author of Struts2-OSGi plugin). He has mentioned to use extender pattern in OSGi, the way it is implemented in Spring OSGi Extender.

    However I am not clear on how to achieve this.
    I can think of the following bundles and their interaction.

    The OSGi container is going to host following bundles
    1) Struts2
    2) xwork
    3) Spring DMs
    4) Web container module
    5) Extender bundle for loading the struts action bundles(I am going to code for this)
    6) Struts action bundles developed for the application (application developers are going to code these)

    The extender bundle is going to load the struts configurations from the respective action bundle, however after loading the configurations, what should the extender do? Can it expose the packages it gets as OSGi services? If so, who will consume these services? The struts2-core bundle would require these action to serve the requests from the browser, however to obtain the exposed OSGi actions I need to change struts2 code. Does this sound like a good idea?

    Please share your thoughts.

    Thanks in advance,
    Shashi

    Comment


    • #3
      Shashi, from what I understand you want to host both the web container and struts inside OSGi. Spring DM took this approach for its web integration where the web container is exposed as a service which is then used for deploying wars.
      The war is doing the classloading from the OSGi space so whatever libraries it imports, are used by the war.
      You could do the same thing in your case - create a war with some basic struts2/webwork functionality and deploy that into OSGi along with struts 2 and Spring DM and the container of your choice (see the Spring DM reference documentation).

      From that point on you can identify what packages are needed and whether you have any resource or classloading issues from Struts2.

      Comment


      • #4
        Thanks Costin.

        I am following your idea of making the war module independently work with struts2 and webwork.

        In fact the war is getting deployed fine. Now there is another issue which is again basic OSGi classloading problem I am encountering.

        Let me explain what is the structure of the modules in the equinox environment.
        I have following modules deployed
        1) Spring DMs
        2) Struts2
        3) xwork
        4) action bundle (This has actions required for the application)
        5) web bundle (I had to copy struts2, xwork and struts2-extender in the web-inf/lib and add these jars to the classpath dependency of the web module to make struts filter dispatcher work and dynamically load action modules)

        The struts2-extender jar is the struts2-osgi plugin which I modified a bit so that it can work within the web module. This plugin would load the configurations from the action bundles getting plugged into the container.
        However here I am facing NoClassDefFoundError for struts and xwork related classes. I have added the dependency for these bundles in the web bundle as well as action bundle. The same error persists.

        HTML Code:
        Caused by: java.lang.NoClassDefFoundError: com/opensymphony/xwork2/interceptor/Interceptor
        	at java.lang.ClassLoader.defineClass1(Native Method)
        	at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.defineClass(DefaultClassLoader.java:161)
        	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:501)
        	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassImpl(ClasspathManager.java:471)
        	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClassImpl(ClasspathManager.java:430)
        	at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:413)
        	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:189)
        	at org.eclipse.osgi.framework.internal.core.BundleLoader.findLocalClass(BundleLoader.java:340)
        	at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:408)
        	at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:369)
        	at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:357)
        	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:83)
        	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        	at org.eclipse.osgi.framework.internal.core.BundleLoader.loadClass(BundleLoader.java:289)
        	at org.eclipse.osgi.framework.internal.core.BundleHost.loadClass(BundleHost.java:227)
        	at org.eclipse.osgi.framework.internal.core.AbstractBundle.loadClass(AbstractBundle.java:1269)
        	at org.apache.struts2.osgi.DefaultBundleAccessor.loadClass(DefaultBundleAccessor.java:109)
        	at org.apache.struts2.osgi.DelegatingObjectFactory.buildBean(DelegatingObjectFactory.java:64)
        	at com.opensymphony.xwork2.ObjectFactory.buildBean(ObjectFactory.java:139)
        	at com.opensymphony.xwork2.ObjectFactory.buildInterceptor(ObjectFactory.java:180)
        	... 31 more
        I am going to try few more things like adding other bundles on which com/opensymphony/xwork2/interceptor/Interceptor could be dependent on.

        Please let me know of any other solution you may have.

        Thanks for your help,
        Shashi

        Comment


        • #5
          Hi,

          I have tried putting the dependencies on which the com/opensymphony/xwork2/interceptor/Interceptor was dependent on but with no success

          Please let me know of any other solution you may have.

          Thanks,
          Shashi

          Comment


          • #6
            I think the easiest way to get to the bottom of this is to d/l the Struts 2 sources and see what code is executed when the exception occurs. You can find information about what class loader is used and potentially change it to one that sees your classes.
            For example if the TCCL is used, then you can adjust it to a correct value, right before your app is started.

            In other news, you can give dmServer a try - it is based on Spring DM and Spring but it handles runtime issues (like the ones you've discovered above).

            Comment


            • #7
              Thanks Costin,

              I am trying to debug the struts2 code. Actually this is the struts2 plugin code which is getting executed when the war bundle is loaded. I have pasted it below.

              Code:
                  public Class<?> loadClass(String className) throws ClassNotFoundException {
                      Bundle bundle = getCurrentBundle(); //Line 1
                      if (bundle != null) {            
                      	Class cls = bundle.loadClass(className); //Line2
                          if (LOG.isTraceEnabled())
                              LOG.trace("Located class [#0] in bundle [#1]", className, bundle.getSymbolicName());
                          return cls;
                      }
              
                      throw new ClassNotFoundException("Unable to find class " + className);
                  }
              At line1 the action bundle is obtained. This is the bundle where application action/interceptor classes are bundled. The bundle obtained is fine which I can see in the debugging session. However when it enters the if condition where at Line2 it tries to load the interceptor/action class (which is dependent the packages in struts and xwork bundles), the exception is thrown. To do further debugging I wrote a test activator class where I try to load a Struts class, however this fails as well.

              Could there be any other reason which would be causing the problem to load struts or xwork classes?

              Further I am going to do further investigation in terms of the classloader related inputs you have provided.

              Please let me know any other input you may have.

              Thanks,
              Shashi

              Comment


              • #8
                Hi,

                I could resolve the NoClassDefFoundError. The problem was with the struts2 and xwork bundles I was deploying in the OSGi container. These bundles were not visible inside any other bundle. So I replaced these bundles from the nighly builds available at apache struts site.

                Now the struts and xwork classes are visible to the classloader. However now I have landed into another problem.

                In my war bundle I have
                1) struts jar
                2) xwork jar
                3) struts-extender jar (This is the modified version of the struts-osgi plugin)

                The struts-extender tries to load the struts related configurations from the other application action bundles deployed in the OSGi container.

                Now the application action bundles are dependent on the struts and xwork BUNDLES deployed in the container. Please note that these are separately deployed bundles and not related to the jars in the web application. Hence the instance of action or interceptor created out of the action bundle is dependent on the xwork/struts bundle classes. Hence the struts/xwork jars contained inside the war bundle throw classcastexcetion saying that the interceptor defined in application action bundle does not implement Interceptor class.

                HTML Code:
                Class [com.arisglobal.aglite.ui.interceptors.ExceptionInterceptor] does not implement com.opensymphony.xwork2.interceptor.Interceptor - interceptor - bundleresource://41/struts.xml:33:74
                	at com.opensymphony.xwork2.ObjectFactory.buildInterceptor(ObjectFactory.java:202)
                	at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:59)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:987)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStack(XmlConfigurationProvider.java:806)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStacks(XmlConfigurationProvider.java:819)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptors(XmlConfigurationProvider.java:842)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:449)
                	at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:264)
                	at org.apache.struts2.osgi.BundlePackageLoader.loadPackages(BundlePackageLoader.java:58)
                	at org.apache.struts2.osgi.OsgiConfigurationProvider.loadConfigFromBundle(OsgiConfigurationProvider.java:133)
                	at org.apache.struts2.osgi.OsgiConfigurationProvider.loadPackages(OsgiConfigurationProvider.java:98)
                	at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:204)
                	at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:55)
                	at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:364)
                	at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:408)
                	at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:190)
                	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
                	at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
                	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
                	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3709)
                	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4363)
                	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
                	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
                	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
                	at org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer.startCatalinaContext(TomcatWarDeployer.java:144)
                	at org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer.startDeployment(TomcatWarDeployer.java:133)
                	at org.springframework.osgi.web.deployer.support.AbstractWarDeployer.deploy(AbstractWarDeployer.java:93)
                	at org.springframework.osgi.web.extender.internal.activator.WarLoaderListener$DeploymentManager$DeployTask.doRun(WarLoaderListener.java:247)
                	at org.springframework.osgi.web.extender.internal.activator.WarLoaderListener$DeploymentManager$BaseTask.run(WarLoaderListener.java:219)
                	at org.springframework.scheduling.timer.DelegatingTimerTask.run(DelegatingTimerTask.java:66)
                	at java.util.TimerThread.mainLoop(Timer.java:512)
                	at java.util.TimerThread.run(Timer.java:462)
                Caused by: java.lang.ClassCastException: com.arisglobal.aglite.ui.interceptors.ExceptionInterceptor
                	at com.opensymphony.xwork2.ObjectFactory.buildInterceptor(ObjectFactory.java:180)
                	... 31 more
                I am out of clues to solve this issue.

                Can you pass any help you may have.

                Thanks in advance,
                Shashi

                Comment


                • #9
                  So if I understand correctly, you have two versions - one outside OSGi and one inside? If it is so, then you can go around it by bootdelegating the classes so that the OSGi platform actually loads the classes from the libraries deployed inside the container.
                  This has some downsides however.
                  There is a blog by yours truly on bootpath delegation which might be helpful, if you're interested in the topic.

                  Comment


                  • #10
                    Hi Costin,

                    Thanks.

                    Yes, I have two versions of the same jars. One set is within the web bundle as normal jars and the other set is deployed as bundles.

                    I am going to go through your blog and would certainly give a try to your solution of bootpath delegation. However I have an initial question here. For loading the struts configuration without problems I think I would need struts and xwork jars within the web bundle. Otherwise I would end in the problem which we are discussing at http://forum.springsource.org/showthread.php?t=68941. IMHO setting these jars as part of the bootpath would still create the Malformed URL issue which I have posted. Please share your opinion.

                    This may sound stupid, but I am not able to use bootdelegation in equinox launcher within eclipse. I have set
                    HTML Code:
                    -Dorg.osgi.framework.bootdelegation=com.opensymphony.*,org.apache.struts2.*
                    in the arguments tab of the equinox run setup. Also the plugin target platform contain both xwork and struts2 bundles. However after removing the struts and xwork jars from the web module I get CNFE for
                    HTML Code:
                    java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.FilterDispatcher
                    	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
                    	at java.security.AccessController.doPrivileged(Native Method)
                    Could you please point me to some tutorial or reference on this?

                    Thanks for your help,
                    Shashi
                    Last edited by shashi; Jun 1st, 2009, 11:40 AM.

                    Comment


                    • #11
                      As I replied in the other thread, loading resources from the stream is different then resolving them. The OSGi platform is always going to use its own URL schema no matter how you try to pack things up - if the library expects just file:// or jar:// then this is not going to work.
                      Regarding the bootpath delegation, I'm sure there are other examples on the internet as well. Try to use various startup combinations and as a simple test, double check what packages are exported by the system bundle.
                      Also, make sure the packages that you export are available on the startup classpath since otherwise the platform does delegate but it cannot find the classes requested.

                      Comment


                      • #12
                        Hi Costin,

                        I am trying to make struts and xwork bundles as boot classpath bundles. I am trying to use the fragment bundle approach for this since the bootclasspath approach didn't work for me. I think this was also discussed in another post at http://forum.springsource.org/showthread.php?t=68479.

                        I have converted the struts and xwork bundle as fragments by adding the header

                        Code:
                        Fragment-Host: system.bundle; extension: framework
                        to the manifests of these bundles. However when I start the OSGi framework within eclipse I see the bundles get into the 'Installed' state and not 'Resolved' state.

                        Also they showed no host bundles when I ran the bundle command.

                        HTML Code:
                        osgi> bundle 83
                        getService[System Bundle [0]]({org.eclipse.osgi.framework.console.CommandProvider}={service.ranking=2147483647, service.id=21})
                        getService[System Bundle [0]]({org.eclipse.osgi.framework.console.CommandProvider}={service.ranking=2147483647, service.pid=0.org.eclipse.core.runtime.internal.adaptor.EclipseCommandProvider, service.vendor=Eclipse.org, service.id=17})
                        initial@reference:file:xwork-core-2.1.4.jar/ [83]
                          Id=83, Status=INSTALLED   Data Root=C:\osgi\.metadata\.plugins\org.eclipse.pde.core\Spring-DM-TP\org.eclipse.osgi\bundles\83\data
                          No registered services.
                          No services in use.
                        getServiceReference(org.osgi.service.packageadmin.PackageAdmin)
                          Exported packages
                            com.opensymphony.xwork2.spring; version="2.1.4"[exported]
                            com.opensymphony.xwork2.conversion.metadata; version="2.1.4"[exported]
                          ....
                          ....
                          ....
                          No imported packages
                        getService[System Bundle [0]]({org.osgi.service.packageadmin.PackageAdmin}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.internal.core.PackageAdminImpl, service.vendor=Eclipse.org, service.id=2})
                          No host bundles
                          No named class spaces
                          No required bundles
                        ungetService[System Bundle [0]]({org.osgi.service.packageadmin.PackageAdmin}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.internal.core.PackageAdminImpl, service.vendor=Eclipse.org, service.id=2})
                        Could you see any problem here?

                        Please let me know your comments.

                        Thanks,
                        Shashi

                        Comment


                        • #13
                          First your fragment declaration is wrong - it should be :
                          Code:
                          Fragment-Host = system.bundle; extension:=framework
                          
                          Second, make sure your fragment bundles do not have imports - as they are installed with the framework, they ideally should work standalone and not depend on any other bundles.
                          I see you're using Equinox - search their documentation on how to enable logging which will indicate why your bundles are not resolved if the above fails.

                          Comment


                          • #14
                            Thanks for correcting the headers Costin,

                            The xwork and struts bundles depend on various other bundles. Does that mean that I cannot deploy these bundles as fragment?

                            Or alternatively can I make the bundles on which these bundles depend on also as fragment bundles?

                            Thanks for your help,
                            Shashi

                            Comment


                            • #15
                              You can try it out and see what you achieve but since fragments are attached to the host bundle, I think it's best to have them be self sufficient - that is, the fragments should not depend on other bundles.
                              Consider the case where the depending bundles get unresolved - in that case the attached fragments get unresolved as well which means the packages exported by the framework cannot be used any more.
                              The less dependencies and the cleaner your setup is, the less side effects you'll have down the road.

                              Comment

                              Working...
                              X