#required annotation usage. I tried giving this above setter method and tried to find the bean from context without setting this dependency. I got the object with the dependency is set null, my expectation was spring will throw some exception. Please guide me where I am doing wrong?
#Required to make it mandatory that the dependency has to be injected
Let us example:
We need to use RequiredAnnotationPostProcessor which checks whether #Required dependencies have been injected or not
public class BankService {
private CustomerService customerService;
private BillPaymentService billPaymentService;
#Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
#Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}
}
The configuration is like
<bean id="custService" class="xml.CustomerServiceImpl" />
<bean id="billingService" class="xml.BillPaymentServiceImpl" />
<bean id="bankService" class="xml.BankServiceImpl">
<property name="customerService" ref="custService" />
<property name="billPaymentService" ref="billingService" />
</bean>
<bean class=”o.s.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
If we don’t set both the properties we will get an error for the BankService configuration as both are #Required.
I hope this helps!!
Same anwer by bmt - just adding here what i did to verify.
package com.requiredAnnotation;
import org.springframework.beans.factory.annotation.Required;
public class BankService {
private CustomerService customerService;
private BillPaymentService billPaymentService;
#Required
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
#Required
public void setBillPaymentService(BillPaymentService billPaymentService) {
this.billPaymentService = billPaymentService;
}
public BillPaymentService getBillPaymentService() {
return billPaymentService;
}
public CustomerService getCustomerService() {
return customerService;
}
}
package com.requiredAnnotation;
public class CustomerService {
}
package com.requiredAnnotation;
public class BillPaymentService {
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="customerService" class="com.requiredAnnotation.CustomerService" />
<bean id="billPaymentService" class="com.requiredAnnotation.BillPaymentService" />
<bean id="bankService" class="com.requiredAnnotation.BankService">
<property name="customerService" ref="customerService" />
<!-- <property name="billPaymentService" ref="billPaymentService" /> -->
</bean>
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
</beans>
package com.requiredAnnotation;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:com/requiredAnnotation/beans-required.xml");
BankService bankService = applicationContext.getBean(BankService.class);
System.out.println("bankService got.");
System.out.println("getCustomerService - " + bankService.getCustomerService());
System.out.println("getBillPaymentService - " + bankService.getBillPaymentService());
}
}
Related
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I have the below code in my SpringBoot project which is throwing NPE at a specific line mentioned.
Exception in thread "main" java.lang.NullPointerException
at com.temp.controller.Controller.triggerJob(Controller.java:15)
at com.temp.Application.main(Application.java:19)
Application.java
#Configuration
#SpringBootApplication
#ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller();
controller.triggerJob();
}
}
Controller.java
#Controller
public class Controller {
#Autowired
private Service Service;
public void triggerJob() {
Service.selectRecords();
}
}
Service.selectRecords(); is where the NPE is being thrown
Service.java
public interface Service {
List<VO> selectRecords();
}
ServiceImpl.java
#Service
public class ServiceImpl implements Service {
#Autowired
private Dao dao;
#Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<util:properties id="configProperties"
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<context:property-placeholder
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<bean id="crypt" class="com.temp.util.MyUtil">
<property name="userId" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="key" value="123456789012345678901234"></property>
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${connection}" />
<property name="username" value="#{crypt.userId}" />
<property name="password" value="#{crypt.password}" />
</bean>
<bean id="namedJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="datasource" />
</bean>
</beans>
I have a similar project like this and have compared the configuration of both and they are the same except for 2 things.
The spring boot starter version is 2.4.2 for this project and 1.5.3 for the other project.
Java version is 11 for this project and 1.8 for the other project.
Not sure where I'm going wrong.
Am I missing something? Kindly help.
You are creating new instance
Controller controller = new Controller();
manually and this instance is not in Spring context. Therefore, the injected (autowired) instance of Service is null. #Autowired only works when the instance exists in Spring context.
The best approach is to keep Controller testable is injection via constructor:
#Configuration
#SpringBootApplication
#ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller(new ServiceImpl(new DaoImpl()));
controller.triggerJob();
}
}
Inject the instance via constructor:
#Controller
public class Controller {
private final Service Service;
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
And also inject the Dao dependency via constructor:
#Service
public class ServiceImpl implements Service {
private final Dao dao;
public ServiceImpl(final Dao dao) {
this.dao = dao;
}
#Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
For Spring version above 4.3, #Autowired could be omitted from top of the constructor, Spring scans the injection automatically and injects the dependency via constructor.
For Spring version below 4.3, add #Autowired on top of constructors i.e.:
#Controller
public class Controller {
private final Service Service;
#Autowired
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
I'm currently doing novice tutorial about Spring, it seems i have everything the same like person who makes this tutorial but i keep getting errors NullPointerException , could someone help me?
There is section in my xml that is commented if you uncomment it, program will work. But without it, when I try to use autowire byName it doesn't work.
Main Class:
public class MainSpring {
public static void main(String[] args) {
ApplicationContext context= new ClassPathXmlApplicationContext("konfiguracja.xml");
SomeBean bean = context.getBean("SomeBean",SomeBean.class);
System.out.println(bean.getInjectedBean1().getName());
System.out.println(bean.getInjectedBean2().getName());
}
}
InjectedBean Class
package springTutorial;
public class InjectedBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SomeBean Class
import org.springframework.beans.factory.annotation.Autowired;
public class SomeBean {
private InjectedBean InjectedBean1;
private InjectedBean InjectedBean2;
public InjectedBean getInjectedBean1() {
return InjectedBean1;
}
public void setInjectedBean1(InjectedBean injectedBean1) {
this.InjectedBean1 = injectedBean1;
}
public InjectedBean getInjectedBean2() {
return InjectedBean2;
}
public void setInjectedBean2(InjectedBean injectedBean2) {
this.InjectedBean2 = injectedBean2;
}
}
Configuration.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="InjectedBean1" class="springTutorial.InjectedBean" >
<property name="name" value="asasa" >
</property>
</bean>
<bean id="InjectedBean2" class="springTutorial.InjectedBean" >
<property name="name" value="vbvb">
</property>
</bean>
<bean id="SomeBean" class="springTutorial.SomeBean" autowire="byName" >
<!-- <property name="injectedBean1"> -->
<!-- <ref bean="InjectedBean1"/> -->
<!-- </property> -->
<!-- <property name="injectedBean2"> -->
<!-- <ref bean="InjectedBean2"/> -->
<!-- </property> -->
</bean>
</beans>
As per Configuration.xml ; InjectedBean1,InjectedBean2 are not injected with any values.
So basically InjectedBean1 and InjectedBean2 are null.
On null you are trying for get Operation which is leading to null pointer exception.
Adding ref to InjectedBean1 and InjectedBean2 will solve problem.
<bean id="SomeBean" class="com.stackoverflow.SomeBean" autowire="byName">
<property name="injectedBean1">
<ref bean="inject1" />
</property>
<property name="injectedBean2">
<ref bean="inject2" />
</property>
</bean>
ABSTRACT:
I have some initialisation operations executed in #PostConstruct of #Service ServiceInitialiserFacsimile. Those operations include a call to a method after whose execution an Aspect (DoAttionalStuffAspect) is applied.
The Aspect is instantied through aspectOf, so it is handled by the Spring Container, but unfortunately its dependencies are injected AFTER the execution of ServiceInitialiserFacsimile #PostConstruct, resulting in a NullPointerException.
How can I tell the Spring Container to inject first the fields in the Aspect and then instantiate the ServiceInitialiserFacsimile ?
I tried with an Autowired constructor for the aspect, but I think in the end AspectJ requires the no-arg constructor, so it was no help
CODE
This is a Sample I created in order to reproduce the issue I have in a much more complicated app. Here is the project if you want to check it out. https://github.com/alessiop86/spring3-mvc-maven-xml-hello-world
Code below:
This is the initialisation class:
#Component
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
This is the service with some custom logic that requires to be initialised by the ServiceInitialiserFacsimile #PostConstruct:
#Service
public class SampleService {
public void init() {
System.out.println("do some stuff");
try {
execute();
}
catch(Exception e) {
System.err.println("I do not want to block to whole framework initialisation");
}
}
#DoAdditionalStuff
public void execute() {
System.out.println("Phase 1");
}
}
This is the annotation I use in the aspect definition
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface DoAdditionalStuff {
}
This is the aspect
#Aspect
public class AdditionalStuffAspect {
private AdditionalStuffService service;
public AdditionalStuffService getService() {
return service;
}
public void setService(AdditionalStuffService service) {
this.service = service;
}
#Pointcut(value="execution(public * *(..))")
private void anyPublicMethod() { }
#AfterReturning("anyPublicMethod() && #annotation(doAdditionalStuff)")
public void afterReturning(JoinPoint jointPoint, DoAdditionalStuff doAdditionalStuff) {
System.out.println(jointPoint);
service.doStuff();
}
}
This is the service that is created, but not yet instantiated when the aspect is run:
#Service
public class AdditionalStuffService {
public void doStuff() {
System.out.println("Phase2: additional stuff");
}
}
Spring context xml configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="initialisation.mess"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:annotation-driven/>
<bean class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
</beans>
I was able to enforce a dependency on the ServiceInitialiserFacsimile from the Aspect by setting an id in the xml:
<bean id="myAspect" class="initialisation.mess.aspects.AdditionalStuffAspect" factory-method="aspectOf">
<property name="service" ref="additionalStuffService" />
</bean>
and then specifying the dependency of ServiceInitialiserFacsimile from the spring managed AdditionalStuffAspect with a #DependsOn annotation:
#Component
#DependsOn("myAspect")
public class ServiceInitialiserFacsimile {
private final SampleService sampleService;
#Autowired
public ServiceInitialiserFacsimile(SampleService ss) {
this.sampleService = ss;
}
#PostConstruct
public void initialiseAllTheServices() {
this.sampleService.init();
}
}
I have this DAO:
#Transactional("transactionManager")
public class DAO{
public void save(String a){...}
}
I have this class:
public class test{
...
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void save(){
DAO.save("a");
DAO.save("b");
}
}
I want the "save" method to rollback when it throws an exception, but it doesn't seem to work when an exception occurs it does not rollback, what is the proper approach for this? All the other methods in the DAO are transactional. Is there a way I can override the transactional settings of the override?
EDIT:
I have updated to be, and it is still not working when throwing exception:
public class test{
...
public void save(){
Service.test(a,b);
}
}
public class Service{
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void testSave(object a, object b){
dao.updateEntry(a);
dao.updateEntry(b);
}
}
Remove the Transactional annotation from the Dao layer and place a Transactional annotation in your service layer. Take a look at my code:-
#Transactional
#Service
public class Service {
#Autowired
private Dao1 dao1;
#Autowired
private Dao2 dao2;
public Dao1 getDao1() {
return dao1;
}
public void setDao1(Dao1 dao1) {
this.dao1 = dao1;
}
public Dao2 getDao2() {
return dao2;
}
public void setDao2(Dao2 dao2) {
this.dao2 = dao2;
}
public void insertData(){
dao1.insert1();
dao2.insert2();
}
In above code, if dao2.insert2() fails then dao1.insert1() will rollback.
In case when you have multiple methods in service class with different transaction properties :
You can define the #Transactional annotation on your public methods with below rule:-
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings.
Link1: Transactional annotation on whole class + excluding a single method
Transaction support configuration setup:-
1) spring-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.concept" />
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
</beans>
I am attempting a java application that has two beans it gets through Spring, one retrieved by name and one autowired. Here is that code:
package firstspring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class FirstSpring
{
private final static Logger logger = LoggerFactory.getLogger(FirstSpring.class);
#Autowired
private Car currentCar;
public void setCurrentCar(Car car) { this.currentCar = car; }
public Car getCurrentCar() { return currentCar; }
private static void say(String message) { System.out.println(message); }
public static void main(String[] args)
{
FirstSpring firstSpring = new FirstSpring();
firstSpring.go();
}
public void go()
{
logger.info("here we go");
ApplicationContext appContext = new ClassPathXmlApplicationContext("/appContext.xml");
Car firstCar = (Car)appContext.getBean("firstCar");
say ("firstCar was " + firstCar.getColor());
say ("currentCar is " + currentCar.getColor());
}
}
and its configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<bean id="firstCar" class="firstspring.Car">
<property name="color" value="blue" />
<property name="doors" value="2" />
<property name="transmission" value="automatic" />
</bean>
<bean id="currentCar" class="firstspring.Car" >
<property name="color" value="red" />
<property name="doors" value="4" />
<property name="transmission" value="5-speed" />
</bean>
<bean id="firstSpring" class="firstspring.FirstSpring">
<property name="currentCar" ref="currentCar" />
</bean>
</beans>
And the Car class just to make it complete:
package firstspring;
public class Car
{
String color;
int doors;
String transmission;
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
public int getDoors() { return doors; }
public void setDoors(int doors) { this.doors = doors; }
public String getTransmission() { return transmission; }
public void setTransmission(String transmission) { this.transmission = transmission; }
}
I get a null pointer exception:
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#5e6458a6: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,firstCar,currentCar,firstSpring,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
Exception in thread "main" java.lang.NullPointerException
at firstspring.FirstSpring.go(FirstSpring.java:33)
at firstspring.FirstSpring.main(FirstSpring.java:23)
firstCar was blue
I've tried various other things -- putting 'byName' on the currentCar bean in the configuration, but I don't think that's necessary according to what documentation I've read. What am I missing here?
When you say new FirstSpring(), you're creating your own instance of that class which is outside of Spring's control, so Spring can't autowire it. Therefore when you get to currentCar.getColor(), currentCar is null. For this to work properly, you'd need to create your ApplicationContext in the main method, get the FirstSpring instance from Spring, and invoke go() on that instead of creating the object yourself.
In short, Spring cannot and will not manage (that is, autowire, initialize, destroy, etc.) any object that it didn't create itself.*
*Unless you're using AspectJ with bytecode weaving to accomplish this, but that's a rather advanced topic that you probably don't want to touch yet, unless you have other experience with AspectJ.