Results 1 to 7 of 7

Thread: Autowiring not working inside aspect

  1. #1

    Default 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. #2

    Default

    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

  3. #3

    Default

    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...

  4. #4

    Default

    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

  5. #5
    Join Date
    Dec 2011
    Posts
    3

    Default

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

  6. #6

    Default

    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();
    	}
    }

  7. #7

    Default

    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •