Autowire Bean with no default constructor, using config annotation - java

I have this Repository class which I wish to Autowire in a unit test. I'm currently getting the "no default constructor" error when running the test.
The class in question has no default constructor, I'm new to spring so may not have created the Bean correctly in the config class.
Below is the Bean in question (has no default constructor)
#Repository
public class GenericDaoImpl<T extends AbstractEntity> implements GenericDao<T> {
The config class
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackages = "com.example")
public class AppConfig {
#Bean
GenericDaoImpl<AbstractEntity> genericDoaIpm(final Class<AbstractEntity> tClass) {
return new GenericDaoImpl<AbstractEntity>(tClass);
}
}
And in the test I have:
#Autowired
private GenericDaoImpl<AbstractEntity> genericDaoImpl;
Is there something I'm missing or doing wrong here?

According to this and this, you only need to mark your constructor with #Autowired.
GenericDaoImpl.java
#Autowired
public GenericDaoImpl(Class<?> tClass) {
...
}
You can apply #Autowired to constructors as well. A constructor #Autowired annotation indicates that the constructor should be autowired when creating the bean, even if no elements are used while configuring the bean in XML file

Related

How to use spring #autowired annotation in the class having void methods?

I have an interface and service implements it. It has some void methods.
I am using spring java bean configuration. But unable to create bean object because of void methods.How to handle this problem.
I tried to use #PostConstruct instead of #Bean after reading some blogs, but it didn't work out.
public interface MyInterface {
void someData(List<MyClass> list, String somedata);
}
#Service("myInterface")
public DummyClass implements MyInterface {
public void someData(List<MyClass> list, String somedata){
// my business logic
}
}
public AppConfig {
#Bean
public MyInterface myInterface {
return new DummyClass(); // but gives error void cannot return value
}
}
My Junit looks like this
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
classes = {AppConfig.class},
loader = AnnotationConfigContextLoader.class
)
public class MyTest {
#Autowired
DummyClass dummyClass;
// If I don't use AppConfig and simply autowire then I get
"Error creating bean name, unsatisfied dependency
}
How do I achieve dependency injection here?
Use #Configuration annotation on AppConfig class, with this all the beans defined on this class will be loaded on spring context.
If you use #Service annotation on DummyClass, you do not need to declare #Bean annotation because you are already saying to spring to detect this class for dependency injection. On the other hand use #Bean annotation to specify the instantiation of the class. Normally I let the #Bean to complex classes for dependency injection or to override configurations.

Spring Boot - How to create manually a bean and pass it to a hash map

Want put a class in a HashMap. For that I have created a Bean with #Service. This is it:
#Service
public class ServiceManagerImpl implements ServiceManager {
#Override
public void registerService() {
// registerService will put this in the HashMap!
dispatcher.registerService("serviceList", getServiceListImpl());
}
#Bean
public BusinessService getServiceListImpl() {
return new ServiceListManager();
}
}
Is this the right way to make something like this?
Move your bean definition from a class annotated with #Service to a configuration class annotated with #Configuration (or at least move to your main class which has #SpringBootApplication annotation, if you have). Then Autowire that bean here in the Service class. `
#Autowired BusinessService businessService
take a look here Where to put #Bean in Spring Boot?

Spring autowiring parameter by name

