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
OSGi Reference & Spring AOP Aspect Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OSGi Reference & Spring AOP Aspect

    Hi,

    I would like to advise an OSGi reference using an aspect with Spring AOP as the AOP implementation.

    The OSGi reference which has an annotated method to be advised
    Code:
    	<osgi:reference id="mockInitializer" bean-name="mockInitializer">
    		<osgi:interfaces>
    			<value>edu.utah.further.ds.api.service.query.SearchQueryInitializer</value>
    			<value>edu.utah.further.core.api.chain.RequestProcessor</value>
    		</osgi:interfaces>
    	</osgi:reference>
    By this aspect

    Code:
    	@SuppressWarnings("unused")
    	@Pointcut("@annotation(edu.utah.further.ds.api.annotation.QueryProcessor) "
    			+ " && args(chainRequest) && this(requestProcessor)")
    	private void annotatedMethod(final ChainRequest chainRequest,
    			final RequestProcessor requestProcessor)
    	{}
    
    	@SuppressWarnings("boxing")
    	@Around("annotatedMethod(chainRequest, requestProcessor)")
    	public Object aroundAdvice(final ProceedingJoinPoint pjp,
    			final ChainRequest chainRequest, final RequestProcessor requestProcessor)
    and the annotation used to mark the methods

    Code:
    @Target(METHOD)
    @Retention(RUNTIME)
    @Inherited
    public @interface QueryProcessor
    I'm not having much luck, I never see AspectJAwareAdvisorAutoproxyCreator creating a proxy to advise the given reference. Is what I want to do even possible?

    It's unclear to me when AspectJAwareAdvisorAutoproxyCreator runs in order to create the proxies...I'd imagine it's during an initialization phase but I'm not sure?

    It's also unclear if the annotation is even visible inside the proxied OSGi service?

    Thus far the only idea I have is to make the service included in the bundle classpath where the aspect lives and export the services there so that they are advised before being exported.

    Can anyone help?

    Thanks

  • #2
    After changing the aspect to look at a method instead of the annotation, I was able to get AspectJAutoProxyCreator to run.

    To answer some of my questions, it looks like AspectJAutoProxyCreator gets invoked after the bean is created (bean post processing)

    So the OSGi reference is obtained and then AspectJAutoProxyCreator runs to create the proxy for AOP.

    I'm running into a problem though. It seems that the OSGi references use JDK Dynamic Proxies and as I understand these are final. When CGLIB2 tries to subclass the proxy (the OSGi reference) it blows up.

    Code:
    Could not generate CGLIB subclass of class [class $Proxy420]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class $Proxy420
    So...is it possible to get OSGi references as CGLIB2 proxies? I don't know if these are final or not but if they weren't then it'd work.

    Comment


    • #3
      I found my own solution for this.

      In my api module I create a new wrapper class called AdvisableDelegatingQueryProcessor which implements the same interface of the service I want to advise but is annotated with the annotation I look for in the pointcut. As you can guess by the name, this class simply wraps and delegates.

      Code:
      public class AdvisableDelegatingQueryProcessor implements RequestProcessor
      Code:
      /**
       * @param requestProcessor
       */
      public AdvisableDelegatingQueryProcessor(final RequestProcessor requestProcessor)
      {
      	this.requestProcessor = requestProcessor;
      }
      
      @Override
      @QueryProcessor
      public boolean process(final ChainRequest request)
      {
      	return requestProcessor.process(request);
      }
      Likewise, I moved my Aspect to my api module and decoupled the Advice from the advice class. Note the addition of the + in the pointcut in order to recognize subclasses.

      Code:
      /**
       * The around advice to execute
       */
      private QpAroundAdvice aroundAdvice;
      
      @SuppressWarnings("unused")
      @Pointcut("@annotation(edu.utah.further.ds.api.annotation.QueryProcessor)"
      		+ " && args(chainRequest) && this(requestProcessor+)")
      private void annotatedMethod(final ChainRequest chainRequest,
      		final RequestProcessor requestProcessor)
      {
      
      }
      
      @Around("annotatedMethod(chainRequest, requestProcessor)")
      public Object aroundAdvice(final ProceedingJoinPoint pjp,
      		final ChainRequest chainRequest, final RequestProcessor requestProcessor)
      {
      	return aroundAdvice.doAround(pjp, chainRequest, requestProcessor);
      }
      I then obtain an OSGi reference to my service and wrap it

      Code:
      <osgi:reference id="mockInitializer" bean-name="mockInitializer">
      	<osgi:interfaces>
      		<value>edu.utah.further.ds.api.service.query.SearchQueryInitializer</value>
      		<value>edu.utah.further.core.api.chain.RequestProcessor</value>
      	</osgi:interfaces>
      </osgi:reference>
      
      <bean id="wrappedInitializer"
      	class="edu.utah.further.ds.api.service.query.AdvisableDelegatingQueryProcessor"
      	p:requestProcessor-ref="mockInitializer" />
      this then allows AnnotationAwareAspectJAutoProxyCreator to create a proxy around the method instead of trying to create a proxy for an already final proxy generated from the OSGi service reference.

      Comment

      Working...
      X