Spring bean management using #Autowired - spring

I have a messaging call that will process my payload which starts from MyClass. In load test i see that the first payload is getting over written by the next. All my classes are spring managed by #Autowired. Obviously the bean scope is singleton and thats why this is happening. But i do not want to use new operator and want it to be spring annotation configured. Is there any way to fix this issue of losing data ?
UPDATE
My configuration looks like below :
Public class MyClass {
...
#Autowired
public MyService myService;
...
}
#Component
#Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class MyService{
#Autowired
public Aone one;
#Autowired
public Atwo two;
...
}
#Component
#Scope(value="prototype")
public class Aone {
}
I am attempting this configuration after suggestions from net. For every call i get in MyClass a new instance of MyService will be created and from there on all other instances like Aone / Atwo should have new instance, will this configuration be ok ?

Related

Autowiring of Service and Service Implementation class

Following are my code
#RestController
public class EmployeeController {
#Autowired
EmployeeService empService;
public EmployeeController (EmployeeService Impl empServiceImpl) {
super();
this.empService = empServiceImpl;
}
}
#Service
public interface EmployeeService {
public List<EmployeeDTO> getAllEmployeeDetails()
}
public class EmployeeServiceImpl {
public List<EmployeeDTO> getAllEmployeeDetails(){
//methods business logic and repo call goes here
}
}
When I start my server I am getting below error.
Parameter 1 of constructor in
com.app.in.controller.EmployeeController required a bean of type
'com.app.in.service.EmployeeServiceImpl' that could not be found
My understanding might be wrong. If I annotate the EmployeeSeriveImpl class also with #Service then it working.Is that is the correct way to do it ? My question is the service interface is annotated with #Service still why its implementation is also required to annotation. Please let me know if I miss something in that ? What is the standard method to solve this issue ?
You can get your dependency injected using a constructor. And #Autowired is optional in this case.
This is your example, but with a few corrections:
#RestController
public class EmployeeController {
// private final is a good practice. no need in #Autowire
private final EmployeeService empService;
// this constructor will be used to inject your dependency
// #Autowired is optional in this case, but you can put it here
public EmployeeController (EmployeeService empServiceImpl) {
this.empService = empServiceImpl;
}
}
I assume you have an interface EmployeeService and class EmployeeServiceImpl which implements that interface and is Spring Bean.
Something like this:
#Service
public class EmployeeServiceImpl implements EmployeeService {}
Why this #Service is needed? When you put this annotation on your class, Spring knows this is a bean that Spring should manage for you (container will create an instance of it and inject it wherever it is needed).
Check Spring docs to get more details about Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null.

How to use #Autowired annotation two or more different Component class for same service?

For example, have a class like as follows.
First XService service in class A is not null but second XService service in AmountValidator is null.I get NullPointerException I try to create bean new it works and then I get same exception when call AmountValidateService outsideRestService in XService.
How can I use XService everywhere that I use #Autowired annotation.
My main class:
#Service
class A extends AbstractA implements IA {
#Autowired
XService service; //first autowired definition. code go to check() method. service not null now.
public doSometing(){
validator.check();
service.methodA();
super.AbstractMethod();
}
}
Validator class used in class A :
class Validator<T> implements IValidator<T> {
public void check(){
rule.check(); // rule have a implements IValidator eg: amountValidator, dateValidator class
}
}
AmountValidator added to rule in class Validator.
#Component
class AmountValidator implements IValidator<T>{
#Autowired
XService service; // code comes here service is null. same service class mentioned above class A.
#Override
public void check(){
service.validateAmount(); // nullPointerException.
}
}
My main Service
#Component
class XService {
#Autowired
AmountValidateService outsideRestService;
public validateAmount(){
outsideRestService.validate(); // nullPointer when create XService with the `New` keyword
}
}
You have an error cause you are trying to create components/beans/services yourself. As i mentioned in comment when you create components yourself it - #Autowired doesn't work - thats you've got NPE
All classes annotated with #Component, #Service are considered special classes which are instantiated by Spring automatically via DI, instantiating them with new defeats the purpose of DI.
These special classes are named Spring Beans.
Every time the application starts, the framework instances all Spring Beans, and all #Autowired fields are injected by Spring automatically. But the Spring Beans must be defined somewhere in the class path. Else you will receive a NoSuchBeanDefinitionException
As an attempt to answer the question, since I don't have a stack trace nor all the Spring Bean definitions:
When you instantiate XService using new XService() your new instance will not actually initialize the field AmountValidateService outsideRestService, effectively leaving it as null.
You may set the field yourself but as I mentioned earlier, it defeats the purpose of DI
Your question is not complex, it is incomplete.

Mockito mock does not work as expected in Spring MockMvc test

