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
Aspectj Weaving JPA- In Standalone Equinox Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Aspectj Weaving JPA- In Standalone Equinox

    I'm trying to deploy a bundle using AspectJ Weaving with JPA in a standalone Equinox instance. But I can't seem to activate the weaver, I've tried various approaches but each time I get the following error:
    Code:
    17:23:26.329 [SpringOsgiExtenderThread-5] ERROR o.s.o.c.s.OsgiBundleXmlApplicationContext - Pre refresh error
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.weaving.AspectJWeavingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [org.springframework.osgi.util.BundleDelegatingClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:478)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:881)
    	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:534)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:54)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:227)
    	at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:195)
    	at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:228)
    	at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:179)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:137)
    	at org.springframework.osgi.extender.internal.activator.ContextLoaderListener$2.run(ContextLoaderListener.java:741)
    	at java.lang.Thread.run(Thread.java:595)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [org.springframework.osgi.util.BundleDelegatingClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:478)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
    The bundle's descriptor is using <context:load-time-weaver aspectj-weaving="on"/> and as suggested, I've tried adding the -javaagent:spring-agent.jar when I start-up Equinox, here are a few attempts that have failed:
    Code:
    java -javaagent:spring-agent.jar -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar  -console
    
    java -Xbootclasspath/a:aspectjweaver.jar -javaagent:spring-agent.jar -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar  -console
    
    java -javaagent:org.springframework.instrument-2.5.4.A.jar -jar org.eclipse.osgi_3.5.0.v20080804-1730.jar  -console
    
    java -Xbootclasspath/a:aspectjrt.jar,pectjweaver.jar,spring-agent.jar -javaagent:spring-agent.jar -jar org.eclipse.gi_3.5.0.v20080804-1730.jar  -console
    Anyone else had a similar experience loading a bundle using aspectj ?
    Do I need to add Spring-DM or some other library in order for the spring-agent.jar to be detected ?

  • #2
    You can try to add -Dosgi.parentClassloader=app to the jvm parameter.

    This is probably a problem with the visibility of the javaagent in the different bundle classloaders. I haven't figured out yet how you can propagate the
    javaagent to the other bundles.

    efh

    Comment


    • #3
      Hi,

      I'm facing exactly with the same error and Google only returned this post as a reference.
      Have you managed to fix it ?

      Comment


      • #4
        Originally posted by Nico View Post
        Hi,

        I'm facing exactly with the same error and Google only returned this post as a reference.
        Have you managed to fix it ?
        Hmm I've spent very little time on this problem but it seems to me that javaagent approach will not work in equinox apps.

        There is the equinox aspects project that enables LTW in equinox environment but it has problems.

        I have traced issue to the org.springframework.instrument.classloading.Instru mentationLoadTimeWeaver and I guess that spring LTW could be integrated with equinox aspects if someone writes correct LoadTimeWeaver (in my case everything blows somewhere in addTransformer method).

        I guess that it has something to do with https://bugs.eclipse.org/bugs/show_bug.cgi?id=248047
        Last edited by iloncar; Apr 14th, 2009, 07:02 PM.

        Comment


        • #5
          The link to the bugzilla entry of Equinox Aspects is absolutely correct. I briefly looked at this and think it is possible to implement a small bridge between Equinox Aspects and the LoadTimeWeaver infrastructure of Spring, but I haven't found the time to actually implement it.

          If anybody out there would like to volunteer, I would be happy to assist and provide some guidance through Equinox Aspects, otherwise I will look at this in more depth within the next weeks and post my results.

          Comment


          • #6
            Does anybody have a small example project to reproduce the problem? That would be highly appreciated - and would speed up solving this issue... :-)

            Feel free to send me a zipped project for my workspace via email ([email protected]).

            Comment


            • #7
              Originally posted by mlippert View Post
              Does anybody have a small example project to reproduce the problem? That would be highly appreciated - and would speed up solving this issue... :-)

              Feel free to send me a zipped project for my workspace via email ([email protected]).
              Hi Martin! Thank you very much for your work on equinox aspects. It helped us a lot. I don't know how would we manage those change listeners if there were no aspects.

              I will try to assemble an example during the weekend.

              Comment


              • #8
                Copy of the email sent to mlippert:
                Hi Martin,

                As you requested on this forum thread, I send you an eclipse project to reproduce the problem. To run it, I used the standard equinox platform package, with Eclipse Link 1.1 bundles installed. I've also installed the project dependencies from pom.xml using the command: mvn -e eclipse:install-plugins -DeclipseDir=/path/to/equinox/
                Then I used this platform in eclipe as the target platform for the project and created a run configuration.
                When I run this platform, I can reproduce the error stack described on the thread. Note that to be able to run, this project has a reference to a SQL datasource defined in osgi-context.xml. You will add to provide another bundle which exports such a service.
                Hope this help. Let me know I you have problems using this sample project.

                Regards,

                Nicolas.

                Comment


                • #9
                  Thank you guys for the examples. I made some progress on this. Let me explain what the current status is.

                  I implemented an EquinoxAspectsLoadTimeWeaver that can be used instead of InstrumentingLoadTimeWeaver or similar things from Spring as the load-time weaver for a specific bundle. This EquinoxAspectsLoadTimeWeaver uses the Equinox Aspects infrastructure to modify bytecode at load-time. This works pretty fine. I tested this with the @Configurable stuff from spring-aspects and it works. Since it implements the LoadTimeWeaver interface of Spring, I hope that all the other things that uses this load-time weaving integration of Spring (JPA weaving etc.) will work as well. Haven't tested all the other use-cases at the moment.

                  Nevertheless (especially for the AspectJ weaver) there are some issues with this solution:

                  1. You need to start the bundle that uses this load-time weaver before any other bundle accesses it (via config.ini, p2, startlevel, whatever). Using the Lazy-Start works only partially. The problem with Lazy-Activation is that it activates the bundle when the first class is loaded. As a reaction to this Spring loads and initializes the spring context for this bundle, which then initializes the load-time weaver for this bundle (as defined in the context definition). That means also, that the first class is loaded and AFTER that the context is initialized. Therefore the first class that gets loaded is not woven. If this is your view, for example, that got loaded because of the extension being created, your view class is not woven (when its the first class from that bundle).
                  This is a problem at the moment and I have no clue how to solve this in a generic way. You can workaround this by starting those bundles manually or automatically, NOT using Lazy-Activation.

                  2. The second problem is the spring-aspects bundle. The AspectJ weaver of spring configures itself by loading the aop.xml files from the classpath. The spring-aspects bundle does not export the aop.xml file. Therefore its not accessible to other bundles via normal classloader resource loading. You can fix this by adding "META-INF" to the list of exported packages in the MANIFEST.MF of the spring-aspects bundle, but you need to modify that bundle.

                  So far the details about my investigations at the moment... Let me know if you would like to try that out! I am happy to get feedback on this.

                  Comment


                  • #10
                    Originally posted by mlippert View Post
                    Thank you guys for the examples. I made some progress on this. Let me explain what the current status is.
                    Great news Martin!

                    Nevertheless (especially for the AspectJ weaver) there are some issues with this solution:

                    1. You need to start the bundle that uses this load-time weaver before any other bundle accesses it (via config.ini, p2, startlevel, whatever). Using the Lazy-Start works only partially. The problem with Lazy-Activation is that it activates the bundle when the first class is loaded. As a reaction to this Spring loads and initializes the spring context for this bundle, which then initializes the load-time weaver for this bundle (as defined in the context definition). That means also, that the first class is loaded and AFTER that the context is initialized. Therefore the first class that gets loaded is not woven. If this is your view, for example, that got loaded because of the extension being created, your view class is not woven (when its the first class from that bundle).
                    This is a problem at the moment and I have no clue how to solve this in a generic way. You can workaround this by starting those bundles manually or automatically, NOT using Lazy-Activation.

                    Is it possible to implement equinox hook (extender) to force context initialization of spring enabled budle before first class is loaded?

                    2. The second problem is the spring-aspects bundle. The AspectJ weaver of spring configures itself by loading the aop.xml files from the classpath. The spring-aspects bundle does not export the aop.xml file. Therefore its not accessible to other bundles via normal classloader resource loading. You can fix this by adding "META-INF" to the list of exported packages in the MANIFEST.MF of the spring-aspects bundle, but you need to modify that bundle.

                    So far the details about my investigations at the moment... Let me know if you would like to try that out! I am happy to get feedback on this.

                    I would really like to try this. Can you post the code?

                    Should we open JIRA issue to make aop.xml pubicly exposed?

                    Comment


                    • #11
                      Here are my first sketches for the bundle. You can use it together with Equinox Aspects. Just start the org.eclipse.equinox.weaving.springweaver bundle instead of the org.eclipse.equinox.weaving.aspectj bundle by default at startup (and set the other options you need to run EA).

                      Basically you need to have Equinox Aspects installed into the same place as the org.eclipse.osgi bundle, set the system option -Dosgi.framework.extensions=org.eclipse.equinox.wea ving.hook. That should do it.

                      To get more output you should also set -Dorg.aspectj.osgi.verbose=true.

                      Comment


                      • #12
                        I've raised:

                        http://jira.springframework.org/browse/SPR-5692

                        to look at moving the aop.xml or exporting the META-INF.

                        It looks like the best option is moving it to org/aspectj and exporting that folder.

                        However, equinox aspects will then not be able to find it (ironically) and so we will need to also modify the manifest for the bundle to include the brand new Equinox Aspects headers that allow the definition of aspects in the manifest (and avoid any need for aop.xml access)

                        Comment


                        • #13
                          Originally posted by clemas View Post
                          I've raised:

                          It looks like the best option is moving it to org/aspectj and exporting that folder.

                          However, equinox aspects will then not be able to find it (ironically) and so we will need to also modify the manifest for the bundle to include the brand new Equinox Aspects headers that allow the definition of aspects in the manifest (and avoid any need for aop.xml access)
                          I think that the best solution is to do both. Leave aop.xml where it is and use new manifest.mf headers to export aspects.

                          Correct me if I'm wrong, but spring-aspects doesn't contain org.aspectj package so how could it be exported? Besides it would probably be a split package and I'm afraid that PDE could not deal with it.

                          Comment


                          • #14
                            Leaving it where it is and using the new headers will only allow Equinox Aspects to find the aspect definitions (since they are now visible to it in the manifest) - the AspectJ weaver will still not be able to discover the definitions as it doesn't go looking in the manifest. And Martins bit of magic still uses the AspectJ weaver and not EA to load the aspect definitions.

                            Exposing aop.xml by exporting META-INF is a risk given that the '-' makes it an illegal Export declaration - although it is tolerated by equinox (and dm Server) without throwing an error, and some bundles choose to export their resources like that. (you might consider this a split package problem too as multiple bundles can export META-INF)

                            I did not rush into making the change for Spring Framework 3.0 M3 because there are pros and cons with the possible solutions for exposing aop.xml.

                            Andy

                            Comment


                            • #15
                              Hello Martin,

                              Thanks very much for your adapter of Equinox Aspects for Spring. It really works fine for me within an example using Spring JPA support and EclipseLink.

                              However, I wonder if the -Dosgi.framework.extensions=org.eclipse.equinox.wea ving.hook property is mandatory since it works without it with Equinox 3.5. In some cases (for example, within a Spring DM integration test case), I have some strange exceptions:

                              Code:
                              882  [main] ERROR com.manning.sdmia.dataaccess.service.test.LibraryServiceTest  - cannot start bundle [WeavingService Plug-in (Incubation) (org.eclipse.equinox.weaving.aspectj)|file: (...)/org.eclipse.equinox.weaving.aspectj_1.0.0.200905031323.jar]
                              	org.osgi.framework.BundleException: Exception in org.eclipse.equinox.weaving.aspectj.WeavingServicePlugin.start() of bundle org.eclipse.equinox.weaving.aspectj.
                              	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:805)
                              	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:754)
                              	(...)
                              
                              Caused by: java.lang.NoClassDefFoundError: org/eclipse/equinox/service/weaving/IWeavingServiceFactory
                              	at org.eclipse.equinox.weaving.aspectj.WeavingServicePlugin.start(WeavingServicePlugin.java:78)
                              	at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:782)
                              	at java.security.AccessController.doPrivileged(Native Method)
                              	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:773)
                              	... 27 more
                              
                              Caused by: java.lang.ClassNotFoundException: org.eclipse.equinox.service.weaving.IWeavingServiceFactory
                              	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:443)
                              	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:405)
                              	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:393)
                              	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:105)
                              Any ideas about this error?
                              Thanks very much by advance for your help,
                              Thierry

                              Comment

                              Working...
                              X