I wanted to know if AspectJ Load time time weaving is supported in Dm 2.0 ?
I wanted to know if AspectJ Load time time weaving is supported in Dm 2.0 ?
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.
Andy Wilkinson
SpringSource
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.
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)
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.
Andy Wilkinson
SpringSource
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.
Thanks for quick reply.Code:<osgi:reference id="helloService1" interface="com.test.svc.HelloService" /> <osgi:service ref="helloService1" interface="com.test.svc.HelloService" ranking="8" />
-Harshad.
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)
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.
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 ]
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.
Andy Wilkinson
SpringSource