Creating unique instances in spring mvc 3 parent Controller - java

I'm developing a web app using the Spring 3 framework.
So, I have the next hierachy level in my controllers package:
#Controller
public class BaseController {
#Autowired
#Qualifier("problemService")
protected ProblemService problemservice;
#Autowired
#Qualifier("codeService")
protected CodeService codeservice;
#Autowired
#Qualifier("userService")
protected UserService userservice;
#Autowired
#Qualifier("sessionRegistry")
protected SessionRegistry session;
.....
}
with children
#Controller
public class CodeController extends BaseController{
...
}
#Controller
public class ProblemController extends BaseController{
...
}
What i want is all these service of BaseController available to the children, but more like static resources, that is, all children share an unique instance of the father's services, and not a new instance of each as inheritance does.
In that way, I tried this for each resource in BaseController:
#Autowired
#Qualifier("problemService")
protected static ProblemService problemservice;
but Spring throws a NullPointerException.
So, is my idea at least correct? I mean, i do want to do what i said, but i dont know if it is a good approach at least.

Related

JAVA - Can I delete #Autowire directly?

after my teammates merged her changes (implements #EnableFeignClients for our SpringBootApplication and created some feign clients, properties and configs from the main branch), when boot the application it will pop up the The dependencies of some of the beans in the application context from a cycle: xxx
To resolve this issue I deleted some #Autowired from some involved controller/service classes and make them private and then the application can be boot successfully:
before my change:
#Autowired
MyUtil myUtil; //#Component
#Autowired
MyConfig myConfig; //#Component
#Autowired
MyApi myApi; //Interface class
public void myFunction(){
String id = myUtil.getId();
String name = myConfig.getNameById(id);
myApi.sendInfo(id, name);
}
after my change:
private MyUtil myUtil; //#Component
private MyConfig myConfig; //#Component
private MyApi myApi; //#Component
public void myFunction(){
String id = myUtil.getId();
String name = myConfig.getNameById(id);
myApi.sendInfo(id, name);
}
Spring version:
<groupID>org.springframework.boot</groupID>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>
and here are my concerns:
Will there be any impact after my changes (functional, performance, etc.)?
In my case (or in most scenarios in the future development), should i use #Autowired? When need to? When doesn't need to?
TL DR. You cannot delete #Autowired directly.
#Autowired is used by Spring in order to do dependency injection ( I know this is a fancy word)
#Autowired
ChickenService chickenService
#Autowired is almost equivalent to ChickenService chickenService = new ChickenService();
After your change,private MyConfig myConfig; //#Component myConfig will be null and therefore you introduced a bug.
Suppose that you have an EggService
#Service
public class ChickenService {
#Autowired
private EggService eggService;
}
The chicken holds a reference to the egg
#Service
public class EggService {
#Autowired
private ChickenService;
}
Now you have a chicken and egg problem.
https://www.baeldung.com/circular-dependencies-in-spring
#Autowired help the spring to find where it should inject classes.
The impact is that spring will not create objects of the classes where you removed the annotation.
Additional way to create objects in spring are with setter or constructor injection.
Example of constructor injection will be something like:
public YourClassName(MyUtil myUtil, MyConfig myConfig, MyApi myApi){
this.myUtil = myUtil;
this.myConfig = myConfig;
this.myApi = myApi;
}
I think also good idea as well to check why #Autowired not working. Can you provide full error? Does your class annotated with #Service or something

Null pointer exception thrown when operating on service that should be Autowired [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 5 years ago.
I've created a utilities class that will house some functionality that doesn't belong in standard controllers, such as syncing and ingesting API data. I have a very simple Repository class that extends CrudRepository:
//TransactionCategoryRepository.java
#Repository
public interface TransactionCategoryRepository extends CrudRepository<TransactionCategory, Integer> {
}
Then I have a service class which is also very straightforward at the moment:
//TransactionCategoryService.java
#Service
public class TransactionCategoryService {
private TransactionCategoryRepository transactionCategoryRepository;
#Autowired
public TransactionCategoryService(TransactionCategoryRepository repository) {
this.transactionCategoryRepository = repository;
}
public void saveTransactionCategory(TransactionCategory transactionCategory) {
transactionCategoryRepository.save(transactionCategory);
}
My utilities class leverages the TransactionCategoryService and I've attempted to include it with #Autowired:
//Utilities.java
#Controller
public class PlaidUtilities {
private Logger logger = LoggerFactory.getLogger(PlaidUtilities.class.getSimpleName());
private PlaidClient mPlaidClient;
#Autowired
TransactionCategoryService mTransactionCategoryService;
#Autowired
TransactionRepository mTransactionCategoryRepository;
....
When I use mTransactionCategoryService to save a new entity, I get the null pointer exception. IntelliJ previously threw warnings on my #Autowired annotations that the member classes needed to be declared in spring beans. Adding the #Controller annotation made these go away, though I'm not sure if that is the right thing to do; I tried this because this is the only difference between this class and another class which #Autowires in exactly the same way but does not have this problem.
The other classes that use Autowired in this way are in a package called controllers which is in the root directory. This Utilities class is in a package called util which is also in the root directory.
What have I done wrong in this setup/configuration?
You forget to autowire the repository in your service layer.
//TransactionCategoryService.java
#Service
public class TransactionCategoryService {
#Autowired //MISSING THIS
private TransactionCategoryRepository transactionCategoryRepository;
#Autowired
public TransactionCategoryService(TransactionCategoryRepository repository) {
this.transactionCategoryRepository = repository;
}
public void saveTransactionCategory(TransactionCategory transactionCategory) {
transactionCategoryRepository.save(transactionCategory);
}

#Autowired attribute that needs a parameter to be instantiated

I'm new to spring boot, and I need to know how to use #autowired in an attribute that needs parameters to be instantiated.
Please bear in mind the following illustrative situation. It would be something like this:
public class MyClassA{
public SpecificClass myMethod(){
//some logic
}
}
public class MyClassB extends MyClassA{
#Autowired
MyComponent myComponent (myMethod()); //here is my doubt, because my component needs a parameter to be built
}
#Component
public class MyComponent{
public MyComponent(SpecificClass foo){
this.foo=foo;
}
That's not really proper design if your intention is to work with dependency injection. There shouldn't be a direct dependency to the superclass' method like that. Injecting the dependencies indirectly as you're supposed to do would result in something like the following
public class MyClassB extends MyClassA {
#Autowired
private MyComponent myComponent;
}
#Configuration
public class SomeConfig {
#Bean
#Autowired
public MyComponent createComponent(SpecificClass foo) {
// SpecificClass is also injected, providing another layer of indirection
return new MyComponent(foo);
}
}
#Autowired only tells Spring to inject a component into a constructor, field, or method parameter. The injected component is instantiated by the bean container before that. I assume what you are looking for is a way to create MyComponent in such a way that it also receives a Spring Bean.
In your example you could achieve this with the following
#Configuration
public class MyClassA{
#Bean //the bean would have the name 'myMethod', so maybe change that
public SpecificClass myMethod(){
//some logic
}
}
//this needs to be a component, service, ...
#Component
public class MyClassB {
#Autowired
MyComponent myComponent;
}
#Component
public class MyComponent{
#Autowired //Spring wires the Bean 'myMethod' in here, autowired is not needed in the latest Spring Versions
public MyComponent(SpecificClass foo){
this.foo=foo;
}
}
This is a basic Spring question, and not specific to Spring Boot. To better understand wiring you can take a look at the Spring 4 Framework Reference Documentation.

Spring Autowired gwt RemoteServiceServlet implement class is null

I have two gwt RemoteServiceServlet in my project which has use GWT framework as below
#RemoteServiceRelativePath("AuthService")
public interface AuthService extends RemoteService {
}
public class AuthServiceImpl extends RemoteServiceServlet implements AuthService
{
#Autowired
private StoredService storeService;
}
#RemoteServiceRelativePath("webService")
public interface WebService extends RemoteService
{
}
public class WebServiceImpl extends RemoteServiceServlet implements WebService
{
#Autowired
private LogService logService;
}
Both the #Autowired of StoreService and LogService are work. But when I try to autowired WebService in AuthService, it will be null at runtime.
The interface and implements are in different package, which is com.test.client.service and com.test.server.service respectively.
I have confirm my SpringApplication-context.xml has below declare:
<context:component-scan
base-package="com.test.client.service, com.test.server.service
>
Also try to add #Service, #Component or #Configurable on WebServiceImpl, but still not works.
Override the init() of WebServiceImpl is also not work either.
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
WebApplicationContextUtils.getWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
}
Is that because the RemoteService cause the autowired not work correctly?
Any help is appreciated.
Thanks
I use the following to integrate GWT-RPC into Spring. I wrote it 6 years ago and never saw the need to change it. It is old-school and it works. It models GWT-RPC services as Spring MVC controllers, which they are. You can autowire anything into those controllers.
I mentioned it in a different answer, so I'll just post a link: https://stackoverflow.com/a/30838630/4982193

Problems with Injection (Using vaadin)

I am newbie with EJB and Injections...
I am currently using Vaadin framework with CDI
I have been trying to using injection but i have not could do it...
In my Vaadin UI class MyVaadinUI i have tried...
CDIUI("")
#SuppressWarnings("serial")
public class MyVaadinUI extends UI {
#EJB
UserController userController;
#Override
protected void init(VaadinRequest request) {
System.err.println("desde controller "+userController.getAll().size());
}
}
UserController
#Stateless
public class UserController {
#EJB
IUserDAO userDao;
public List<User> getAll() {
return userDao.findAll();
}
}
and it works!!
but when I do not inject UserController, it does not work... In other words when I instance the class UserController the injection in this class does not work...
Code does not work
CDIUI("")
#SuppressWarnings("serial")
public class MyVaadinUI extends UI {
#Override
protected void init(VaadinRequest request) {
UserController userController = new UserController();
System.err.println("desde controller "+userController.getAll().size());
}
}
Somebody can explain me why?
Thanks
Nicolas
Only in injected objects will have its dependencies injected. If you create an object with new all field having #inject, #ejb or #resource will not be injected.
In your case you create UserController like this:
UserController userController = new UserController();
and so this field will not be injected:
#EJB
IUserDAO userDao;
And therefore getAll() will throw a NullPointerException.
I use vaadin and cdi for projects. I'd recommend to use injection for almost everything or not at all. I inject my uis, views, own components... (and do not create them with new) so it is possible to inject ejb beans or other things into them. If you are using it only sometimes you are ending up with am mixture of injection and normal object creation and will have to pass around injected objects to other object you instantiated yourself. In another project of mine this happened and got really problematic for future changed in the code.

Categories

Resources