How to obtain bean from context? - spring

I have two services A and B, and A has in its pom file the dependency from B.
In service B I am creating a bean of a class named ClassB, and in service A I have a class called ClassA that receives in the constructor as parameter an instance of the ClassB from the other service.
Even I specify in the import section that is from the other service when I run both services I get the error:
Error creating bean with name 'classA' defined in file
[something/ClassA.class]: Unsatisfied dependency expressed through
constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'something.something.something.something.something.ClassB' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {}
I don't know how to specify to autowire the class with the bean of the other service.
package .....;
import something.something.something.something.something.ClassB;
public class ClassA {
private ClassB classB;
#Autowired
public ClassA(ClassB classB) {
this.classB = classB;
}
//More methods not relevant
}
Thank you for your help!

Inn your #Configuration class create a a method anotated with #Bean that returns the ClassB instance named classB as below
#Configuration
public class YourConfigClass {
...
.
.
#Bean
public ClassB classB() {
return new ClassB();
}
.
.
...
}

Related

How do I create and use a spring boot testing utility class?

I want to create a utility class just for my tests that have some methods that all tests will use to reduce code duplication.
Where do I create this class and how do I import it in my tests?
Errors
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'FooTest': Unsatisfied dependency
expressed through field 'myTestUtils'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.utils.MyTestUtils' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Files
// src/test/com/example/utils/MyTestUtils.java
public class MyTestUtils {
public String foo = "bar";
}
// src/test/com/example/services/FooTest.java
import com.example.utils.TestUtils;
#SpringBootTest
public class FooTest {
// If I remove this decorator I get that this.testUtils is null
#Autowired
MyTestUtils myTestUtils
#Test
public void testFoo() throws Exception {}
Asserthat(myTestUtils.foo).equals("bar")
}
Update
I solved the problem above with annotating the myTestUtils class with #Service
This works.
// src/test/com/example/utils/MyTestUtils.java
#Service
public class MyTestUtils {
public String foo = "bar";
}

Test application cannot find autowired bean in same project

I have a jar file that is the persistence layer, ad I just want to test the DAO that are simply autowired into other service layer clasees. But I want to test without any mocking or whatever.
I think this should be pretty simple. I have this in my srs/test/java
#RunWith(SpringRunner.class)
#ComponentScan("com.xxxx")
public class ApplicationTester {
#Autowired
AplicationDocumentDao aplicationDocumentDao;
#Test
private void testAplicationDocumentDao() {
aplicationDocumentDao.allForOrg(1);
}
}
All the DAO's are in the same projust under the usual /src/main/java
When I run the mvn to just run the tests like this:
mvn -Dtest=ApplicationTester test
I get this error:
Error creating bean with name 'xxx.test.ApplicationTester': Unsatisfied dependency expressed through field 'aplicationDocumentDao';
nested exception is 0rg.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx.dao.AplicationDocumentDao' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which means is can't find the Bean of course, but i would think the #ComponentScan would pick up add the Dao's.
How do I get this tester to find all my Dao's (Which are all annotated with #Componenet) and are picked up just fine in the rest for the application.
Any ideas?
** EDIT **
here is the DAO
#Repository
#Component
public class AplicationDocumentDao extends JdbcDaoSupport {
#Autowired
public void setJT(JdbcTemplate jdbcTemplate) {
setJdbcTemplate(jdbcTemplate);
}
public List<ApplicationDocumentBean> allForOrg(int orgId) {
String sql = "SELECT * FROM ApplicationDocument WHERE organizationId = ?";
return (List<ApplicationDocumentBean>) getJdbcTemplate().query(sql, new BeanPropertyRowMapper<ApplicationDocumentBean>(ApplicationDocumentBean.class), orgId);
}
}
Add annotate to your persistence layer class, for example: #Repository or #Component,like this :
#Repository
public interface OrderMapper {}

Spring Injecting implementation instead of interface