I have two beans with the type InterfaceA.
I was trying to inject the bean into an argument of a #Bean method using #Qualifier to autowire by name.
I was surprising that Spring can't resolve the proper bean unless your parameter name is matching the bean name.
I was trying:
#Component
public class ClassA implements InterfaceA {
}
#Component
public class ClassB implements InterfaceA {
}
#Configuration
public class AppConfig {
#Bean
#Autowired
#Qualifier("classA")
public SomeOtherClass someOtherClass(InterfaceA object) {...}
}
But got the NoUniqueBeanDefinitionException.
However if I use parameter name matching the component name it works fine.
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeOtherClass someOtherClass(InterfaceA classA) {...}
}
Could someone explain why I can't use autowiring by name with #Resource or #Qualifier here?
Add the #Qualifier annotation to the parameter not to the method:
public SomeOtherClass someOtherClass(#Qualifier("classA") InterfaceA object) {...}

Error creating bean because it's an interface?

Basically I have two beans implementing the same interface. One is for profile "default" and another "integration".
public interface SomeClientIfc { ... }
#Component
#Profile(value={"functional", "integration"})
public class StubSomeNIOClient implements SomeClientIfc {...}
public class SomeNIOClient implements SomeClientIfc {...}
#Configuration
#Profile("default")
public class SomeClientConfiguration {
#Bean
public SomeClientIfc someClient() {
...
SomeNIOClient someClient = new SomeNIOClient(numberOfParititions, controllerHosts, maxBufferReadSize,
connectionPoolSize);
return someClient;
}
}
In prod code it's
#Autowired
public SomeUserResolver(..., SomeClientIfc someClient) {...}
So far so good and I did see the stub bean is called in an integration test. Then I want to inject some test data into the stub bean in my integration test:
#ContextConfiguration(locations = {"/configProperties.xml", "/integrationTests.xml", ...})
#ActiveProfiles("integration")
public class SomeTestBase {
#Autowired
private SomeClientIfc someClientIfc;
}
However, when running the test I got error message
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'someClientIfc': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.audiencescience.some.client.SomeClientIfc]: Specified class is an interface
I even tried to replace SomeClientIfc with StubSomeNIOClient but still get the same message, even though StubSomeNIOClient is not an interface.
You should add a Qualifier annotation along with the Autowired one to specify which bean must be instantiated:
#Autowired
#Qualifier("my-bean")
The reason it's trying to inject the SomeClientIfc is because you called the variable 'someClientIfc'.
In the integration environment you have all 3 classes initialized: SomeClientIfc, StubSomeNIOClient, and SomeNIOClient. This creates a confusion for spring, luckily there are ways to resolve that confusion.
One way is as mentioned above by Little Santi, another way is to name your variable 'stubSomeNIOClient' see code below
#ContextConfiguration(locations = {"/configProperties.xml", "/integrationTests.xml", ...})
#ActiveProfiles("integration")
public class SomeTestBase {
#Autowired
private SomeClientIfc stubSomeNIOClient;
}

Spring annotations confusion

i am really confused with spring annotations.
where to use # Autowired, where class is # Bean or # Component,
i understand we cannot use
Example example=new Example("String");
in Spring
but how alone
#Autowired
Example example;
will solve the purpose?
what about Example Constructor ,how spring will provide String value to Example Constructor?
i went through one of the article but it does not make much sense to me.
it would be great if some one can give me just brief and simple explanation.
Spring doesn't say you can't do Example example = new Example("String"); That is still perfectly legal if Example does not need to be a singleton bean. Where #Autowired and #Bean come into play is when you want to instantiate a class as a singleton. In Spring, any bean you annotate with #Service, #Component or #Repository would get automatically registered as a singleton bean as long as your component scanning is setup correctly. The option of using #Bean allows you to define these singletons without annotating the classes explicitly. Instead you would create a class, annotate it with #Configuration and within that class, define one or more #Bean definitions.
So instead of
#Component
public class MyService {
public MyService() {}
}
You could have
public class MyService {
public MyService() {}
}
#Configuration
public class Application {
#Bean
public MyService myService() {
return new MyService();
}
#Autowired
#Bean
public MyOtherService myOtherService(MyService myService) {
return new MyOtherService();
}
}
The trade-off is having your beans defined in one place vs annotating individual classes. I typically use both depending on what I need.
You will first define a bean of type example:
<beans>
<bean name="example" class="Example">
<constructor-arg value="String">
</bean>
</beans>
or in Java code as:
#Bean
public Example example() {
return new Example("String");
}
Now when you use #Autowired the spring container will inject the bean created above into the parent bean.
Default constructor + #Component - Annotation is enough to get #Autowired work:
#Component
public class Example {
public Example(){
this.str = "string";
}
}
You should never instantiate a concrete implementation via #Bean declaration. Always do something like this:
public interface MyApiInterface{
void doSomeOperation();
}
#Component
public class MyApiV1 implements MyApiInterface {
public void doSomeOperation() {...}
}
And now you can use it in your code:
#Autowired
private MyApiInterface _api; // spring will AUTOmaticaly find the implementation

Categories