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>
Related
Hi I am new to spring technology.
I have a class called Employee as follows which has 2 constructors with different argument types.
I am able to inject values to one of the constructors as described in the xml file.
May I know how to inject value to other constructor as well using constructor injection.
I tried various possibilities but unable to figure out how to do it.
public class Employee {
private int eno ;
private String name ;
private double salary ;
private String desig ;
public Employee(int eno, String name) {
this.eno = eno;
this.name = name;
}
public Employee(double salary, String desig) {
this.salary = salary;
this.desig = desig;
}
public void showInjectedValues() {
System.out.println("Eno : " + eno);
System.out.println("name : " + name);
System.out.println("salary : " + salary);
System.out.println("desig : " + desig);
}
}
Trying to inject with spring.xml and the Java class for Injection is as follows:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class InjectionTest {
static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springconfig.xml");
public static void main(String[] args) {
Employee employee = (Employee) applicationContext.getBean("employee");
employee.showInjectedValues();
}
}
applicationContext.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-3.2.xsd">
<bean id="employee" class="com.vidvaan.spring.Employee">
<constructor-arg value="2000" index="0" type="double" />
<constructor-arg value="team lead" index="1"
type="java.lang.String" />
</bean>
</beans>
Well, that is not possible. What you are asking is
call two constructors to create one object.
This doesn't make any sense. (Just read the above line again).
You can always place multiple objects of the same class on the spring context, calling a different constructor in each case.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-3.2.xsd">
<bean id="otherEmployee" class="com.vidvaan.spring.Employee">
<constructor-arg value="100" index="0" type="int" />
<constructor-arg value="team lead" index="1"
type="java.lang.String" />
</bean>
<bean id="employee" class="com.vidvaan.spring.Employee">
<constructor-arg value="2000" index="0" type="double" />
<constructor-arg value="team lead" index="1"
type="java.lang.String" />
</bean>
</beans>
what you can do is create a constructor with all four arguments and pass null for objects which you don't want to initilize
or You can have a constructor with some arguments and others you can set through Field Injection <property name = ...>
You can create a another bean like this for different arguments:
<bean id = "employeeBean" class = "com.vidvaan.spring.Employee">
<constructor-arg type = "int" value = "2001"/>
<constructor-arg type = "java.lang.String" value = "Employee"/>
</bean>
#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());
}
}
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>
So, I read that the best place to put the #Transactional annotation was outside the DAO classes which contains the db access methods, like in a service class which use those methods.
Now, the problem is, once I've already remove this annotations from the DAO classes, I launch the DAO test methods and the aforementioned exception raised. I put back the annotations in the DAO classes and this exception doesn't raises anymore.
Then my question is: how can I clear my DAOs of this annotations and still have my tests working?
Let's add some code:
DAO class
public class UserDAO extends IDAO implements IUserDAO {
#Override
//#Transactional(readOnly=true)
public User get(int idUser) {
return (User) currentSession().get(User.class,idUser);
}}
IDAO Class
public abstract class IDAO {
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session currentSession()
{
return sessionFactory.getCurrentSession();
}
}
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/app-context.xml" })
public class UserDAOTest extends AbstractJUnit4SpringContextTests {
#Autowired
private IUserDAO userDAO;
#Test
public void testGetUser() throws Exception {
User user = userDAO.get(2);
assertNotNull(user);
}
}
app-config
<?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"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/waldb" />
<property name="username" value="user" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.wal.serverside.persistence.domain.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="userDAO" class="com.wal.serverside.persistence.DAO.UserDAO">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.wal.serverside.persistence" />
</beans>
Gosh, how much stupid can I be?
My test class didn't extend from AbstractTransactionalJUnit4SpringContextTests, so there were nor transaction nor session inside my tests.
This fixed it all:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/app-context.xml" })
#TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
#Transactional
public class UserDAOTest extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
private IUserDAO userDAO;
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
#Test
public void testGetUser() throws Exception {
User user = userDAO.get(2);
assertNotNull(user);
}
}
Try to put not only #Transactional annotaition on your test class but also #TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false). Where you explicitly set the name of the transaction manager that you have defined in xml.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/app-context.xml" })
#TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
#Transactional(propagation=Propagation.REQUIRED, rollbackFor={Exception.class})
public class UserDAOTest {
...
}
Also transaction will not work if you explicitly create the application context in your test method and then get the bean from it:
ApplicationContext appContext = new ClassPathXmlApplicationContext(...);
SomeDAO someDAO = (SomeDAO) appContext.getBean(...);
instad of inhjecting it.
But I see this is not your case.
I need help making AOP work. What am I missing here?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.0.xsd">
<bean id="duke" class="com.tutorial.springidol.Singer">
<constructor-arg value="Duke"/>
<constructor-arg>
<bean class="com.tutorial.springidol.Song">
<property name="title" value="ABC"/>
</bean>
</constructor-arg>
</bean>
<bean id="audienceAdvice" class="com.tutorial.advice.AudienceAdvice">
<property name="audience">
<bean class="com.tutorial.springidol.Audience"/>
</property>
</bean>
<bean id="audienceAdvisor"
class="org.springframework.
aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="audienceAdvice"/>
<property name="pattern" value=".*perform"/>
</bean>
</beans>
AudienceAdvice.java
public class AudienceAdvice implements MethodBeforeAdvice,
AfterReturningAdvice {
#Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
audience.takeSeats();
audience.turnOffCellphones();
}
#Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
audience.applaud();
}
private Audience audience;
public void setAudience(Audience audience) {
this.audience = audience;
}
}
The AOP does not work but the target executes though.
You've declared the target bean and the advice, but by default Spring doesn't know to actually apply the advice to the target.
You need to run an Autoproxy.
One way to do this:
<!-- Autoproxy -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>duke</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>audienceAdvisor</value>
</list>
</property>
</bean>