1

I work on simple Spring Boot application and want to use concurrent threads on it. To achieve this I use @Async annotation on service method, but when I add @Async annotation spring DI crashes. It works without @Async within one thread no problems. To call service method I create jUnit test. Error log shows DI not works and no such bean found for service class. Please help to run multiple threads with @Async on Spring.


EDIT I tried to put in my test class @Autowired service interface instead of it's implementation and after that @Async method runs in other threads. How should I test different implementations of my service?

Was and crash:

@Autowired
CatalogPageServiceImpl catalogPageServiceImpl;

Now and not crash:

@Autowired
CatalogPageService catalogPageService;

My service interface:

public interface CatalogPageService {
    public void processPagesList(List<CatalogPage> catalogPage);
    public void processPage(CatalogPage catalogPage);
}

Test class:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CLApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class CatalogPageServiceImplTest {

    @Autowired
    CatalogPageServiceImpl catalogPageServiceImpl;

    @Test
    public void processPageTest(){
        for (int i=0; i<20; i++){
            catalogPageServiceImpl.processPage(
                    new CatalogPage("test url string "+Integer.toString(i)));
        }
    }
}

Application class:

@SpringBootApplication
@EnableAsync
@ComponentScan(basePackages = {"org.cl, org.cl.service.location "})
public class CLApplication {

    private static final Logger log = LoggerFactory.getLogger(CLApplication.class);

    @Bean
    public TaskExecutor locationPageExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(20);
        return executor;
    }   

    public static void main(String[] args) {
        log.info("Application main method call");
        try{
            SpringApplication.run(CLApplication.class, args);
        }catch(Throwable t){
            log.error("Unexpected error: ",t);
        }
        log.info("Application main method exit");
    }
}

Service class:

@Service
public class CatalogPageServiceImpl implements CatalogPageService {

    @Override
    public void processPagesList(List<CatalogPage> catalogPageList) {
        for (CatalogPage catalogPage:catalogPageList){
            processPage(catalogPage);
        }
    }

    @Override
    @Async("locationPageExecutor")
    public void processPage(CatalogPage catalogPage) {
        try {
            Thread.sleep((new Random()).nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("print from Async method "+catalogPage.getUrl());
    }
}

Error log:

org.springframework.beans.factory.BeanCreationException: Error creating bean wit
h name 'org.cl.service.CatalogPageServiceImplTest': Injection of autowired depen
dencies failed; nested exception is org.springframework.beans.factory.BeanCreati
onException: Could not autowire field: org.cl.service.location.CatalogPageServic
eImpl org.cl.service.CatalogPageServiceImplTest.catalogPageServiceImpl; nested e
xception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
qualifying bean of type [org.cl.service.location.CatalogPageServiceImpl] found f
or dependency: expected at least 1 bean which qualifies as autowire candidate fo
r this dependency. Dependency annotations: {@org.springframework.beans.factory.a
nnotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~
[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.7
.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:385) ~[spring-be
ans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionLis
tener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[sp
ring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.support.DependencyInjectionTestExecutionLis
tener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[sp
ring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.TestContextManager.prepareTestInstance(Test
ContextManager.java:228) ~[spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(S
pringJUnit4ClassRunner.java:230) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflect
iveCall(SpringJUnit4ClassRunner.java:289) [spring-test-4.2.7.RELEASE.jar:4.2.7.R
ELEASE]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.j
ava:12) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(
SpringJUnit4ClassRunner.java:291) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr
ingJUnit4ClassRunner.java:249) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(Spr
ingJUnit4ClassRunner.java:89) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:
4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.
jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.1
2.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.
jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12
.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbac
ks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.2.7.RELEASE.jar:
4.2.7.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallback
s.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.2.7.RELEASE.jar:4.
2.7.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.
12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJU
nit4ClassRunner.java:193) [spring-test-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestRef
erence.java:86) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:3
8) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu
nner.java:459) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu
nner.java:675) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.
java:382) [.cp/:na]
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner
.java:192) [.cp/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not au
towire field: org.cl.service.location.CatalogPageServiceImpl org.cl.service.Cata
logPageServiceImplTest.catalogPageServiceImpl; nested exception is org.springfra
mework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [
org.cl.service.location.CatalogPageServiceImpl] found for dependency: expected a
t least 1 bean which qualifies as autowire candidate for this dependency. Depend
ency annotations: {@org.springframework.beans.factory.annotation.Autowired(requi
red=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573
) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(Inject
ionMetadata.java:88) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331) ~
[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    ... 26 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No q
ualifying bean of type [org.cl.service.location.CatalogPageServiceImpl] found fo
r dependency: expected at least 1 bean which qualifies as autowire candidate for
 this dependency. Dependency annotations: {@org.springframework.beans.factory.an
notation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNo
SuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans
-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResol
veDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.7.RELEASE.
jar:4.2.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolve
Dependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.7.RELEASE.ja
r:4.2.7.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProc
essor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545
) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]
    ... 28 common frames omitted
4
  • Show your web.xml. Commented Jul 14, 2016 at 11:18
  • I do not have web.xml, because not use web (servlet) server at all. My test.properties contains: spring.main.web-environment=false Commented Jul 14, 2016 at 11:22
  • did you solve your problem? Commented Jun 27, 2017 at 17:54
  • Hi. Yes I did it, and it works great when set up properly, but I do not have it under my hands now. Sorry, cannot help with it now. Commented Jun 28, 2017 at 6:53

3 Answers 3

2

Your application is crashing because you are using Async method (processPage()) in same class. Please check - https://dzone.com/articles/effective-advice-on-spring-async-part-1

There are few rules for using @Async in your application:

  1. The return type of Async method should be void
  2. Never write an Async method in the same class where the caller method invokes the same Asyncmethod in the same class.
  3. There should not be Aop Circular dependency.

Please visit - https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/Async.html

Sign up to request clarification or add additional context in comments.

Comments

1

The basePackages attribute on the @ComponentScan annotation on class CLApplication is wrong:

@ComponentScan(basePackages = {"org.cl, org.cl.service.location "})

This should be:

@ComponentScan(basePackages = {"org.cl", "org.cl.service.location"})

The two packages should be specified as two separate strings, not as one string with package names separated by a comma.

You could also just specify org.cl, because Spring will also look in all subpackages, so org.cl.service.location will also be scanned if you specify org.cl:

@ComponentScan(basePackages = "org.cl")

In fact, since it's a Spring Boot application, you can remove the @ComponentScan annotation completely, because the @SpringBootApplication annotation already automatically includes it (it will scan the package and all subpackages that class CLApplication is in).

1 Comment

Yes right, thanks I changed it, though application still crash on DI when @Async annotation present
0

Just add a @Configuration to your Service class

@Configuration
@Service
public class CatalogPageServiceImpl implements CatalogPageService

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.