#Autowired does not create members in constructor - java

I have a bean that is created from context, after which a autowired member is created:
#Service
public class FileDownloadService extends WFWFileDownloadService {
#Autowired
ConfigurationManager configurationManager;
When I use in code manual constructor call:
FileDownloadService fileDownloadService = new FileDownloadService();
I see configurationManager is null, so I have to make manual wiring:
public FileDownloadService() {
configurationManager = new ConfigurationManagerImpl();
}
What am I doing wrong to make autowiring working with manual creating?

When you call the constructor directly, you're just creating an object and not a bean. The support of the #Autowired annotation is a feature of bean.
Ask the Spring context for the bean.

If you attempt to get the bean by using new operator, you will get all autowired beans inside that class as null.
Your service class is annotated with #Service, so to use it you should autowire this service class also.
Sample code to access service bean in other classes is :
#Controller or #Component
public class OtherClass {
#Autowired FileDownloadService fileService;
public void download() {
fileService.downloadFile();
}
}
In order this class to be able to autowire other beans, this class itself should be annotated with #Controller or #Component.

The Answer is simple:
If you manually create the Object, there is no wiring involved. How should Spring know, that you are in need for wiring? Instead of using new, you could use the getBean() method of the application context (Bean Factory). http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html
http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html

Related

Spring : creating beans with #Bean

I have an issue with beans creations :
#Bean
Service carService() {
return new Service(new CarRepository(), "car");
}
My issue is that CarRepository class has a dependency to EntityManager em variable (with #PersistenceContext)
So if I use new operator, I'm missing this dependency (because I'm instanciating myself the bean).
Also I have many services (CarService, BikeService etc...) and many repositories too (CarRepository, BikeRepository etc...). So using annotations directly in classes seems difficult.
So any solutions ?
Simple. Pass your repository as dependency into your Bean factory function:
#Bean
Service carService(final CarRepository carRepository) {
return new Service(carRepository, "car");
}
The repository needs to exist as a bean itself. You can create the repository bean in another bean method of a configuration class, or by annotating the class and having it created during component scanning.
I think you need to annotate every repository class with #Repository
annotation. And every service class with #Service.
In Spring you should not use the new operator for Services. Use the annotation
#Service
public classSomeClass {
or
#Component
public classSomeClass {
and your class can be injected via depnendency Injection.
If you want to create a new custom bean that can be used via dependencyInjection This is what the #Configuration annotation is for.
#Configuration
public class ConfigurationClass{
#Bean
public SomeClass createSomeClass(){
return new SomeClass();
}
}

How to properly inject #Autowired between Spring Boot classes?

I have a classA which implements an interfaceA, with a methodA, then I have a classB in which I call classA with an #Autowired to be able to use methodA, but it gives me a warning that I must create a method for classA. Why is this happening? Doesn't #Autowired work like this in this case? Should I just instantiate classA? Thank you very much for your answers.
ClassA
#RequiredArgsConstructor
public class RepositoryImpl implements IRepository {
#Autowired
private final TransactionDataMapper transactionDataMapper;
#Autowired
private SpringDataColminvoice springDataColminvoice;
#Override
public <S extends TransactionDto> S save(S s) {
Colm colm = transactionDataMapper.toEntity(s);
//methodA
springDataColminvoice.save(colm);
return null;
}
}
InterfaceA
public interface IRepository extends IRepository<TransactionDto, Integer> {}
ClassB
#Service
#RequiredArgsConstructor
public class ServiceImpl implements IInvoiceService {
#Autowired
private RepositoryImpl repositoryImpl;
#Override
public void save(CMessage cMessage) throws HandlerException {
try {
TransactionDto transactionDto = cMessage.getTransaction();
// methodA
repositoryImpl.save(transactionDto);
} catch (Exception e) {
throw new HandlerException(e.getMessage());
}
}
}
Exception
Action:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field RepositoryImpl in com.st.ms.yyu.d.binvoce.infraestructure.rest.spring.services.impl.InvoiceServiceImpl required a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.ServiceImpl' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.RepositoryImpl' in your configuration.
(posting this as an answer since I do not have enough reputation to comment)
As others have pointed out already, a code sample would help tremendously.
That being said, though, it sounds like you're missing implementation for "ClassA".
If you have an interface that "ClassA" implements, you have to implement the interface's methods in "ClassA" before you can use them.
I assume your code currently looks somewhat like this?
public interface InterfaceA {
void methodA();
}
public class ClassA implements InterfaceA {
}
public class ClassB {
#Autowired
ClassA classA; // Cannot use {#link InterfaceA#methodA} because the class does not implement the function
}
If this is your code, make sure you add an implementation for your "methodA()" function in "ClassA". Somewhat like so:
public class ClassA implements InterfaceA {
#Override
public void methodA() {
}
}
Additionally, in order to autowire in Spring (Boot), you need to ensure that the class you'd like to autowire is marked as such. You can autowire beans.
To make "ClassA" in the example eligible for autowiring, make sure to instantiate it either as:
A bean (using the #Bean annotation).
A component (using the #Component annotation).
A service (using the #Service annotation).
Any of the other annotations that may match your use case the best.
In our example, this would look somewhat like this:
#Component // Or #Service / whatever you may need
public class ClassA implements InterfaceA {
#Override
public void methodA() {
}
}
Hope you've found any of this helpful. All the best!
-T
As what I have understood, #Autowire means injecting the value/instance of the specific property where you put the annotation #Autowire. In this case, #Autowire only happens when there is defined/created Bean within your basePackage of your Spring Boot project that can match it, i.e. where your #Autowire referred to (meaning there is no conflict issue like ambiguity, etc. and the DataType(Class) can be implicitly casted). In your example, first you treat the IRepository and/or RepositoryImpl as Repository without using the #Repository annotation to inform the Spring Boot default configuration that this is a Repository bean. As you didn't put the POM.xml or posted the related code, I presumed you are creating your own repository class. I think it's much better to post your dependencies here.
But as what others pointed out. You need to create a bean that can match the #Autowired you've put on TransactDataManager & SpringDataColminvoice. You need also to inform the Spring Boot or register it that your class A is a Bean by annotating
#Bean - defining a regular bean,
#Component - a Component in the Project,
#Service - a Service in the Project,
#Repository - a Repository (if you're using Spring JPA), etc.
#<Other Annotations depending of what other Spring Project/Dependencies your using>
Since newer versions of Spring is moving to annotation based from XML mapping, we need to put proper annotation for each class/object that we want to be auto injected/instantiated from #Autowired using the above sample annotations depending on the role/purpose of your class/object is.
I suggest if you're not sure. Then create a typical bean using common annotation #Bean. So your class A might be
#Component //Insert proper Annotation for your class if necessary. This is just a sample
#RequiredArgsConstructor
public class RepositoryImpl implements IRepository {
#Autowired
private final TransactionDataMapper transactionDataMapper;
#Autowired
private SpringDataColminvoice
springDataColminvoice;//segunda
#Override
public <S extends TransactionDto> S save(S s) {
//Some implementation
}
#Bean
private TransactionDataMapper getTransactionDataMapper(<Some parameters if needed>){
return <an instance for TransactionDataManager>;
}
#Bean
private SpringDataColminvoice getSpringDataColmInvoice(<Some parameters if needed>){
return <an instance for SpringDataColminvoice>;
}
}
Note that 2 beans definition are optional if there are already a Beans define on outside class or if it was marked by other annotation like #Service, #Component or other proper annotations and the other one bean is just a reference parameter for the other bean in order to properly instantiated.
In your class B is the following:
public class ClassB {
#Autowired
ClassA classA;
/*Note: ignore this Bean definition if Class A is annotated with #Component,
#Service, or other proper #Annotation for Class A.
*/
#Bean
private ClassA getClassA(<Some Parameters if Needed>){
return <Instance of Class A>
}
}
Take note that, you don't need to put a Bean definition inside the Class B if you put a proper annotation for your Class A like #Component, #Service, etc.

Spring why #MockBean can't autowire an interface using profile

I've an interface with two implementations. Which implementaton is to be used depends of the environment (production, development, test, ...). I therefore use Spring profiles. I'm using a configuration file to instantiate the correct implementation.
#Configuration
public class BeanConfiguration {
#Profile({"develop","test-unit"})
#Bean(name = "customerEmailSender")
public CustomerEmailSender emailSenderImpl_1(){
return new EmailSenderImpl_1();
}
#Profile({"prod"})
#Bean(name = "customerEmailSender")
public CustomerEmailSender emailSenderImpl_2(){
return new EmailSenderImpl_2();
}
}
When the Spring container starts (with a specific profile), the correct bean is autowired into the class, and all works fine.
#Component
public class CustomerEmailProcessor {
#Autowire
private CustomerEmailSender customerEmailSender;
...
}
I also have a test class in which I want to autowire the bean. I'm using #Mock for autowiring.
The profile is set to "test-unit" in the test class. So, I'm expecting the spring container to lookup in the config class for the correct bean to be instantiated. But this doesn't happen.
Instead, an Exception is thrown :
Caused by: java.lang.IllegalStateException: Unable to register mock bean .... expected a single matching bean to replace but found [customerEmailSender, emailSenderImpl_1, emailSenderImpl_2]
When using #Autowire annotation, all goes fine. But of course the bean is not mocked anymore and that's what I need to have.
#RunWith(SpringRunner.class)
#ActiveProfiles(profiles = {"test-unit"})
#Import(BeanConfiguration.class)
public class CustomerEmailResourceTest {
#MockBean
private CustomerEmailSender customerEmailSender;
}
I've put a breakpoint in the config class, and I can see that when using #Autowire in the test class, the correct bean is instantiated (breaks at the line "return new EmailSenderImpl_1();".
When using #Mock, no bean at all is instantiated. Spring doesn't break at the line "return new EmailSenderImpl_1();"
Why is it that Spring can find the correct bean when using the #Mock annotation.
The #Mock annotation must be the reason that Spring doesn't use the config class "BeanConfiguration.java". That makes sence after all.

How to inject static field in static class in spring

I have the service MyStaticService which is doing some calculations using a DAO.
How can I inject the MyDao object into the class field?
I've tried to implement the setter with #Autowired but when I call doCalculations(..) the DAO is null. What am I doing wrong?
public class MyStaticService
{
private static MyDao dao;
public static int doCalculations(..){
dao.doSmth()
// omitted
}
}
First of all you cannot Autowire Spring beans inside classes that are not managed by Spring.
Hence in your example even if you DAO is a valid Spring managed bean, you cannot inject that in your MyStaticService. Of course it will always be null. Spring wouldn't be able to know what dependencies to scan and inject if your static service class is itself not a Spring Component
Spring dependency injection is meant to work only in classes managed by the Spring IOC container.
Your StaticService class makes more sense to be of a Singleton Class, hence there is no harm in declaring it as a Spring component.
#Component
public class MyStaticService
Then you can Autowire your DAO classes.
Service classes should ideally be Singletons with other singletons dependencies like your DAOs.
You need initialize your object for you to access the functions of MyDao() class like this:
dao = new MyDao();
or while you create the instance
private static MyDao dao = new MyDao();
else it will always show null

How to Autowire a Spring-annotated service class in a #Configuration class?

I'm trying to inject a service-annotated class into a configuration class in a Spring Boot application, but it doesn't get injected (is set to null), which I assume is due to the Spring lifeycle.
Also, this service has an overloaded constructor that uses constructor injection, and I guess this is also a problem, as autowiring acts upon a default constructor. However, the service needs to be Spring-configured, so I don't think one can create a new instance in a Bean annotated method.
How can one solve this?
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private SessionService sessionService;
#Bean
public SessionService sessionService() {
return sessionService;
}
}
public interface SessionService extends BaseCacheService<Session> {
void extendExpiration(String key);
String getSessionId(String key);
}
#Service
public class SessionServiceImpl implements SessionService {
private Environment environment;
private UserService userService;
#Autowired
public SessionServiceImpl(Environment environment, UserService userService) {
this.environment = environment;
this.userService = userService;
}
}
If I exclude the #Bean method, then I get a compilation error:
Your error is the following (you are returning a null value):
#Bean
public SessionService sessionService() {
return sessionService;
}
Solution
Since your SessionServiceImpl is annotated with #Service, you can just remove the #Bean method and let spring create it. Spring already makes it available for you.
Or, If your SessionServiceImpl wasn't annotated with #Service, you would need the following :
#Bean
public SessionService sessionService() {
return new SessionService();
}
If this doesn't work, it may just be that your SessionServiceImpl is in a package not being scanned by spring (as suggested by #Miloš Milivojević)
You may add #ComponentScan to your Configuration class
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#ComponentScan("com.package.to.sessionServiceImpl-or-higher")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Expanding on #Alex's answer, when you annotate a method with #Bean, it tells Spring that this method will produce that type. So, you essentially told Spring to give you the null reference you already had for all Beans of type SessionService.
If you are using Annotation-based context configuration, you can Autowire any #Component Bean (not just #Service) that can be constructed without runtime parameters (e.g. has a default constructor or an Autowired Constructor). If you need to do something to create the bean (e.g. runtime configuration required), you would either create a method as #Alex suggested, or you can use getBean and pass in the Type and Constructor arguments. The former is generally preferred.
I was facing similar issue while writing an integration test class for a spring boot application. RestTemplate class and CounterService of metrics API are autowired in my service class. I could use #ContextConfiguration(Classes={RestTemplate.class}) for injecting RestTemplate to my service, but adding CounterService.class to above annotation does not help, maybe because CounterService is an interface not a concrete class, Hence I was getting "No bean of type CounterService found" issue.
Thanks to answer by Milos, I included #EnableAutoConfiguration to my integration test class, issue was resolved!
If Alex's answer does not work (removing the #Bean method), you're probably not using #EnableAutoConfiguration or your Application is not in the root-hierarchy package so it's not scanning the whole classpath. Try adding #ComponentScan("service.class.package") to your configuration (in addition to removing the sessionService method) and see if it helps.

Categories