Announcement Announcement Module
Collapse
No announcement yet.
Autowiring not working inside aspect Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Autowiring not working inside aspect

    Hello there! I'm working on a simple demo to use Spring and AOP to make HATEOAS on rest services simpler, but I'm having some issues with aspect and autowiring.

    This is driving me crazy for the past hours. I've searched around but can't find a reason why my dependencies are not being wired to my aspects.

    The EtagService is null on the aspect. Spring does not inject the service. The service is created by Spring as I can see on the logs the bean creation, and It gets injected in another place with no problems.

    Here's the aspect and the config that starts the app.

    I tried to add the aspect package to the component scan, tried to add @configurable to it, nothing seems to work.

    I really would love some help here.

    Regards

    Code:
    @Configuration
    @ComponentScan(basePackages={"com.fb.restbucks.services","com.fb.restbucks.aspects"},excludeFilters={@Filter(Configuration.class)})
    @EnableAspectJAutoProxy(proxyTargetClass=true)
    public class AppConfig {
    	
    }
    
    
    
    @Configurable
    @Aspect
    public class ResponseEnhancerAspect {
    
    	
    	@Autowired
    	private ETagService eTagService;
    	
    	
    	
    	@Around("execution(public ResponseEntity com.fb.restbucks.controllers.*.*(..))  && @annotation(javax.ws.rs.GET)")
    	public Object addEtag(ProceedingJoinPoint pjp) throws Throwable {
    		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    		Object retVal = pjp.proceed();
    		ResponseEntity entity = (ResponseEntity)retVal;
    		HttpHeaders headers = new HttpHeaders();
    		String url = ServletUriComponentsBuilder.fromRequest(request).build().toString();
    		String tag = null;
    		try{
    			tag = eTagService.get(url);
    		}catch (InvalidTagException e) {
    			tag = eTagService.generate(url, entity.getBody());
    		}
    		headers.add("Etag", tag);
    		return new ResponseEntity(entity.getBody(),headers,entity.getStatusCode());
    	}
    	
    }

  • #2
    Just an update on this. I've noticed that I had AspectJ project enabled on my project, it really helps checking the weaving points and etc.
    I've removed this from the project and now, I get errors when deploying the app.

    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appConfig': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: javax$ws$rs$POST
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:526)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:381)
    	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
    	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4765)
    	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5260)
    	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1525)
    	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1515)
    	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    	at java.lang.Thread.run(Thread.java:619)
    Caused by: java.lang.IllegalArgumentException: error Type referred to is not an annotation type: javax$ws$rs$POST
    	at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:301)
    	at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:207)
    	at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:193)
    	at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:182)
    	at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:163)
    	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:209)
    	at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:263)
    	at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:295)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
    	at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
    	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
    	at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:406)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1450)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:518)
    	... 21 more
    What I really don't understand is why it was at least being deployed before, and now I get this error. Also, before I only had the return type as the class name ResponseEntity, after removing the aspecj feature, I had to introduce the FQN of the class.

    Weird, really weird :P

    Comment


    • #3
      Ok the last one was a mistake, the jsr311.jar was not present inside the war.
      But after fixing that, now the odd thing is that the aspect is never invoked.
      First it was invoked but no dependency injected, now it's created (I can see on log that the aspect gets the EtagService injected) but when invoking the method the aspect does not kicks in.

      Hope someone answers this thread...

      Comment


      • #4
        Wow! Finally cracked this one.
        My Aspect was being declared on the first context loader (I'm using a xml free loading with servlet 3.0). So I moved it to the dispatcher servlet loader and it works.

        Kinda weird as I was expecting the appcontext to merge the configurations.

        But at least this is working now

        Comment


        • #5
          How did you do "So I moved it to the dispatcher servlet loader and it works." exactly ?

          Comment


          • #6
            I guess I missed that config. Here's my full config, and I think you'll understand.
            I'm using WebApplicationInitializer inside a servlet 3.0 engine. So as you can see I have 2 main configuration classes: AppConfig and DispatcherConfig.

            The @EnableAspect was declared inside the AppConfig, I've moved it to the DispatcherConfig, and now it's working like a charm

            Code:
            public class AppInitializer implements WebApplicationInitializer {
            
            	public void onStartup(ServletContext container)
            			throws ServletException {
            		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            		rootContext.register(AppConfig.class);
            
            		// Manage the lifecycle of the root application context
            		container.addListener(new ContextLoaderListener(rootContext));
            
            		// Create the dispatcher servlet's Spring application context
            		AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
            		dispatcherContext.register(DispatcherConfig.class);
            
            		// Register and map the dispatcher servlet
            		ServletRegistration.Dynamic dispatcher = container.addServlet(
            				"dispatcher", new DispatcherServlet(dispatcherContext));
            		dispatcher.setLoadOnStartup(1);
            		dispatcher.addMapping("/");
            
            	}
            
            }
            
            @Configuration
            @ComponentScan(basePackages={"com.fb.restbucks.services","com.fb.restbucks.aspects"},excludeFilters={@Filter(Configuration.class)})
            @EnableAspectJAutoProxy(proxyTargetClass=true)
            public class AppConfig {
            	public @Bean
            	MongoDbFactory mongoDbFactory() throws Exception {
            		return new SimpleMongoDbFactory(new Mongo(), "restbucks");
            	}
            
            	public @Bean
            	MongoTemplate mongoTemplate() throws Exception {
            		MongoTemplate template = new MongoTemplate(mongoDbFactory());
            		template.setWriteConcern(WriteConcern.SAFE);
            		return template;
            	}
            
            }
            @Configuration
            @EnableWebMvc
            @ComponentScan(basePackages={"com.fb.restbucks.controllers"},excludeFilters={@Filter(Configuration.class)})
            @EnableAspectJAutoProxy(proxyTargetClass=true)
            public class DispatcherConfig extends WebMvcConfigurerAdapter {
            
            	@Override
            	public void configureMessageConverters(
            			List<HttpMessageConverter<?>> converters) {
            		MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
            		List<MediaType> mediatypes = new ArrayList<MediaType>();
            		mediatypes.add(MediaType.APPLICATION_JSON);
            		converter.setSupportedMediaTypes(mediatypes);
            		converters.add(converter);
            	}
            
            	
            	@Bean
            	public DefaultAnnotationHandlerMapping handlerMapping(){
            		return new DefaultAnnotationHandlerMapping();
            	}
            }

            Comment


            • #7
              Still your aspect will work only on dispatcherContext but not rootContext, in my case I have one aspect for logging and 2 config context as you mentioned but when put @EnableAspectJAutoProxy in app context the auto wiring for services and rpos are going to fail, and I want to log them too.

              the work around is to move the config of services and repos to dispatcherContext but this is not the correct place for them.

              Comment

              Working...
              X