I have an aspect which creates by load-time weaving mechanism. But I need to inject my service in it, so it aspect must be created by spring.
My aspect looks like this :
#Aspect
public class SomeAspect {
#Inject
private SomeService someService;
#Before("some_pointcut_here")
public void doInterception() {
//...call service here
}
}
I can do it with xml:
<bean id="myAspect" class="foo.bar.SomeAspect" factory-method="aspectOf" />
So the question is how to achieve the same with spring java config. Any suggestions will be appreciated. Thanks
Edit
I annotate my aspect with #Component and it works. It strange for me because in case of xml config dependency injection doesn't worked in my case, but it works for java configuration
#Bean
public SomeAspect someAspect() {
return org.aspectj.lang.Aspects.aspectOf(SomeAspect.class);
}
ISSUE:
I am trying to inject a service into a bean but the service instance is always null.
BACKGROUND:
I have two beans one called from the other. This is how they are defined in XML config:
<context:annotation-config />
<bean class="com.test.MyBeanImpl" name="myBean"/>
<bean id="myService" class="com.test.MyServiceImpl" />
and the beans are implemented like so:
MyServiceImpl.java
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Resource(name="myBean")
private MyService myService;
public MyBeanImpl() {}
}
QUESTIONS:
Is there some reason related to the fact that my bean implements 3 interfaces that is preventing the Service being injected? If not what other factors could be effecting it?
as you are using annotations Just mark your service class with #Service annotation and use #Autowired annotation to get the instance of your service class
MyServiceImpl.java
package com.mypackage.service;
#Service
class MyServiceImpl implements MyService {
public void getString() {
return "Hello World";
}
}
MyBeanImpl.java
#Component
class MyBeanImpl implements MyBean, SomeOtherBean1, SomeOtherBean2 {
#Autowired
private MyService myService;
public MyBeanImpl() {}
}
also make sure you mention your package name in <context:component-scan /> element in your dispatcher file as
<context:annotation-config />
<context:component-scan base-package="com.mypackage" />
hope this will solve your problem
Make sure the bean you are injecting MyService into is a bean.
/* This must be a bean, either use #Component or place in configuration file */
#Component
public class SomeClass{
#Resource
private MyService myService;
}
Also make sure that within your configuration you have specified that the application uses annotation-based configuration using:
<context:annotation-config/>
Since your using multiple interfaces it may be best to qualify the bean with a name:
<bean class="com.test.MyBeanImpl" name="myBean" />
Then specify the name element on the #Resource annotation
#Resource(name="myBean")
private MyService myService;
Here is a Github Gist that explains these concepts.
I am trying to autowire a class into a WebSocketServlet in the following way:
#Configurable(autowire=Autowire.BY_TYPE)
public class MyServlet extends WebSocketServlet {
#Autowired
public MyClass field;
// etc...
}
Here's what my configuration looks like:
<context:annotation-config />
<context:component-scan base-package="org.*" />
<bean id="config" class="org.*.MyClass">
<!-- a bunch of properties -->
</bean>
Note that autowire used to work just fine as long as I was in a Spring #Controller. I had to step out of that because i don't know how to map a WebSocketsServlet to a method of the #Controller as you do with regular servlets.
Any idea what I might be missing?
In order to use #Configurable, you need to have these line in tour context:
<context:load-time-weaver aspectj-weaving="true"/>
<context:spring-configured/>
<context:annotation-config />
<context:component-scan base-package="org.*" />
In addition, I think you must reference spring-aspect in the Import-Library section of your Manifest.
I didn't succeed to make it work, there is a post on this in the Virgo forum at Eclipse.
If you succeed, let me know how ;)
Getting rid of #Configurable and doing the following in the servlet init method does the trick:
#Override
public void init() throws ServletException {
super.init();
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
As per the spring documentation
Externalized values may be looked up by injecting the Spring Environment into a #Configuration class using the #Autowired or the #Inject annotation:
#Configuration
public class AppConfig {
#Inject Environment env;
#Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
myBean.setName(env.getProperty("bean.name"));
return myBean;
}
}
I'm trying to setup a TransactionManager in my Web Application (powered by Spring MVC 3), as I need to have one method of a component annotated as #Transactional.
This is my situation:
web.xml: load 2 xml files for the Spring ContextLoaderListener (applicationContext.xml and database.xml)
applicationContext.xml: contains some beans which I can't define via annotation, plus the tags for annotation, plus the usual context:annotation-config and context:component-scan (this component-scan includes the package that contains the #Transactional method)
database.xml: contains the datasource (I'm using BasicDataSource from commons-dbcp), the transaction manager definition and tx:annotation-driven.
I've got a #Component (DeleteComponent) which has an interface and an implementation (DeleteComponentImpl). The implementation class is annotated with #Component and has one public method annotated with #Transactional (I annotated the concrete class and not the interface, as Spring documentation states). For #Transactional I didn't put any arguments, as defaults are fine. This class has some DAOs (annotated with #Repository) being injected via #Autowired. I'm using only plain JDBC (no Hibernate or other ORM). This #Component is injected into a #Controller (which is defined in spring-servlet.xml).
If the method annotated as #Transactional throws an exception (unchecked, as RuntimeException), however, nothing is rolled back. The database retains the changes did before the exception. I'm using Jetty web server for testing locally my application. The thing I noticed is actually that seems like no transaction manager is being set up. Actually, my transaction manager is named transactionManager. The xml line to set up the annotation-driven transaction is
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
If I change it to use a non-existing bean name like
<tx:annotation-driven transaction-manager="fake"/>
The application still deploys correctly and doesn't complain.
Any tips on what should I check to make it working?
Thanks.
I solved by using #Transactional(rollbackFor = RuntimeException.class) and switching from a BasicDataSource to a ComboPooled that's present in c3p0 library. Thanks for the suggestions though.
To get rollback when an exception is thrown add this:
#Transactional(rollbackFor=Exception.class)
You will also need to set up the transactionManger bean (here is mine, using hibernate) :
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
I found this tutorial informative.
I believe that #Autowired and #Resource aren't scanned by Spring on a #Component.
Try to use a ContextHolder class to get the context and the DAO
#Component
public class ContextHolder implements ApplicationContextAware {
/**
* Spring context which will directly be injected by Spring itself
*/
private static ApplicationContext context = null;
/**
* Overridden method of ApplicationContextAware, which will automatically be called by the container
*/
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
/**
/**
* Static method used to get the context
*/
public static ApplicationContext getApplicationContext() {
return context;
}
}
and call your dao with :
ContextHolder.getApplicationContext().getBean("MyDAO");
An #Async method in a #Service-annotated class is not being called asynchronously - it's blocking the thread.
I've got <task: annotation-driven /> in my config, and the call to the method is coming from outside of the class so the proxy should be being hit. When I step through the code, the proxy is indeed hit, but it doesn't seem to go anywhere near any classes related to running in a task executor.
I've put breakpoints in AsyncExecutionInterceptor and they never get hit. I've debugged into AsyncAnnotationBeanPostProcessor and can see advice getting applied.
The service is defined as an interface (with the method annotated #Async there for good measure) with the implementation's method annotated #Async too. Neither are marked #Transactional.
Any ideas what may have gone wrong?
-=UPDATE=-
Curiously, it works only when I have my task XML elements in my app-servlet.xml file, and not in my app-services.xml file, and if I do my component scanning over services from there too. Normally I have one XML file with only controllers in it (and restrict the component-scan accordingly), and another with services in it (again with a component-scan restricted such that it doesn't re-scan the controllers loaded in the other file).
app-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"
>
<task:annotation-driven executor="executor" />
<task:executor id="executor" pool-size="7"/>
<!-- Enable controller annotations -->
<context:component-scan base-package="com.package.store">
<!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> -->
</context:component-scan>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
app-services.xml (doesn't work when specified here)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<!-- Set up Spring to scan through various packages to find annotated classes -->
<context:component-scan base-package="com.package.store">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<task:annotation-driven executor="han" />
<task:executor id="han" pool-size="6"/>
...
Am I missing something glaringly obvious in my configuration, or is there some subtle interplay between config elements going on?
For me the solution was to add #EnableAsync on my #Configuration annotated class:
#Configuration
#ComponentScan("bla.package")
#EnableAsync
public class BlaConfiguration {
}
Now the class in package bla.package which has #Async annotated methods can really have them called asynchronously.
With the help of this excellent answer by Ryan Stewart, I was able to figure this out (at least for my specific problem).
In short, the context loaded by the ContextLoaderListener (generally from applicationContext.xml) is the parent of the context loaded by the DispatcherServlet (generally from *-servlet.xml). If you have the bean with the #Async method declared/component-scanned in both contexts, the version from the child context (DispatcherServlet) will override the one in the parent context (ContextLoaderListener). I verified this by excluding that component from component scanning in the *-servlet.xml -- it now works as expected.
Jiří Vypědřík's answer solved my problem. Specifically,
Check if your method annotated with #Async is public.
Another useful information from Spring tutorials https://spring.io/guides/gs/async-method/:
Creating a local instance of the FacebookLookupService class does NOT
allow the findPage method to run asynchronously. It must be created inside
a #Configuration class or picked up by #ComponentScan.
What this means is that if you had a static method Foo.bar(), calling it in that manner wouldn't execute it in async, even if it was annotated with #Async. You'll have to annotate Foo with #Component, and in the calling class get an #Autowired instance of Foo.
Ie, if you have a annotated method bar in class Foo:
#Component
class Foo {
#Async
public static void bar(){ /* ... */ }
#Async
public void bar2(){ /* ... */ }
}
An in your caller class:
class Test {
#Autowired Foo foo;
public test(){
Foo.bar(); // Not async
foo.bar(); // Not async
foo.bar2(); // Async
}
}
Edit: Seems like calling it statically also doesn't execute it in async.
Hope this helps.
Try adding proxy-target-class="true" to all <*:annotation-driven/> elements that support this attribute.
Check if your method annotated with #Async is public.
In my case the #Async method was defined in same class as the sync method that used it, and that apparently caused all jobs to hang on current thread.
Bad
#Component
#EnableAsync
public class TranslationGapiReader {
#Async
public CompletableFuture<GapiFile> readFile(String fileId) {
try { Thread.sleep(2000); } catch (Exception exc) { throw new RuntimeException("ololo", exc); }
return CompletableFuture.completedFuture(null);
}
public Stream<GapiFile> readFiles(Iterable<String> fileIds) {
List<CompletableFuture<GapiFile>> futures = new ArrayList<>();
for (String fileId: fileIds) {
futures.add(readFile(fileId));
}
return Stream.empty();
}
}
Good
#Component
#EnableAsync
public class AsyncGapiFileReader {
#Async
public CompletableFuture<TranslationGapiReader.GapiFile> readFile(String fileId) {
try { Thread.sleep(2000); } catch (Exception exc) { throw new RuntimeException("ololo", exc); }
return CompletableFuture.completedFuture(null);
}
}
#Component
#EnableAsync
public class TranslationGapiReader {
#Autowired
AsyncGapiFileReader asyncGapiFileReader;
public Stream<GapiFile> readFiles(Iterable<String> fileIds) {
List<CompletableFuture<GapiFile>> futures = new ArrayList<>();
for (String fileId: fileIds) {
futures.add(asyncGapiFileReader.readFile(fileId));
}
return Stream.empty();
}
}
I'm not Spring guru enough to understand why does it only work when the #Async method is in a different class, but that's what fixes the issue from my observations.
Firstly make your .xml config looks like:
<task:scheduler id="myScheduler" pool-size="10" />
<task:executor id="myExecutor" pool-size="10" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" proxy-target-class="true" />
(Yes, scheduler count and executor thread pool size is configurable)
Or just use default:
<!-- enable task annotation to support #Async, #Scheduled, ... -->
<task:annotation-driven />
Secondly make sure #Async methods are public.
#Async can not be used in conjunction with lifecycle callbacks such as #PostConstruct. To asynchonously initialize Spring beans you currently have to use a separate initializing Spring bean that invokes the #Async annotated method on the target then.
public class SampleBeanImpl implements SampleBean {
#Async
void doSomething() { … }
}
public class SampleBeanInititalizer {
private final SampleBean bean;
public SampleBeanInitializer(SampleBean bean) {
this.bean = bean;
}
#PostConstruct
public void initialize() {
bean.doSomething();
}
}
source
I realized following the tutorial async-method tutorial code that my issue source was: the bean with the annotated #Async method was not being created wrapped in a proxy.
I started digging and realized that there was a message saying
Bean 'NameOfTheBean' is not eligible for getting processed by all
BeanPostProcessors (for example: not eligible for auto-proxying)
You can see here responses about this issue and its basically that BeanPostProcessors are required by every Bean, so every bean injected here and its dependencies will be excluded to be processed later by other BeanPostProcessors, because it corrupted the life cycle of beans. So identify which is the BeanPostProcessor that is causing this and dont use or create beans inside of it.
In my case i had this configuration
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Autowired
private Wss4jSecurityInterceptor securityInterceptor;
#Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
#Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(securityInterceptor);
interceptors.add(payloadLoggingInterceptor);
}
}
WsConfigurerAdapter is actually a BeanPostProcessor and you realize it because there is always a pattern: #Configuration that extends classes and override some of it functions to install or tweak beans involved in some non functional features, like web service or security.
In the aforementioned example you have to override the addInterceptors and added interceptors beans, so if you are using some annotation like #Async inside DefaultPayloadLoggingInterceptor it wont work. What is the solution? Get ride of WsConfigurerAdapter to start.
After digging a bit i realized a class named PayloadRootAnnotationMethodEndpointMapping at the end was which had all valid interceptors, so i did it manually insted of overriding a function.
#EnableWs
#Configuration
public class WebServiceConfig {
#Autowired
private Wss4jSecurityInterceptor securityInterceptor;
#Autowired
private DefaultPayloadLoggingInterceptor payloadLoggingInterceptor;
#Autowired
public void setupInterceptors(PayloadRootAnnotationMethodEndpointMapping endpointMapping) {
EndpointInterceptor[] interceptors = {
securityInterceptor,
payloadLoggingInterceptor
};
endpointMapping.setInterceptors(interceptors);
}
}
So this will be run after all BeanPostProcessor have done their job. The setupInterceptors function will run when that party is over and install the interceptors beans. This use case may be extrapolated to cases like Security.
Conclusions:
If you are using a #Configuration extending from some class that runs some given functions automatically and you override them, you are probably inside of a BeanPostProcessor, so dont inject beans there and try to use AOP behaviour, because it wont work, and you will see Spring tells it to you with the beforementioned message in the console. In those cases dont use beans but objects (using the new clause).
If you need to use beans digg about which class is carrying the beans you want to setup at the end, #Autowired it and add those beans like i did before.
I hope this may save some time for you.
You need 3 lines of code for Async to work
in applicationContext.xml
At class level #EnableAsync
#Async at method level
#Service
#EnableAsync
public myClass {
#Async
public void myMethod(){
}
write a independent Spring configuration for asynchronous bean.
for example:
#Configuration
#ComponentScan(basePackages="xxxxxxxxxxxxxxxxxxxxx")
#EnableAsync
public class AsyncConfig {
/**
* used by asynchronous event listener.
* #return
*/
#Bean(name = "asynchronousListenerExecutor")
public Executor createAsynchronousListenerExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100);
executor.initialize();
return executor;
}
}
I overcome this problem with this situation.
Try below:
1. In config create bean for ThreadPoolTaskExecutor
#Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
return new ThreadPoolTaskExecutor();
}
2. In service method where #Async is used add
#Async("threadPoolTaskExecutor")
public void asyncMethod(){
//do something
}
This should get #Async working.