Here my class structure :
public interface CertificatService
{
}
The only one implementation
#Service
#Transactional
public class CertificatServiceImpl extends GestionCertificat implements CertificatService
{
}
And the injection :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatServiceImpl certificatService;
}
}
Injection the implementation causes injection failure :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connexionEbicsServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tess2i.service.impl.CertificatServiceImpl com.tess2i.service.impl.ConnexionEbicsServiceImpl.certificatService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.tess2i.service.impl.CertificatServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.inject.Inject()}
But if I inject the interface, it works :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatService certificatService;
}
}
But I need to inject the implementation so to benefit methods inherited from GestionCertificat
Can you help me to autowired the implementation. I understand that the real type is a proxy and not the implementation class CertificatServiceImpl as I would like. But what is the solution so ?
Thanks.
Perfect.
Just using proxy via CGLIB it is OK setting proxyTargetClass = true :
#EnableTransactionManagement(proxyTargetClass = true)
Thanks for the answer here : Spring - how to inject concrete interface implementation?

Autowiring of #Repository interface fails in concrete class

I have a concrete class implementing an interface as below:
#Service
public class BaseImpl implements Base{
#Autowired
Details details;
...
public void doSomething(){
}
}
Code for the interface:
#Service
public interface Base{
void doSomething();
}
My configuration class:
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
}
And the Details interface (which is annotated with #Repository):
#Repository
public interface Details extends CrudRepository<..., ...>{
...
}
Finally, I call the BaseImpl class as below:
#RestController
#RequestMapping(value = "...")
public class Caller{
public void foo(){
Base b = (Base) context.getBean("samplebean");
b.doSomething();
}
}
I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.model.Details com.pkg.BaseImpl.details; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 35 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 37 more
However, when I do the same auto-wiring in the Caller class (or for that matter any other class which is not implementing an interface), it seems to work fine. I'm new to Spring, so I might be missing something here.
Thanks.
You need to tell spring about the Details bean. Either declare it as a bean,
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
#Bean
public Details details() {
return new Details();
}
}
or annotate it with #Component (or some other more appropriate stereotype)
#Component
public class Details {
// ...
}
Since you are annotating your Details class with #Repository, you just need to add #ComponentScan annotation to your configuration class with the correct base package names.
#ComponentScan(basePackages = { "<yourBasePackage>" })

Spring expected at least 1 bean which qualifies as autowire candidate for this dependency

I have a trouble with this Autowire:
#Controller
public class ChiusuraController {
#Autowired
private ChiusuraProvider chiusuraProvider;
}
with this bean:
#Service #Transactional
public class ChiusuraProvider extends ThreadProvider {
public void run() {}
}
that extends
public abstract class ThreadProvider extends Thread implements InitializingBean, Runnable, DisposableBean {
...
}
I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'chiusuraController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.cinebot.service.ChiusuraProvider com.cinebot.web.controller.ChiusuraController.chiusuraProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.cinebot.service.ChiusuraProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I saw that I did not get this error if I remove extends ThreadProvider of autowired class, but I really need ThreadProvider abstract class.
If there is an interface anywhere in the ThreadProvider hierarchy try putting the name of the Interface as the type of your service provider, eg. if you have say this structure:
public class ThreadProvider implements CustomInterface{
...
}
Then in your controller try this:
#Controller
public class ChiusuraController {
#Autowired
private CustomInterface chiusuraProvider;
}
The reason why this is happening is, in your first case when you DID NOT have ChiusuraProvider extend ThreadProvider Spring probably was underlying creating a CGLIB based proxy for you(to handle the #Transaction).
When you DID extend from ThreadProvider assuming that ThreadProvider extends some interface, Spring in that case creates a Java Dynamic Proxy based Proxy, which would appear to be an implementation of that interface instead of being of ChisuraProvider type.
If you absolutely need to use ChisuraProvider you can try AspectJ as an alternative or force CGLIB based proxy in the case with ThreadProvider also this way:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Here is some more reference on this from the Spring Reference site: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/classic-aop-spring.html#classic-aop-pfb
You should put this line in your application context:
<context:component-scan base-package="com.cinebot.service" />
Read more about Automatically detecting classes and registering bean definitions in documentation.

Resources