Spring Boot accessing dao service from custom class [duplicate] - java

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Role of new keyword in Spring Framework
(1 answer)
Closed 3 years ago.
I am trouble with accessing my service to save data in a class.
I have a class and wish to use my defined service that works well in my RestController by am struggling to access it in custom class.
I wish to do something like the following new MessageProcessor.processMessage(message) --> this should access service and save the data to database.
#Controller
public class MessageProcessor {
#Autowired
private IOTService iotService;
public MessageProcessor() {
}
public void processMessage(String message) {
iotService.addMessage(message);
}
}
It is being called like this in a random class.
The Autowired annotion is not working as i expected.
new MessageProcessor().processMessage("test");
I am new to Spring so any suggestions would be appreciated

First of all, you need to understand how the framework work. I am giving an example, may be it clears some of your doubts and logic.
The autowiring works in a way like, you have to follow a standard :
Make a domain class (Domain.class).
Make a controller (DomainController.class)(if there is need), mark it with annotation #Controller.
Make a service class,(DomainService.class), mark it with annotation #Service
In this way, you can use autowiring concept. If you want to use your service class method outside this class hierarchy, you have create its new instance with new keyword i.e. new DomainService()
The thing to be noted here autowiring works within a specific model not everywhere.

Related

What is the best practice to solve the issue "My bean is null after I new a object" [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 1 year ago.
I have a bean used in MyApp, but when I have MyApp app = new MyApp(), then carIF is null. What is the best practice to solve this issue? I have tried to make MyApp as a bean as well by adding #Component, so I don't need to do 'new MyApp()', but it turns out I need to keep making a java class as bean in my java classes calling workflow, which I don't think it is a right approach. How to solve the issue like this?
public class MyApp() {
#Autowired
private CarIF carIF;
When you instantiate the class on your own (MyApp()) you are not taking advantage of Spring-managed Beans and Spring Dependency Injection features. When you do it like that you can't expect Spring to inject a CarIF instance in your newly created MyApp instance.
As you mentioned, you should make MyApp a Spring-managed Bean by, for example, annotate it with #Component as follows:
#Component
public class MyApp() {
#Autowired
private CarIF carIF;
}
This will generally work, but it really depends on your project setup and if you are following a usual Spring project structure.

Helper Class Spring Boot with Environment Values [duplicate]

This question already has answers here:
Accessing spring beans in static method
(7 answers)
Closed 2 years ago.
I would like to create a helper class, but it just failed..
The error : java.lang.NullPointerException: null
When i do this without making a static class (with autowired) it works without problem. But it's a helper class, i think the static class is the better thing.
Thanks for help
Helper.java
public final class UrlHelper {
#Autowired
private static Environment bean;
public static String method(String projet) {
return "titi"+ bean.getProperty("property.name");
}
}
And in my service, i use it like this :
String list = getRequest.getHTTPRequest(UrlHelper.method(projet));
In Spring, the #Autowired annotation allows you to resolve and inject beans into other beans. In your case, the UrlHelper class is not a bean and therefore, your Environment is not injected (stays null), hence the error. You have two options:
Make the UrlHelper a bean using #Component, #Service, etc. This will make your class non-static.
Keep the UrlHelper static, and pass the Environment as parameter. This, I believe, is the more correct approach. The Environment can be injected in the class calling the static method.

Make an existing instance a spring-bean [duplicate]

This question already has answers here:
How to add bean instance at runtime in spring WebApplicationContext?
(3 answers)
Closed 3 years ago.
I'm developing a framework in Spring boot, that is used by some applications. In some point at runtime, the application supply me (the framework)
an instance of class A, that I want to aspect (using spring) its func method.
The problem is, that I am not the one who construct this instace so I can't create it by applicationContext.getBean(A.class).
Is there a way to give Spring this instance and tell it to make it (or proxy it with) a bean?
public interface A {
void func(int i);
}
Aspect:
#Aspect
public class AspectClass {
#Around("execution(*com.A.func(..))")
public void funcAspect(ProceedingJoinPoint joinPoint) throws Throwable {
....
}
}
I expect it to be something like: A bean = applicationContext.makeBean(instanceOfA)
EDIT: I can't control the construction of A, I'm not the one who construct it, and I just get its existing instance and want to aspect its func method, from now on.
Are you aware of #Bean annotation in Java #Configuration class? this is the 3rd and popular way of creating beans and that's exactly for the moment, when you don't want your Spring container to instantiate default beans from the candidate classes, but rather create your custom object (in the #Bean method), make any adjustments to that object (before you return it) and finally return that instance. Spring will automatically register that (your custom object) object as a bean in its application context.

Should i never use 'new' keyword on a spring boot project?

I'm working on Spring Boot Rest API, and I did end up using the new keyword here and there.
I'm wondering, did I do something wrong when I used the new keyword for my program. And if it is absolutely forbidden to use new keyword on a real project.
If the answer is yes should i annotate each class i wrote with #component annotation so i can instantiate an object using #autowired.
If the answer is no when can we break that rule ?
You can create objects using the new keyword in a spring application.
But these objects would be outside the scope of the Spring Application Context and hence are not spring managed.
Since these are not spring managed, any nested levels of dependency (such as your Service class having a reference to your Repository class etc)
will not be resolved.
So if you try to invoke a method in your service class, you might end up getting a NullPointer for the repository.
#Service
public class GreetingService {
#Autowired
private GreetingRepository greetingRepository;
public String greet(String userid) {
return greetingRepository.greet(userid);
}
}
#RestController
public class GreetingController {
#Autowired
private GreetingService greetingService;
#RequestMapping("/greeting")
public String greeting(#RequestParam(value = "name", defaultValue = "World") String name) {
return String.format("Hello %s", greetingService.greet(name));
}
#RequestMapping("/greeting2")
public String greeting2(#RequestParam(value = "name", defaultValue = "World") String name) {
GreetingService newGreetingService = new GreetingService();
return String.format("Hello %s", newGreetingService.greet(name));
}
}
In the above example /greeting will work but /greeting2 will fail because the nested dependencies are not resolved.
So if you want your object to be spring managed, then you have to Autowire them.
Generally speaking, for view layer pojos and custom bean configurations, you will use the new keyword.
There is no rule for using or not using new.
It's up to you if you want Spring to manage your objects or want to take care of them on your own.
Spring eases object creation, dependency management, and auto wiring; however, you can instantiate it using new if you don't want that.
I think its fine to use new keyword, but you should learn the difference between different stereotype (Controller, Service, Repository)
You can follow this question to get some clarity:
What's the difference between #Component, #Repository & #Service annotations in Spring?
Using appropriate annotation will allow you to correctly use DI (dependency injection), that will help in writing sliced tests for your spring boot application. Also the Service,Controller and Repository components are created as Singleton, so lesser GC overhead. Moreover components that you create using new keyword are not managed by Spring, and by default Spring will never inject dependencies in a object created using new.
Spring official documentation:
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
You will need new on Spring mock tests when you will have to create an object as service and inject mock object as dao.
Look at the following code; here as you see, based on a condition it's necessary to dynamically load advertisements on demand. so here you can not #autowire this group of items because all the information are loaded from DB or an external system, so you just need to fill you model accordingly.
if (customer.getType() == CustomerType.INTERNET) {
List < Advertisement > adList = new ArrayList < Advertisement > ();
for (Product product: internetProductList) {
Advertisement advertisement = new Advertisement();
advertisement.setProduct(product);
adList.add(advertisement);
}
}
Note it's appropriate to use Spring for managing external dependencies
like plugging a JDBC connection into a DAO or configurations like
specifying which database type to use.

#ControllerAdvice being called for all Controllers, not just basePackageClasses [duplicate]

This question already has answers here:
How to target specific handlers with a #ControllerAdvice #ModelAttribute?
(2 answers)
Closed 5 years ago.
I cannot provide the actual code since it is on another system but the issue I am seeing in my Spring 4.2.6 Web Release is the use of basePackageClasses not actually mapping to the controller.
Let's say I have 3 Controllers: AController.class, BController.class, and CController.class.
For each I have created a ControllerAdvice: AControllerAdvice.class,BControllerAdvice.class & CControllerAdvice.class.
I use the annotation as follows:
#ControllerAdvice(basePackageClasses = AController.class)
public class AControllerAdvice{
#ModelAttribute
public void addModelInformation(Model model){
//controller specific model information for header and footer added here
}
}
What I am experiencing is that when I call a rest method in AController.class, I have verified that via logging, that the 'addModelInformation' method is being called from all three ControllerAdvice's and thus the last one called by Spring's ordering sets the header and footer with the net effect that the header and footer remain static.
Via documentation Spring should support and my understanding is that only the ControllerAdvice for the rest method residing within that mapped controller should be called. So I have to conclude that I have set up something wrong. I am using JavaConfig and look forward to hearing from you guys!
You should use assignableTypes:
#ControllerAdvice(assignableTypes = AController.class)
public class AControllerAdvice {
#ModelAttribute
public void addModelInformation(Model model){
//controller specific model information for header and footer added here
}
}
You should pass the config classes to #ControllerAdvice's basePackageClasses not controller classes.
Assume you have Configuration named with ConfigClass
#Configuration
public class ConfigClass {
#Bean
public AController controllerA() {
....
}
... // your controllers to be weaved
}
Then you should setup advice with
#ControllerAdvice(basePackageClasses = ConfigClass.class)

Categories