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
Is it normal for AspectJ to post-process OSGi references? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Is it normal for AspectJ to post-process OSGi references?

    I'm running into an issue where I'm using an application context which has an <aop:config> definition and <osgi:reference> beans. It appears that the AOP advice is attempting to be applied to the service reference. While I don't fundamentally have a problem with this, in my particular case it's throwing a reflection-related exception, presumably because of the separate class loaders in OSGi:

    Code:
    Caused by: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine annotations of missing type $Proxy181
     [Xlint:cantFindType]
    	at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:129)
    	at org.aspectj.weaver.Lint$Kind.signal(Lint.java:316)
    	at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.raiseCantFindType(MissingResolvedTypeWithKnownSignature.java:223)
    	at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.hasAnnotation(MissingResolvedTypeWithKnownSignature.java:174)
    	at org.aspectj.weaver.patterns.ExactAnnotationTypePattern.fastMatches(ExactAnnotationTypePattern.java:84)
    	at org.aspectj.weaver.patterns.WithinAnnotationPointcut.fastMatch(WithinAnnotationPointcut.java:80)
    	at org.aspectj.weaver.internal.tools.PointcutExpressionImpl.couldMatchJoinPointsInType(PointcutExpressionImpl.java:78)
    	at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:235)
    	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:195)
    	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:250)
    	at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:284)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:113)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:85)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:66)
    	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
    	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:325)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:361)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1429)
    	at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:139)
    My aop definition looks like:
    Code:
    	<aop:config>
    		<aop:pointcut id="daoOperation"
    			expression="@within(org.springframework.stereotype.Repository)" />
    		<aop:advisor pointcut-ref="daoOperation"
    			advice-ref="daoMonitoringAdvice" />
    	</aop:config>
    Is there a way to inform Spring that I don't want the service reference post-processed? I would be okay with that, too.

    For the record, I'm using Spring 2.5.6.SEC01 and Spring DM 1.2.1.

    Thanks for the help!
    Jonathan
    Last edited by fiddlerpianist; Dec 31st, 2009, 11:22 AM. Reason: added version information

  • #2
    I changed the @Within annotation above to a normal within(org.sample..*) and the problem goes away. However, now I've noticed something else. It seems that any application context with a component scan in it will attempt to post-process OSGi references as well.

    I have an integration bundle which publishes a DAO as an OSGi service (com.example.integration.dao.AccountDao). The implementation class (com.example.integration.daoimpl.jdbc.AccountDaoJd bcImpl) is private within the bundle. I also have a web bundle (in dm server) which imports com.example.integration.dao but not the implementation package (nor should it; it should only care about the interface for the OSGi service). However, the application context attempting to post-process this bean uses reflection on the service object in an attempt to get its metadata (annotations and the like, I'm assuming). So this leads to a ClassNotFoundException within the loading application context:

    Code:
    Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.example.integration.daoimpl.jdbc.AccountDaoJdbcImpl] for bean with name 'accountDao' defined in file [C:\opensource\springsource-dm-server-2.0.0.RC1\work\osgi\configuration\org.eclipse.osgi\bundles\38\data\store\org.eclipse.osgi\bundles\93\1\bundlefile\com\example\integration\daoimpl\jdbc\AccountDaoJdbcImpl.class]; nested exception is java.lang.ClassNotFoundException: com.example.integration.daoimpl.jdbc.AccountDaoJdbcImpl
    	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1141)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:524)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1177)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:222)
    	at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:187)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:652)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:610)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:499)
    	... 34 common frames omitted
    Caused by: java.lang.ClassNotFoundException: com.example.integration.daoimpl.jdbc.AccountDaoJdbcImpl
    	at com.springsource.osgi.webcontainer.tomcat.internal.loading.BundleWebappClassLoader.loadClass(BundleWebappClassLoader.java:273)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    	at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)
    	at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:385)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1138)
    	... 41 common frames omitted
    It would be really handy to turn off this type of post-processing on the OSGi references.

    Comment


    • #3
      All beans/definitions defined inside an application context are subject to processing - if you want to exclude certain beans, then it's the post processor that needs to do the skipping.
      An alternative to your solution would be to use a name/package-based rule to exclude the bean from being processed (there is support for this inside the component-scan) since the class is then ignored altogether and no loading is performed.

      Since you're using dmServer there might be other solutions at hand but for that I recommend the dmServer forum (if you'd like I can move the thread over).

      Cheers,

      Comment


      • #4
        Hi Costin,

        Thanks for the reply. I realized that I was a bit boneheaded and had my web classes in com.example (it had to do with the way the Spring Template project generated the package in STS). So I moved them down to com.example.web.osgidemo and it works now.

        I'm still a bit concerned, however, about the @within syntax. While I was able to get "normal" within syntax working (i.e. within(com.example.integration.daoimpl..*Dao*Impl) ), I couldn't help but feel that this was a bit of a kludge, especially considering @within(org.springframework.stereotype.Repository) was the best expression and did not rely on a naming convention. I tried limiting it to the base integration package (within(com.example.integration.daoimpl..*) and @within(org.springframework.stereotype.Repository) ) in the hopes that the second part of the expression wouldn't be evaluated by AspectJ, but unfortunately it appears that AspectJ does not do this.

        It seems that @within has no chance of working in an OSGi environment. Or am I missing something?

        Thanks for your help,
        Jonathan

        Comment


        • #5
          Class processing (including annotation discovery) can pull in a lot of dependencies which can conflict with the OSGi boundaries. One thing to remember is that when doing annotation scanning, discovery both the classes importing and processing the annotation need to import since otherwise the annotation is considered as not found and thus it will simply be skipped.
          If you're application does import @within then consider turning on debug level on both AspectJ and the OSGi platform to see what class loading occurs.

          Comment

          Working...
          X