Announcement Announcement Module
Collapse
No announcement yet.
Aspectj Load time weaving support in Dm 2.0 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Aspectj Load time weaving support in Dm 2.0

    I wanted to know if AspectJ Load time time weaving is supported in Dm 2.0 ?

  • #2
    Load time weaving with OSGi is a problem area. When a class is weaved as it's loaded, new dependencies may be introduced which won't be imported in the bundle's manifest. This will lead to ClassNotFoundExceptions at runtime. There is some work being done on load time weaving and OSGi by the Equinox aspects project.

    My recommendation at this time is to avoid the use of load-time weaving and, instead, to use compile-time weaving along with a tool like Bundlor to generate the bundle's manifest after compile-time weaving has taken place. This will ensure that any dependencies that are introduced by the weaving are imported in the bundle's manifest.

    Comment


    • #3
      Thanks Andy. As per your suggestion i will try the other two approaches

      Compile time weaving and spring Aop. I assume these two should work fine and let you know in case of any issues.

      Comment


      • #4
        Is it possible to publish a Service from one bundle and use it in another bundle -- attempting LTW on it -- and publishing it again with a higher rank? StackOverFlowError is encountered when a ServiceInterface call is made on a bean that is weaved!!!

        e.g.
        Code:
        Bundle1
        -------
        	<bean id="helloService" class="com.test.svc.impl.HelloServiceImpl" />
        
        	<osgi:service ref="helloService" interface="com.test.svc.HelloService" ranking="5" />
        
        	<osgi:reference id="helloSvc" interface="com.test.svc.HelloService" cardinality="0..1" timeout="100" />
        	
        	<bean id="testHello" class="com.test.svc.impl.TestHello" init-method="init" destroy-method="destroy">
        		<property name="helloService" ref="helloSvc" />
        	</bean>
        
        
        public class HelloServiceImpl implements HelloService {
        	private static int cnt = 1;
        	
        	public String sayHello() {
        		String msg = "*** HelloServiceImpl...sayHello() called *** cnt=" + (cnt++);
        		System.out.println(msg);
        		return msg;
        	}
        }
        
        public class TestHello {
        	private boolean forever = true;
        	private HelloService helloService;
        	
        	public void setHelloService(HelloService helloService)	{
        		this.helloService = helloService;
        	}
        	
        	public void init()	{
        		new Thread(new Runnable(){
        			public void run()	{
        				while (forever)	{
        					try {
        						System.out.println("*** Calling sayHello()..." + new Date());
        						helloService.sayHello();
        					} catch (ServiceUnavailableException e)	{
        						System.out.println("*** HelloService is unavailable...");
        					}
        					try {
        						Thread.sleep(10000);
        					} catch (InterruptedException ie) {
        						// ignore
        					}
        				}
        			}
        		}).start();
        	}
        	public void destroy()	{
        		forever = false;
        	}
        }
        
        Bundle2 with Aspect
        -------------------
        	<bean id="helloAdvice" class="com.pg.aspect.HelloAdvice" />
        	
        	<context:component-scan base-package="com.pg.aspect" />
        	<context:load-time-weaver aspectj-weaving="on" />
        
        @Aspect
        public class HelloAdvice {
            @Pointcut("execution(* com.test.svc.HelloService.sayHello(..))")
            public void aspectjLoadTimeWeavingHello() {
            }
        
            @Around("aspectjLoadTimeWeavingHello()")
            public Object adviceHello(ProceedingJoinPoint pjp) throws Throwable {
        		System.out.println("*** Inside HelloAdvice called....");
        		try {
        			String ret = (String) pjp.proceed();			
        			System.out.println("*** Inside HelloAdvice done..." + ret);
        			return ret;
        		} catch (Throwable e) {
        			e.printStackTrace();
        		}
        		return "";
            }
        }
        
        As the service in the Bundle2 with Aspect is higher in rank it is expected to replace the Service in TestHello but instead it throws StackOverFlowError when a ServiceInterface (sayHello) is invoked!
        
        *** Calling sayHello()...Tue Dec 08 18:23:24 EST 2009
        Exception in thread "Thread-32" java.lang.StackOverflowError
                at org.springframework.aop.support.IntroductionInfoSupport.isMethodOnIntroducedInterface(IntroductionInfoSupport.java:93)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:102)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
                at $Proxy151.sayHello(Unknown Source)
                at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                at java.lang.reflect.Method.invoke(Method.java:597)
                at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
                at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)
                at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)
                at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)
                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
                at $Proxy151.sayHello(Unknown Source)
                at sun.reflect.GeneratedMethodAccessor63.invoke(Unknown Source)

        Comment


        • #5
          I can see that bundle 1 is both publishing and consuming the HelloService, but I can't see how bundle 2 is accessing this service. Apologies if I've missed something. Can you please let us know how bundle 2 is consuming and then republishing the service.

          Also, it would be useful to see some more of the stacktrace. From the snippet you've posted it's not clear how the overflow is occurring as I can't see any obvious repetition in the stack, e.g. isMethodOnIntroducedInterface is only being called once.

          Comment


          • #6
            oops i missed some of the code snippet in Bundle2 with Aspect - consuming the service and republishing it with higher rank. Also added the errlog.zip attachment with StackOverflowError.

            Code:
            	<osgi:reference id="helloService1" interface="com.test.svc.HelloService" />
            	
            	<osgi:service ref="helloService1" interface="com.test.svc.HelloService" ranking="8" />
            Thanks for quick reply.

            -Harshad.

            Comment


            • #7
              I tried a similar usecase but with small changes

              I tried the following use case

              BundleX - exposes service

              BundleXAspect - accepts the service and weaves aspect around it.

              BundleConsumer - consumes the weaved service (by mentioning the filter with bean name in osgi service)


              This works fine. But the drawback with this approach is that aspect and the consumer are tightly bound. Then I tried to modify my sample on the same lines as you mentioned to use ranking , so that we can use get away with the dependency(filter name). But no luck , I too got the same exception

              Code:
               
              
              Exception in thread "timerFactory" java.lang.StackOverflowError
                      at org.eclipse.osgi.framework.internal.core.BundleContextImpl.getService
              (BundleContextImpl.java:658)
                      at org.springframework.osgi.service.importer.support.internal.support.Se
              rviceWrapper.getService(ServiceWrapper.java:99)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eDynamicInterceptor$ServiceLookUpCallback.doWithRetry(ServiceDynamicInterceptor.
              java:107)
                      at org.springframework.osgi.service.importer.support.internal.support.Re
              tryTemplate.execute(RetryTemplate.java:83)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eDynamicInterceptor.lookupService(ServiceDynamicInterceptor.java:430)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eDynamicInterceptor.getTarget(ServiceDynamicInterceptor.java:415)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eInvoker.invoke(ServiceInvoker.java:62)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.doP
              roceed(DelegatingIntroductionInterceptor.java:131)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.inv
              oke(DelegatingIntroductionInterceptor.java:119)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.osgi.service.importer.support.LocalBundleContextA
              dvice.invoke(LocalBundleContextAdvice.java:59)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.doP
              roceed(DelegatingIntroductionInterceptor.java:131)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.inv
              oke(DelegatingIntroductionInterceptor.java:119)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynami
              cAopProxy.java:202)
                      at $Proxy117.dumy(Unknown Source)
                      at sun.reflect.GeneratedMethodAccessor58.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
              sorImpl.java:25)
                      at java.lang.reflect.Method.invoke(Method.java:597)
                      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflecti
              on(AopUtils.java:307)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eInvoker.doInvoke(ServiceInvoker.java:58)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eInvoker.invoke(ServiceInvoker.java:62)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.doP
              roceed(DelegatingIntroductionInterceptor.java:131)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.inv
              oke(DelegatingIntroductionInterceptor.java:119)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.osgi.service.importer.support.LocalBundleContextA
              dvice.invoke(LocalBundleContextAdvice.java:59)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.doP
              roceed(DelegatingIntroductionInterceptor.java:131)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.inv
              oke(DelegatingIntroductionInterceptor.java:119)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynami
              cAopProxy.java:202)
                      at $Proxy117.dumy(Unknown Source)
                      at sun.reflect.GeneratedMethodAccessor58.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
              sorImpl.java:25)
                      at java.lang.reflect.Method.invoke(Method.java:597)
                      at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflecti
              on(AopUtils.java:307)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eInvoker.doInvoke(ServiceInvoker.java:58)
                      at org.springframework.osgi.service.importer.support.internal.aop.Servic
              eInvoker.invoke(ServiceInvoker.java:62)
                      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
              ReflectiveMethodInvocation.java:172)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.doP
              roceed(DelegatingIntroductionInterceptor.java:131)
                      at org.springframework.aop.support.DelegatingIntroductionInterceptor.inv
              oke(DelegatingIntroductionInterceptor.java:119)

              Comment


              • #8
                Spring DM dynamic proxies

                The problem is that when you are specifying a ranking for a service you are, somewhat, changing the importance of exported services in an OSGi environment.

                Let's consider your sample. In BundleXAspect you are importing one service that is differentiated by interface then you are exporting the proxied service that has the same discriminator - the interface. But, upon re-export you are exporting a service that has a higher discriminator and which will make BundleXAspect to consider this service, as well, as an imported service.

                BundleXAspect will get to use its own exported service and then re-export it. Let's consider a concrete example:
                - service exported by BundleX is S
                - BundleXAspect imports S
                - AOP makes a proxy from S and it generates P1
                - P1 is exported with rank 20 (for example) which is greater than 0 (the default)
                - BundleXAspect re-imports P1 because it has a greater ranking
                - AOP transforms P1 in P2 and it's exported; but BundleXAspect will not use P2 because it already has a "good" service (P1 - the same rank as P2)
                - when the exported service (P2) is called by BundleConsumer, P2 will call P1 because this is the proxied target. P1 is, in fact, a Spring DM proxy to a service from service registry and because it's a dynamic one, when called, will invoke the best service available at the moment in the registry which is P2. And now the cycle begins.

                Comment


                • #9
                  Thanks Andrie. Beautiful Explanation :-)

                  So how can i get my use case working ?

                  My use case : Adding aspect bundle during runtime and changing the behaviour of the service ? [without impacting service provider and service consumer ]

                  Comment


                  • #10
                    How about always weaving your service with an aspect that looks for a particular kind of service in the service registry and, if it finds one, it calls the appropriate method(s) on the service? Basically you'd move all of the actual logic out of your aspect and into this service and the aspect would simply delegate to it.

                    Comment


                    • #11
                      Andy, I could not completely get you solution, but my requirement is my service exporter and importer bundles should be totally unaware of the aspect logic.


                      What version on dynamic modules does spring dm use ?

                      I see an attricute sticky is <osgi:ref> - which the reference says is - will stick to the first version on the obtained service. Is it supported in Dm 2.0M6

                      I think this can solve my issue. In my BundleXAspect(bundle containing the aspect) i will give sticky=true . It avoid my cycle and my application should work fine.

                      Comment


                      • #12
                        i get the following error when adding sticky attribute


                        Code:
                        aused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'sticky' of bean class [org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean]: Bean property 'sticky' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
                        	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:877)
                        	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:722)
                        	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
                        	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:60)
                        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1332)
                        	... 21 common frames omitted

                        Comment


                        • #13
                          Originally posted by sudheerk84 View Post
                          i get the following error when adding sticky attribute


                          Code:
                          aused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'sticky' of bean class [org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean]: Bean property 'sticky' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
                          	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:877)
                          	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:722)
                          	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
                          	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:60)
                          	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1332)
                          	... 21 common frames omitted
                          The sticky attribute has been added in Spring DM 2.x. dm Server 1.x uses Spring DM 1.x.

                          Comment


                          • #14
                            HI Andrei,

                            I tried my sample pasted above with DM server 2.0 M6.


                            But i am not sure what version of Dynamic modules does Spring DM 2.0M6 use.

                            Comment


                            • #15
                              did you figure this out? I get this same exception while trying to reference a service myself. I am using dm server 2 release.

                              thanks,
                              craig

                              Comment

                              Working...
                              X