#Autowired Request processing failed; nested exception is java.lang.NullPointerException - java

I'm trying to de-couple dependencies from an existing Spring app by using
Spring #Bean in the config class, and #Autowired in the class that utilises it.
Below is the main configuration class:
#Configuration
#ComponentScan(basePackages = {"com.example"})
#EnableWebMvc
public class DataLoadConfig extends WebMvcConfigurerAdapter {
#Bean
ActivitiesFeed activityFeed() {
HashMap<Integer, Object> temp = new HashMap<Integer, Object>();
return new ActivitiesFeed(temp);
}
...
Here is how the dependency is being used:
public class ActivitiesLoad {
// ADDED
#Autowired
ActivitiesFeed activityFeed;
public ActivitiesLoad(String loadType, int personCode, String outputFilter, int outputNumber) {
...
// REMOVED - this approach didn't throw any errors though
// HashMap<Integer, Object> temp = new HashMap<Integer, Object>();
// ActivitiesFeed activityFeed = new ActivitiesFeed(temp);
// This dependency is now #Autowired in
feed = activityFeed.getActivities();
...
But, I'm now getting the following error:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/DataLoads] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at ac.uk.strath.t4.dataload.pure.activities.ActivitiesLoad.<init>(ActivitiesLoad.java:66)
at ac.uk.strath.t4.dataload.controller.DataLoadController.pureActivities(DataLoadController.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
...
See the original intialisation code, this run without any issue so I know the dependency works but wondering whether I've implemented the injection wrong.
By the way, I don't own the ActivitiesFeed source so I cannot attach any #Components like annotation to the class, so have opted to put it into the app config class (DataLoadConfig) as #Bean.
Note: I've also tried putting the ActivitiesLoad constructor code into a run(...) method, just encase it was an issue with the fact I am trying to access a dependency from within the constructor, but it just gave me the same error. Ideally I'd prefer to leave the code within the constructor for now as it's someone else's code and don't want to risk breaking too much at this stage :)
UPDATE
I've tried to add a #PostConstruct method but just the same issue. I then made the activityFeed property private as I'd seen in examples, but same.
public class ActivitiesLoad {
#Autowired
private ActivitiesFeed activityFeed;
private String loadType;
private int personCode;
private String outputFilter;
private int outputNumber;
public ActivitiesLoad(String loadType, int personCode, String outputFilter, int outputNumber) {
log.debug("Starting pure activities data load");
this.loadType = loadType;
this.personCode = personCode;
this.outputFilter = outputFilter;
this.outputNumber = outputNumber;
}
#PostConstruct
public void init() {
log.debug("Starting pure activities data load #PostConstruct");
log.debug(activityFeed); // outputs: null
...
UPDATE 2
Here I'm leaving the dependency out of the constructor, instead putting it into it's own init method and calling that after creating the ActivityLoad instance. However, I'm still seeing the issue with NullPointerException.
The instantiating of ActivityLoad (now with init method that is called after the instance is created):
...
ActivitiesLoad activitiesLoad = new ActivitiesLoad();
activitiesLoad.init(loadType, personCode, typeFilter, outputLimit);
...
Here is the ActivityLoad class containing the new method
#Component
public class ActivitiesLoad {
#Autowired
private ActivitiesFeed activityFeed;
public void init(String loadType, int personCode, String outputFilter, int outputNumber) {
log.debug(activityFeed); // outputs: null

You need to keep in mind 2 things.
i) If you create a class instance by using the new keyword , then the specific instance won't be managed by Spring , which means it wont autowire the beans you are requesting in the chain. So from the first place , ActivitiesFeed activityFeed will be null always inside the ActivitiesLoad instances, which are getting spawned by using new ActivitiesLoad(...)
ii) The second point is regarding your update. As proposed by the other answers , you were trying to invoke a method by an injected bean inside the Class Constructor. This is not working in any DI framework , because the constructor is meant to be used only for initializing the field references and not invoking them. That's why you need the #PostConstruct, which gets invoked by the Spring Container after the bean initialization / constructor has finished successfully , thus the bean reference , will get a proper instance.
So this leaves you with 2 possible options:
a. Maintain the context , by autowiring the ActivitiesLoad properly as Prototype and pass the required state.
b. Refactor the ActivitiesLoad to do not keep context at all , change the constructor to keep the default one and implement all the logic along with the required params(context) inside this method. Then you can autowire this bean in the controller by just using #Autowire

ActivitiesLoad should be a Spring component to be able to autowire bean in it.
Try to make it a spring component with one of this i.e. #Component #Service
And you still will need to use #PostConstruct as it was designed directly for such cases.

This is happening because you did not load the component in the context.
Your question is missing some infos, but in case you are running a standalone application or a spring boot web app, you should have a part of logic which explicitly says "please load DataLoadConfig" in the context.
I will refer to a link to avoid to re-write your code : https://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
the 4th code snippet is what I assume you missing, which actually will cause the issue you are facing. The component is not in the context so when you autowire it you get a nullpointer.
Make sure in you main the component is there via following the example.

This has already been answered, but I found this article also good for explaining why Autowired dependencies are null:
https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/

Related

What are the differences between #PostConstruct and Autowired Constructor?

I'd like to know what are the differences between the two examples below. One is using #PostConstruct init method to ensure autowired bean is initialized, and the other one is using constructor with #Autowired to ensure any needed beans are initialized.
I am curious
If there is any functional differences
If one is better than the other, why? (Maybe initialization speed, less call stack, less memory usage, etc.)
Thanks in advance :)
#Component
public class MyBean {
#Autowired
public MyBean(SomeOtherBean someOtherBean) {
...
}
...
}
#Component
public class MyBean {
#Autowired
private SomeOtherBean someOtherBean;
#PostConstruct
public void init() {
...
}
...
}
in the first case, if I'm going to use MyBean.class without in a none Spring framework project I'll need to pass SomeOtherBean so I know the object is created correctly. but in the second case, I would have done new MyBean() and then after I'll get NullPointerException when using it because the object depends on SomeOtherBean.
so the first one is much cleaner.
Autowired constructor will not create the instance unless it has someotherbean available, that means it fast fails and will not even try to create the instance before someotherbean is available. If you do not have an autowired constructor it will create the instance and the bean is available in container, then inject the someotherbean when it is available. Whatever inside the #PostConstruct annotated method will execute after the instance is created. Please read the following will get better idea
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core

how to initialize a bean in spring container once and use it everywhere

actually i'm using spring for developing a web application, the problem i'm facing is that i'm initializing a bean as soon as the spring container is getting loaded, now i have to use that bean in different parts of my program.
constraints that i have
1. i can get application context everywhere and get that bean but according to my problem i should get that bean without writing that redundant code again and again.so is there any way by which i can initialize that bean and use it directly everywhere in my program.
If you already initialized your bean you can get access to it via #Autowired from each Component in your Spring Application.
private SomeClass myBean;
#Autowired
public void setMyBean(SomeClass myBean){
this.myBean =myBean;
}
Or just:
#Autowired
private SomeClass myBean;
I prefer the first method, looks fancier in my eyes.
You should not get your bean from the context directly, instead you should #Autowire them and let Spring inject it for you.
Here’s an example of two dependencies injected via constructor:
#Component
public class Car {
private final Engine engine;
private final Transmission transmission;
#Autowired
public Car(Engine engine, Transmission transmission) {
this.engine = engine;
this.transmission = transmission;
}
}
Note that your class must be a Spring Component itself in order for the injection to occur.
There are actually three types of dependency injection in Spring: constructor, field and setter injection. Spring team recommends using the constructor based approach, and this post brings very nice arguments to this point: https://blog.marcnuri.com/field-injection-is-not-recommended/
You can refer to this link for more information on constructor-based injection: https://www.baeldung.com/constructor-injection-in-spring

In spring, is there a way to autowire the first bean?

In the example below, is there a way to avoid doing a context.getBean()? All the other beans subsequently used by the testService get autowired. (It is a console application)
public class Test {
private static ITestService testService;
private static ApplicationContext context;
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext(
new String[]{"/META-INF/spring/app-context.xml"});
ITestService testService = context.getBean(ITestService.class);
}
}
I tried adding autowire annotation to ApplicationContext, but it didnt work. Besides how does it know where my app-context.xml is located if I autowire it?
Update: I found what I needed over here
Right, you're missing out a few details here.
Below is a short explanation of how Spring works.
1- The application context is loaded somehow (we will get there soon).
2- After loaded, app context will initialize/create all beans defined. Here is when beans get injected as dependencies. After this Whenever you get a bean back from the app context, that bean is all initialized and ready to go with all the dependencies in place (considering everything went fine).
RE the first step, there are a few way to automate the Spring initialization.
One way is what you are doing, explicitly instantiating one. Other way could be via a context listener in case you're in a web environment, or maybe with the #RunWith. (You can find more here)
In your case, I believe you are looking for using Spring in a (Unit?!?) test environment so you are looking for something like
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTest {
#Autowired
private ApplicationContext applicationContext;
// class body...
}
further details here
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#testing
You cannot call beans without initializing the application context first.
Secondly in your case Test class should be bean itself to be managed by spring then to autowire ITestService. The purpose of Application context as a container is to manage the bean lifecycle so u need to initialize it first by ClassPathXmlApplicationContextand then it will initialize all beans declared by you in ur xml file. About avoiding the getBean method if you are using servlets for creating web app you can avoid getBean. If not you should handle it manually.
I agree with what #Desorder has said. When I started working with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration, I used to get my test cases working. But it took me some time to understand how these two are working internally and their default configurations.
If you would like to take some different approach and would like to try without #RunWith and #ContextConfiguration, take a look at the link - TUTORIAL: JUNIT #RULE. With this, you will be very clear which spring xml file locations are provided.

Autowire of prototype bean into prototype bean?

I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.

AnnotationConfigApplicationContext has not been refreshed yet

I am developing a spring MVC application. When I try to use AnnotationConfigApplicationContext in my controller class I am getting the following error. I have no idea what this statement exactly means.
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
Error Message -->
java.lang.IllegalStateException:org.springframework.context.annotation.AnnotationConfigApplicationContext#116b3c0 has not been refreshed yet
Can someone explain me what went wrong here ? I am using Spring 4.0.1.. I am new to spring mvc.
When you are creating a new instance of an ApplicationContext (regardless which type) you are basically creating new instances of each and every bean configured in that ApplicationContext. That is nice the first time, it might work the second and depending on the amount of beans, the type of beans will crash after that. As the context will never be destroy (until the app crashed and is restarted) you will run into possible memory issues, performance issues, strange transactional problems etc.
A general rule of thumb is to never construct a new instance of an ApplicationContext but to use dependency injection instead.
If you really want access to the ApplicationContext put a field of that type in your controller and put #Autowired on it.
#Controller
public class MyController {
#Autowired
private ApplicationContext ctx;
….
}
Then you can do a lookup for the bean you need in the method. This can be handy if you use the ApplicationContext as a factory for your beans. If all the beans you need are singletons it is better to simply inject the bean you need.
#Controller
public class MyController {
#Autowired
private MappingFileGenerator mfg ;
….
}
Now Spring will inject the MappingFileGenerator and it is available for use in your methods. No need to create a new instance of an ApplicationContext.
More information is in the Spring Reference Guide.
#M.Deinum's comment will get quite a few more upvotes.
Think of creating a new ApplicationContext as instantiating a new (instance of an) application. Do you want to do that every time this (or any other method in said application) is called? No, you don't.
I'm guessing you think you do because you need access to your ApplicationContext in this method. To do that - i.e. to get access to the running application context (rather than creating a new one), you want to do
#Controller // or #Service / #Component / ... : tells Spring that this is a bean, and to inject the specified dependencies
class YourClass {
#Autowired // tells Spring that this object is a dependency should should be injected
ApplicationContext ctx;
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping) {
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
The key here is the Autowired annotation, which tells Spring to inject the annotated object as a dependency.
I highly suggest following the links I've included (for starters), as what you're doing here suggests pretty strongly that you haven't wrapped your head around what DI is and does for you, and until you do, using it is likely to be counterproductive toward it's own ends for you.
In case it helps someone, i was having this issue on a new URL Mapping added to a gradle project, i was missing the first slash of the url and that causing this "illegalstate not refreshed yet" on my tests

Categories

Resources