In an Spring mockmvc test I want to replace a bean by a mock implementation which is configured using Mockito.when() definitions. The definitions are indeed respected at the time the mock is configured, as well as at the time the mock is injected into a depending bean (a controller advice in my case) during application context startup. However, when the mock is used during a certain test, all when definitions are gone.
Why?
Some remarks:
The mock is completely new code, so it is impossible that I am not aware of any call to Mockito.reset().
the mock at the time of usage is the same as at the time of creation.
a bypassing solution to the problem is to configure the mock in a #BeforeEach method in AbstractTest. However, I want to understand why it does not work without.
Here a simplified and anonymized example
#Component
public class MyBean {
private String property;
...
public String getProperty() {
return property;
}
}
#ControllerAdvice
public class MyControllerAdvice() {
private MyBean myBean;
#Autowired
public MyControllerAdvice(MyBean myBean) {
this.myBean = myBean;
System.out.println(this.myBean.getProperty()); // --> outputs "FOOBAR"
}
#ModelAttribute
public String getMyBeanProperty() {
return myBean.getProperty(); // --> returns null
}
}
public class AbstractTest {
#Configuration
static class Config {
#Bean
public MyBean () {
MyBean myBean = Mockito.mock(MyBean.class, "I am a mock of MyBean");
when(myBean.getProperty()).thenReturn("FOOBAR");
}
}
}
That's not a problem of Mockito. I think you simplified the example a lot and we don't see the full picture, but I can say that main cause - 2 different beans MyBean: one is initialized with Spring's #Component, second is in configuration class with #Bean.
Why do you use #Component for POJO/DO?
#Bean in the configuration class is being initialized lazy so better way to use #PostConstruct
If you want to leave both beans mark MyBean in the configuration class as #Primary

Explain how the #service in Spring work

I following my teacher but i have some confused. This is a interface extends CrudRepository from Spring data
import org.springframework.data.repository.CrudRepository;
public interface TaskRepository extends CrudRepository<Task,Integer>{
}
and this is class Service use that interface:
#Service
#Transactional
public class TaskService {
private final TaskRepository taskRepository;
public TaskService(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
public List<Task> findAll(){
List<Task> tasks = new ArrayList<>();
for(Task task : taskRepository.findAll()) {
tasks.add(task);
}
return tasks;
}
}
I confused that when an Controller want to use instance of TaskService. It just declare like this:
#Autowired
private TaskService taskService;
Who can explain me how it work? The init of TaskService have TaskRepository as argument. but I don't find any where init TaskRepository
Once you mark your class with #Component or any variation of it such as #Service/#Repository/#Controller, you delegate it's object management to spring.
By doing
#Autowired
private TaskService taskService;
you are telling spring that, while creating an object of the controller, first create the object of TaskService and assign it to taskService variable declared in the controller.
Then spring will try to create object of TaskService but while creating, it sees the constructor
public TaskService(TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
So, it will now try to create object of TaskRepository because without that, TaskService object can't be created.
Now, TaskRepository is an interface that extends CrudRepository and interfaces cannot be instantiated. Spring creates a proxy that implements TaskRepository, creates the object and injects it into taskRepository of the TaskService constructor.
So far, spring has built the TaskRepository, TaskService objects. It will simply inject TaskService object into autowired taskService variable of the controller.
Spring boot will automatically initialize JPA Repositoriy interfaces if found.
By default, Spring Boot will enable JPA repository support and look in the package (and its subpackages) where #SpringBootApplication is located. If your configuration has JPA repository interface definitions located in a package not visible, you can point out alternate packages using #EnableJpaRepositories and its type-safe basePackageClasses=MyRepository.class parameter.
https://spring.io/guides/gs/accessing-data-jpa/
In addition since Spring Framework 4.3 if there is a single constructor it will be attempted for autowiring.
https://spring.io/blog/2016/03/04/core-container-refinements-in-spring-framework-4-3
For your example you can omit the #Autowired for your constructor, because your Service has only one constructor.
JPA Repositoriy interfaces, TaskRepository will be automatically initialized by spring boot.

Make a third party class a service

I'm a beginner at Spring and beginning to understand how beans work. I want to declare a 3rd party class as a Service or a Bean. How do I do this? Should I just extend the class and annotate that?
example:
#Service
public class MyService { public MyService(ThirdPartyClass thirdPartyClass){..}....}
Here I cannot annotate ThirdPartyClass as a Service or otherwise
If your aren't the owner of the class that you would like to use as a bean, you can create the bean declaration in one of application's configuration classes:
#Configuration
public class YourConfig {
#Bean
public ThirdPartyClass thirdPartyClass() {
return new ThirdPartyClass();
}
}
Spring will instantiate an appropriate object based on that description and expose it via container to other beans.
You can add the class which is out of your control as #Bean
#Configuration
public class ApplicationConfig {
#Bean
public ClassName methodName() {
return new ClassName();
}
}
At the time of initializing the application, spring will call this method and register ClassName object to spring context and will be made available where you #Autowired this bean.

Resources