Spring-boot my service which is autowired is null [duplicate] - java

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 2 years ago.
Field in my project is null and I don't have idea why. I don't initalize in project any autowired variable like new BingoGameService(); - so I don't know why I got null.
public class MessageReaction extends ListenerAdapter {
#Autowired
BingoGameService bingoGameService; //NULL
#Override
public void onMessageReceived(#Nonnull MessageReceivedEvent event) {
if(event.getMessage().getContentRaw().equals("!createBingo")) bingoGameService.createBingoGameForUser(event.getAuthor().getIdLong());
This is my service class:
#Service
public class BingoGameService {
#Autowired
DiscordUserRepo discordUserRepo;
#Autowired
BingoBoardRepo bingoBoardRepo;
#Autowired
GameMechanics gameMechanics;
public void createBingoGameForUser(Long id) {
if(bingoBoardRepo.findById(1L).isPresent()){
String[][] officialBingoBoard = bingoBoardRepo.findById(1L).get().getBingoBoard();
int[][] scoreBoard = gameMechanics.createScoreBoard(3,3);
DiscordUser discordUserToSave = new DiscordUser();
BingoGame bingoGame = new BingoGame(discordUserToSave, officialBingoBoard, scoreBoard);
discordUserToSave.setUserId(id);
discordUserToSave.setBingoGame(bingoGame);
discordUserRepo.save(discordUserToSave);
}
}

you don't need use #Autowired if you create class with constructor.
Add #Component over MessageReaction class
Spring Boot search for annotation like "#Component" "#Service" etc. if you don't include them over class name, it won't know where inject values/classes
#Component
public class MessageReaction extends ListenerAdapter {
private FooService fooService;
public MessageReaction(FooService fooService){
this.fooService = fooService
}
}

Depends on the category of layering of your app, you can annotate classes as #Component, #Service or #Repository.
I didn't see any annotation for the class MessageReaction. If it is a generic component you have to annotate it with #Component.
This annotation helps Spring container to instantiate the instance of your class MessageReaction and autowire the injected dependencies. Since there is no default constructor for the class MessageReaction, you have to annotate the dependency BingoGameService with #Autowired annotation.

Related

Injecting spring beans in non managed objects

the below bean of Class I want to inject in other non-managed bean, but it is not working as expected
#Component
#Setter
#Getter
public class AbstractLayoutProperties {
#Value("${spring.application.name}")
private String appName;
#Autowired
S3Service s3Service;
#Autowired
S3Client s3Client;
}
Below is the class which is not managed by the spring, but I am using #Configurable
#Configurable(preConstruction = true, autowire = Autowire.BY_NAME)
#EnableSpringConfigured
public class OverlayServiceImpl
implements GenericVehicleOverlayService<T, R> {
public findOnlyActive(){
appName = layoutProperties.getAppName(); // throwint NullPointerException beacuse the object not injected properly
}
#Autowired
AbstractLayoutProperties layoutProperties;
}
One more point, findOnlyActive method I am not calling directly, I am calling this from another service, lets say
#Service
public class OtherService{
public void findActive(){
OverlayServiceImpl impl=new OverlayServiceImpl();
impl.findOnlyActive();
}
#Autowired
OtherRepository otherRepo;
}
Problem statrement:
when impl.findOnlyActive(); is executed, it should inject all the required beans inside OverlayServiceImpl. In the same class I have two beans which are autowired, it seems none of them injected, this is the reaosn that every time I am encountering Nullpointer exception. so my question is how do I make it work, what are the steps and action I need to take so that spring will inject the dependencies in non managed object i,e OverlayServiceImpl.

How can I use a JpaRepository, with #Autowired, inside a service class?

I've already read these questions and none of them worked:
Spring boot MVC - Unable to Autowire Repository in the service class
Why can't #Autowired a JPA repository - Spring boot + JPA
JpaRepository getting Null at service class
And also this one: https://www.baeldung.com/spring-autowired-field-null
Unfortunately, none of them worked.
What I have is:
Service interface:
#Service
public interface DayTradeService {
public List<DayTrade> getDayTrades(List<NotaDeCorretagem> corretagens);
}
Service Implementation:
public class DayTradeServiceImpl implements DayTradeService {
#Autowired
private DayTradeRepository dayTradeRepository;
#Override
public List<DayTrade> getDayTrades(List<NotaDeCorretagem> corretagens) {
// Several lines of code and some of them is trying to use dayTradeRepository.
}
}
My DayTradeRepository:
#Repository
public interface DayTradeRepository extends JpaRepository<DayTrade, Integer> {}
Inside my DayTradeController (annotated with #Controller), I can use a dayTradeRepository with #Autowired. But inside a service class, I cannot use. I get this message:
Cannot invoke "meca.irpf.Repositories.DayTradeRepository.getDayTrades()" because "this.dayTradeRepository" is null"
How can I make it possible?
EDIT after I accepted Nikita's answer:
I didn't post the Controller code, but it didn't have the #Autowired for the service class DayTradeServiceImpl. That was the point I was missing. After Nikita pointing that, I could solve the problem.
You not need create new object. You have to call like this:
#Controller
#RequestMapping("/test")
public class TestController {
#Autowired
private DayTradeServiceImpl dayTradeService;
#GetMapping(value = "/get")
public void getTrades() {
dayTradeService.getDayTrades(...);
}
}
And set annotation #Service for DayTradeServiceImpl.
#Service
public class DayTradeServiceImpl implements DayTradeService {
#Autowired
private DayTradeRepository dayTradeRepository;
#Override
public List<DayTrade> getDayTrades(List<NotaDeCorretagem> corretagens) {
// Several lines of code and some of them is trying to use dayTradeRepository.
}
}
Spring framework use inversion of control, which has container for beans. For detect beans use annotation like: #Service, #Component, #Repository.

How can I inject a service into another one in Java, SpringBoot? [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 1 year ago.
Hello, I've been trying to use a service into another one but I get null. Does anyone know how can I inject it correctly?
(My ClassServiceB has its #Service annotation)
This is my service class...
#Service
public class ClassServiceAImpl implements ClassServiceA {
#Autowired
ClassServiceB classServiceB;
#Override
public ClassOutDto searchDriverForOrder(InputDto inputDto ) {
classServiceB.doSomething(); //In this part classServiceB is getting null
...
}
Did you try to use #Autowired in the constructor class? It is easier when you want to do unit tests and the recommendation to do injection depended. Would be like this:
#Service
public class ClassServiceAImpl implements ClassServiceA {
private ClassServiceB classServiceB;
#Autowired
public ClassServiceAImpl(ClassServiceB classServiceB) {
this.classServiceB = classServiceB;
}
#Override
public ClassOutDto searchDriverForOrder(InputDto inputDto ) {
classServiceB.doSomething(); //In this part classServiceB is getting null
...
}
}
Don't forget that your ClassServiceB must also be annotated with #Service. Your interface should not be rated. If that doesn't help, share more of the properties, interface and ClassServiceB.

SpringBoot Autowiring a generic type fails because of multiple possible beans

I'm trying to create a class that Autowire an object of type T.
#component
public class TaskScheduler<T extends TaskService>{
#Autowired
private T taskService;
}
the problem is that I have two components that extend TaskService.
#component
public class firstTaskService extends TaskService {
}
and
#component
public class secondTaskService extends TaskService {
}
so when this line is executed (ts is being created)
#Autowired
TaskScheduler<firstTaskService> ts;
I get this error :
Description:
Parameter 1 of constructor in TaskScheduler required a single bean, but 2 were found
the message I got suggested this :
Action: Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify
the bean that should be consumed.
But from what I understood, the #Primary and #Qualifier annotations make me choose 1 of the components, which not what I want because I want to use firstTaskService and secondTaskService with that same class (TaskScheduler).
How could this be done?
Edit: Clarification: My objective is to reuse the TaskScheduler class with different classes that extend the TaskService class (not to use multiple classes that extend TaskService together in TaskScheduler).
If you want to autowire all beans that extends TaskService maybe you should change the autowired field to a List:
#Component
public class TaskScheduler<T extends TaskService>{
#Autowired
private List<T> taskService;
}
In this way Spring should put in the List all autowireable beans that extends TaskService.
EDIT: since you want to dinamically select the type of TaskService the only way I've found is the following. First, redefine your TaskScheduler:
public class TaskScheduler <T extends TaskService>{
private T taskService;
public void setTaskService(T taskService) {
this.taskService = taskService;
}
}
Your TaskService and related subclasses should remain untouched. Set up a configuration class as it follows:
#Configuration
public class TaskConf {
#Autowired
private FirstTaskService firstTaskService;
#Autowired
private SecondTaskService secondTaskService;
#Bean
public TaskScheduler<FirstTaskService> firstTaskServiceTaskScheduler(){
TaskScheduler<FirstTaskService> t = new TaskScheduler<>();
t.setTaskService(firstTaskService);
return t;
}
#Bean
public TaskScheduler<SecondTaskService> secondTaskServiceTaskScheduler(){
TaskScheduler<SecondTaskService> t = new TaskScheduler<>();
t.setTaskService(secondTaskService);
return t;
}
}
And then test your TaskScheduler in this way:
#Autowired
TaskScheduler<firstTaskService> ts;

NoSuchBeanDefinitionException: No qualifying bean of type [duplicate]

This question already has an answer here:
What is a NoSuchBeanDefinitionException and how do I fix it?
(1 answer)
Closed 6 years ago.
I stack with above mentioned exception and really don't understate why it is appeared. I am using spring boot and declare bean through the annotation.
Application is executed by this class:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
My problem bean has the following declaration:
#Service
public class OrderSvc extends AbstractService implements DAOService {
I try to put it in the following bean:
#RestController
public class OrderController {
#Autowired
CarSvc carSvc;
#Autowired
OrderSvc orderSvc;
and the exception is appeared: Could not autowire field: biz.Services.OrderSvc biz.controllers.rest.administrator.OrderController.orderSvc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [biz.Services.OrderSvc] 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 have also CarSvc bean that is located at the same package as OrderSvc and extends the same classes but there are no problems with it injection
#Service
public class CarSvc extends AbstractService implements DAOService<Car> {
Do you have any ideas why this exception appears ?
Spring creates proxies for classes that declare #Transactional, so that it is able to add the transactional behaviour and intercepted calls to your object. If the bean extends any interface Spring is going to create a Dynamic Proxy using the JDK Reflection API and this can only be done by interface. The proxy is a new object implementing the same interface. So your target bean is not your implementation but a proxy. That is why you were getting a non qualify bean exception.
CGLIB, on the other hand, can create a proxy by subclassing.
So, to get it working, you need to change your bean type to the interface or you can configure cglib using #EnableTransactionManagement(proxyTargetClass = true).
Try to to autowire your beans using interfaces rather than implementations :
#RestController
public class OrderController {
#Autowired
#Qualifier("carSvc")
DAOService carSvc;
#Autowired
#Qualifier("orderSvc")
DAOService orderSvc;
}
Edit : But before that you have to give names to your services :
#Service("carSvc")
public class CarSvc extends AbstractService implements DAOService<Car> {}
#Service("orderSvc")
public class OrderSvc extends AbstractService implements DAOService<Order> {}
What's going on here is that Spring generate proxies of your services based on the CarSvc, OrderSvc and implement the DAOService but does not extend the CarSvc, OrderSvc.
//somthing like this
class CarSvcProxy implement DAOService {
public Object getOrder(Long id) {
try {
// ...
txManager.commit();
} catch (Exception ex) {
txManager.rollback();
}
}
}
#RestController
public class OrderController {
//So when you do this :
#Autowired
CarSvc carSvc;
//it's somehow like if you did :
CarSvc carSvc = new CarSvcProxy(); //carSvc != CarSvcProxy
//But this will work :
DAOService carSvc = new CarSvcProxy(); //because CarSvcProxy implement DAOService
}
I found the code which leads to exception but I really don't undestand why.
In my OrderSvc there is the following method:
#Transactional(readOnly = true)
public Object getOrder(Long id) {
final Order order = getDAO().findOne(id);
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);
return orderDTO;
}
So if the annotation #Transactional(readOnly = true) was excluded the application can be excecuted without problem... Do you have any ideas why this annotation lead to NoSuchBeanDefinitionException ?

Categories