Null Pointer Exception while using jdbcTemplate in Spring 3.0 - spring

This is what I have tried so far.
DaoImpl.java
#Component
public class DaoImpl {
#Autowired
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public int getCircleCount() {
String sql = "select count(*) from circle";
return (Integer)getJdbcTemplate().queryForObject(sql, Integer.class); //throws NPE
//return getJdbcTemplate().queryForInt(sql);
}
}
spring.xml
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/db" />
<property name="initialSize" value="2"/>
<property name="maxTotal" value="5"/>
</bean>
But I'm getting Null Pointer Exception at return statement of getCircleCount().
I'm learning Spring JDBC. Please help.

The problem is that the datasource gets injected directly into the field, but the setter is never called.
You need to move the #Autowired annotation from the field to the setter like so.
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}

Related

Spring not roll back transaction if exception throws in the application

I developed the application using spring transactions and insert records in the table.
I'm explicitly throwing the exception in DAO class but spring is inserting the record into the table rather than roll back the transaction.
I have created the two applications as below . In Case 1 record is inserted into table even though exception is thrown . But In Case 2 no record is inserted and spring roll back the transaction successfully. Can you explain me the difference between these two applications.
Case 1:
Item.java
public class Item {
int itemNo;
String itemName;
String itemType;
String itemSize;
public int getItemNo() {
return itemNo;
}
public void setItemNo(int itemNo) {
this.itemNo = itemNo;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemType() {
return itemType;
}
public void setItemType(String itemType) {
this.itemType = itemType;
}
public String getItemSize() {
return itemSize;
}
public void setItemSize(String itemSize) {
this.itemSize = itemSize;
}
}
ItemDao
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
try{
itemDao.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ct = new ClassPathXmlApplicationContext("spring.xml");
ItemService itemService = ct.getBean("itemService", ItemService.class);
Item item = new Item();
item.setItemNo(1234);
item.setItemName("sofa");
item.setItemSize("4");
item.setItemType("furniture");
itemService.insert(item);
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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/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">
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<context:component-scan base-package="com.spring.springtransaction" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- MySQL DB DataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#locahost:1521:xe)))" />
<property name="username" value="system" />
<property name="password" value="system" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="itemService" class="com.spring.springtransaction.ItemService" />
</beans>
Case 2:
ItemService.java
#Service
public class ItemService {
#Autowired
ItemDao itemDao;
#Autowired
ItemManger itemManger;
#Transactional
public void insert(Item item){
try{
itemManger.insert(item);
}
catch(Exception e){
e.printStackTrace();
}
}
}
ItemManger.java
#Service
public class ItemManger {
#Autowired
ItemDao itemDao;
#Transactional
public void insert(Item item){
itemDao.insert(item);
}
}
ItemDao.java
#Service
public class ItemDao {
#Autowired
JdbcTemplate jdbcTemplate ;
void insert(Item item){
jdbcTemplate.update("insert into item_test(itemno, itemtype,itemsize,itemname) values (?,?,?,?)", new Object[]{item.getItemNo(),item.getItemType(),item.getItemSize(),item.getItemName()});
int a=2/0;
}
}
Annotate you ItemDao as #Repository instead of #Service
You should execute unit test with spring Transactional context instead of main , for example using TestNG:
#ContextConfiguration(classes = {ConfigurationClass.class})
#ActiveProfiles({"test"})
public class TestItemDAO extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private ItemDao dao;
#Test
public void testItemDao() {
dao.insert(item);
}
}
Remove the try block, you are trying to handle the exception so this is reason why RollbackException is not cutting the transaction stream.

Spring #Autowire retuning null while creating an object

I am new to this Spring and trying to learn it.
I am using basic auth jersey and using spring to inject my db props and instantiate the class. However I am getting null pointer exception when I try this with a REST call using postman.
Below is code snippet
AppContx.xml
<context:annotation-config />
<context:component-scan base-package="com.rest" />
<bean id="userDao" class="com.rest.dao.UserDao">
<property name="dataSource" ref="ds" />
</bean>
<bean id="ds" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/Weber" />
<property name="resourceRef" value="true" />
</bean>
Filter
#Provider
public class AuthenticationFilter implements ContainerRequestFilter {
/*ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IuserDao userDao = (IuserDao) ctx.getBean("userDao");*/
#Autowired
UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserDao getUserDao() {
return userDao;
}
if (userDao.getUSerForAuthentication(password, username) == 1) {
String userRole = "ADMIN";
if (rolesSet.contains(userRole)) {
isAllowed = true;
}
DAO
#Autowired
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
I am successfully able to inject DB properties to my data source using #Autowired but I am unable to instantiate the UserDao in my Filter class.
Thank You
Mark

Spring :: #Transactional not working

I am new to Spring and learning the transaction concepts. Unable to get the #Transactional to work.
Use Case:
Data insert of Employee and Employee details should rollback when getEmployee() throws RunTimeException. But the rollback is not happening.
I am using Oracle database 11g and spring 4.3.1.RELEASE. Below is the standalone java code am running.
Code
public static void main( String[] args )
{
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring-bean.xml");
ctx.registerShutdownHook();
Employee emp = new Employee("149518", "Mickey", "Mouse", "15 years", "tennis");
IEmployee empIntfc = (IEmployee)ctx.getBean("empService");
try {
empIntfc.createEmployee(emp);
empIntfc.createEmployeeDetails(emp);
//Below will throw RunTime Exception
empIntfc.getEmployee(2);
}catch (Exception e ) {
e.printStackTrace();
} finally {
ctx.close();
}
}
EmployeeService.java
public class EmployeeService implements IEmployee {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
jdbcTemplate = new JdbcTemplate(this.dataSource);
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
#Override
#Transactional
public int createEmployee(Employee emp) {
String sql1 = "INSERT INTO TEST_T1(EMP_ID, EMP_FNAME, EMP_LNAME) values
(?,?,?)";
return getJdbcTemplate().update(sql1, emp.getEmpId(),
emp.getEmpFirstName(), emp.getEmpLastName());
}
#Override
#Transactional
public int createEmployeeDetails(Employee emp) {
String sql = "INSERT INTO TEST_T2(EMP_ID, EXP, SKILLS) values (?,?,?)";
return getJdbcTemplate().update(sql, emp.getEmpId(), emp.getExp(),
emp.getSkills());
}
#Override
#Transactional(readOnly = true, noRollbackFor=RuntimeException.class)
public Employee getEmployee(int empId) {
throw new RuntimeException("Intentional runtime exception");
}
}
spring-bean.xml
<beans xmlns="http://www.springframework.org/schema/beans">
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
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="jdbc:oracle:thin:#//xxxx:1521/xxxx"/>
<property name="username" value="user"/>
<property name="password" value="user"/>
</bean>
<bean id="empService" class="com.service.EmployeeService">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
Your main method is not transactional ... means : entering 'createEmployee' creates a new transaction and commits it, 'createEmployeeDetails' creates a new transaction and commits it .

Getting jdbcTemplate null in Spring Junit test case

I am writing junit test case for spring 3 restful services. When I am trying to execute it as junit, i am getting JdbcTemplate as null. I am not sure where I did the mistake. Please help me to get out of this...
LoginServiceImpl.java file,
private NamedParameterJdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
System.out.println("--------------"+jdbcTemplate.toString());
}
private static Map<String, AuthToken> tokenHash = new ConcurrentHashMap<String, AuthToken>();
private static String authTokenDetailsSql = "select * from authtoken where token = :token";
#Override
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseBody
public ServiceBean newAccount(#RequestBody Registration registration) {
String newAccountSql = "INSERT INTO account (email,password,name) VALUES (:email,:password,:name)";
ServiceDataBean<AuthToken> retBean = new ServiceDataBean<AuthToken>();
try {
System.out.println("register service calling.....");
MapSqlParameterSource namedParameters = new MapSqlParameterSource();
namedParameters.addValue("email", registration.getEmail());
messageDigest = MessageDigest.getInstance("MD5");
byte[] md5 = new byte[64];
messageDigest.update(registration.getPassword().getBytes("iso-8859-1"), 0, registration.getPassword().length());
md5 = messageDigest.digest();
namedParameters.addValue("password", convertedToHex(md5));
namedParameters.addValue("name", registration.getName());
GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
// TODO what to do with the updInt also check it's not -1
int updInt = jdbcTemplate.update(newAccountSql, namedParameters, generatedKeyHolder);
long accountId = (Long) generatedKeyHolder.getKeys().get("GENERATED_KEY");
registration.getDevice().setOwner(registration.getId());
fotoframz.register(registration.getDevice());
Login login = new Login();
login.setEmail(registration.getEmail());
login.setPassword(registration.getPassword());
login.setDevice(registration.getDevice());
retBean = (ServiceDataBean<AuthToken>) this.login(login);
System.out.println("form register");
} catch (Throwable e) {
retBean.setStatusCode("001");
e.printStackTrace();
}
return retBean;
}
I am getting jdbctemplate=null at int updInt = jdbcTemplate.update(newAccountSql, namedParameters, generatedKeyHolder);
my applicationContext-test.xml file is in src/test/resources folder..applicationContext-test.xml file
<context:component-scan base-package="net.mss.ff.services" />
<context:property-placeholder location="classpath:/app.properties" />
<!-- <task:annotation-driven /> -->
<context:annotation-config />
<!-- <import resource="apicontroller_v1-servlet.xml"/>
<import resource="applicationContext.xml"/> -->
<bean id="photoService" class="net.mss.ff.services.core.api.impl.PhotoServiceImpl">
<property name="rootStorageFolder" value="${storage.root}" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
LoginServiceImplTest
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:/applicationContext-test.xml"})
public class LoginServiceImplTest {
LoginServiceImpl loginServiceObj = new LoginServiceImpl();
Device deviceMock;
#Autowired
private Fotoframz fotoframz;
/*private NamedParameterJdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}*/
#Before
public void setUp() throws Exception {
//loginServiceObj = new LoginServiceImpl();
}
#After
public void tearDown() throws Exception{
}
/**
* Test method for {#link net.mss.ff.services.core.api.impl.LoginServiceImpl#newAccount(net.mss.ff.services.core.beans.Registration)}.
*/
#Test
public void testNewAccount() {
Registration mockRegObj = new Registration();
deviceMock = new Device();
deviceMock.setActive(false);
deviceMock.setHeight(45);
//deviceMock.setId(4568);
deviceMock.setName("Android");
deviceMock.setOwner(1111);
deviceMock.setPlatform("Windows NT");
deviceMock.setUuid("522601");
deviceMock.setVersion("1.0");
deviceMock.setWidth(76);
mockRegObj.setEmail("bbb#gmail.com");
/*mockRegObj.setId(399);*/
mockRegObj.setName("bbb");
mockRegObj.setPassword("BBB");
mockRegObj.setDevice(deviceMock);
loginServiceObj.newAccount(mockRegObj);
//assertEquals("New Account Creation", "", "");
}
}
anything needs to modify in test class, please let me know..
In your test the LoginServiceImpl loginServiceObj = new LoginServiceImpl();
is not instantiated by spring, thus no annaotions will be applied. You need to autowire it, or inject it some other way. Spring 3.2 makes this kinda thing super easy and nice to use.
The rest of my answer is still good adivce :
You have not declared or instantiated the jdbctemplate in your java code. And you have not defined it in your xml file.
You need this
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dateSource"/>
</property>
</bean>
and then this as instance variable (assuming your using annoations)
#Resource(name = "jdbcTemplate")
private JdbcTemplate jdbcTemplate;
As #NimChimpsky mentioned you need to define your jdbcTemplate in your bean xml file and then in your instance variable you can also do.
#Autowired
private JdbcTemplate jdbcTemplate;

Spring MVC - Bean not available with #Autowired

I'm having some trouble getting a data source bean, defined in an xml file, into a class in Spring using #Autowired annotation.
Would anyone have an idea what's happening here? It seems as though dataSource in the *Impl class is not being wired in.
dao-context.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:8889/spring" />
<property name="username" value="user" />
<property name="password" value="1234" />
</bean>
PersonDaoImpl.java
public class PersonDaoImpl implements PersonDao {
#Autowired
private DataSource dataSource;
private JdbcTemplate jdbcTemplate = new JdbcTemplate();
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
System.out.println("SETTING DATA SOURCE");
this.dataSource = dataSource;
}
public List<Person> getPersonList() {
// TODO Auto-generated method stub
return null;
}
public void savePerson(Person person) {
// TODO Auto-generated method stub
}
public Person getPersonById(int id) {
System.out.println("Getting Person: " + id);
return null;
}
#Override
public int getPersonCount(){
String sql = "SELCECT COUNT(*) FROM PERSON";
jdbcTemplate.setDataSource(getDataSource());
int count = jdbcTemplate.queryForInt(sql);
System.out.println("Count of Person: " + count);
return count;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
...and finally, the exception.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: No DataSource specified
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
java.lang.IllegalArgumentException: No DataSource specified
org.springframework.util.Assert.notNull(Assert.java:112)
org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:97)
org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:382)
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:456)
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:464)
org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:472)
org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:477)
org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:486)
com.myPackage.rest.dao.impl.PersonDaoImpl.getPersonCount(PersonDaoImpl.java:50)
com.myPackage.rest.HomeController.home(HomeController.java:36)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
Any help would be greatly appreciated, cheers.
Your data source needs to be set in the JdbcTemplate (I don't see you doing that). Also since you put the #Autowired annotation on the field, I don't think it uses the setter so that would be why your setDataSource method is not being called. Since your exception indicates that you called jdbcTemplate.execute and dataSource is null, this makes sense.
If you look here: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jdbc.html there is an example of autowiring a data source, but the idea is:
public class MyDao {
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
}
Right, thanks to the two replies I've got this working.
dao-context (as above, with this added):
<bean id="personDao" class="com.mypackage.rest.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
Impl class
#Repository
public class PersonDaoImpl implements PersonDao {
private JdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getPersonCount(){
String sql = "select count(*) from person";
return jdbcTemplate.queryForInt(sql);
}
}
One more important piece I had missed was the Dependency Injected Impl instance in the Controller.
#Controller
public class HomeController {
#Autowired
private PersonDao personDao;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
int personCount = personDao.getPersonCount();
model.addAttribute("personCount", personCount );
return "home";
}
}
The impl class needs to be marked for handling by spring:
#Repository
public class PersonDaoImpl implements PersonDao {
Now if spring package scanning is being used, it will find this class and process all the #Autowired annotations

Resources