2

This is part of my root-context.xml in spring mvc project(3.2.8 RELEASE).

<context:component-scan base-package="org.owls.test">

And I got some structures like below.

--org/owls/test
----dao
----dao.impl
----service
----service.impl
----controller

I got 2 annotations in my source code. one is @Repository which is on my DaoImpl Class and the other is @Service on my Service Interface.

I ran this with JUnit(4.7). DAOImpl thing works fine as I expected but Service does not work. I knew I can use @Service with an interface, but somehow this case can not.

error messages is here

  ERROR: org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@c458290] to prepare test instance [org.owls.test.service.JUnitService@277ec23b]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.owls.test.service.JUnitService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.owls.test.service.Service org.owls.test.JUnitService.svc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.owls.test.service.Service] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:376)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:307)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.owls.test.service.Service org.owls.test.service.JUnitService.svc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.owls.test.service.Service] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
    ... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.owls.test.Service] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
    ... 28 more

Is there any good samples which use component-scan xml setting and @Service annotation on interface so I can compare with mine?

thanks for help :D

Juneyoung Oh
  • 7,318
  • 16
  • 73
  • 121
  • 1
    The annotation must be on the implementation not the interface. For some annotations spring looks at the interface (like `@Transactional`) but that is also basically a hack. Annotations are not inherited from interfaces, this is by design and is a Java and not a spring related thing. – M. Deinum Oct 06 '14 at 08:45
  • @M.Deinum I found an article like this http://stackoverflow.com/questions/16351780/where-should-service-annotation-be-kept-interface-or-implementation and I believe I have such experiences too. Is there any document about this? – Juneyoung Oh Oct 06 '14 at 08:48
  • @JuneyoungOh Javadoc of `@Service` say `This annotation serves as a specialization of Component @Component, allowing for implementation classes to be autodetected through classpath scanning`. For this reason if you would use component-scan you should put on a concrete class. – Xstian Oct 06 '14 at 09:08
  • As stated putting `@Service` on the interface has no effect what so ever. If you look at the answer in the link you provided (and have read it) you see that they also put `@Component` and `@Repository` on the implementation. If you put it on the interface it doesn't do a thing and your components will not be detected. – M. Deinum Oct 06 '14 at 09:20
  • I also agree with all the comments above, annotations should always be added on implementations and not interfaces. You can not create instance of an interface so it makes sense to add annotations on classes. – varun Oct 06 '14 at 10:15
  • @M.Deinum Thanks. I knew about `@Repository`, but I thought `@Service` could be little bit different since It has same method with its implement. (I thought that spring can find its method because it has only one implement in the project) I understand what you mean after I saw `@Service` extends `@Component`(Thanks to Xstian). After all, the fact is I can not auto detect interface bean with annotation. Would you like to write an answer this so I can close this? – Juneyoung Oh Oct 10 '14 at 01:40

2 Answers2

4

The annotation must be on the implementation not the interface. For some annotations spring looks at the interface (like @Transactional) but that is also basically a hack. Annotations are not inherited from interfaces, this is by design and is a Java and not a spring related thing.

Putting @Service on the interface has no effect what so ever. If you look at the answer in the link you provided you see that they also put @Component or @Repositoryon the implementation. If you put it on the interface it doesn't do a thing and your components will not be detected.

The specialized annotations like @Service, @Controller, @Repository are stereotype annotations. That way you can see what type of component it is (there are even more like @Endpoint - spring-webservices or @MessageEndpoint - spring-integration). For some of these annotations there is additional behavior like automatic exception translation for @Repository annotated beans.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
0

You must also change autoscan base-package to base-package="org.owls",it looks for all classes.

Jorge Novo
  • 377
  • 3
  • 4
  • It depends on the situation(every bean classes are under `test` package, so it does not matter) As far as I know, scanning too much package effects on application startup time. - I could not find the link, but if I am wrong, feel free to reply – Juneyoung Oh Aug 05 '18 at 23:54
  • If you classes are under test package this solution doesnt work, but it must work if you put @service on implementation. If it doesnt work. can you put the code?. – Jorge Novo Aug 06 '18 at 07:46
  • This post uploaded 3 years ago, I do not have it right now. You may be confused I used the term `structure`, I should use `package`.(I mean the second code block of the original post) Sorry for confusing. – Juneyoung Oh Aug 07 '18 at 00:30
  • Anyway, Thanks for the reply to the old post. Have a great day – Juneyoung Oh Aug 07 '18 at 09:00