Currently I am new to spring to trying to implement data-source with MySQL but I am facing a error but not able to understand what is main reason or error.
Exception in thread "main" java.lang.ExceptionInInitializerError
Apr 26, 2015 8:09:33 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#4ee70b: startup date [Sun Apr 26 20:09:33 IST 2015]; root of context hierarchy
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.springframework.context.support.AbstractRefreshableApplicationContext.createBeanFactory(AbstractRefreshableApplicationContext.java:194)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:127)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:465)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:395)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.rajdeo.jdbcspring.JdbcDemo.main(JdbcDemo.java:12)
Caused by: java.lang.NullPointerException
at org.springframework.beans.factory.support.DefaultListableBeanFactory.<clinit>(DefaultListableBeanFactory.java:104)
... 7 more
JdbcDemo.java
package com.x.jdbcspring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.x.jdbcspring.JdbcDaoImpl;
public class JdbcDemo {
public static void main(String[] args) {
ApplicationContext ctx= new ClassPathXmlApplicationContext("spring.xml");
JdbcDaoImpl dao=ctx.getBean("JdbcDaoImpl",JdbcDaoImpl.class);
/*
//JdbcDaoImpl dao=new JdbcDaoImpl();
Student student=ctx.getStudent(1);
System.out.println("name::\t"+student.getName());
JdbcDaoImpl jdbc=new JdbcDaoImpl();
jdbc.getStudent(1);
System.out.println(jdbc.getStudent(1).getId());*/
}
}
JdbcDaoImpl.java
package com.x.jdbcspring;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class JdbcDaoImpl {
#Autowired
private DataSource datasource;
public DataSource getDatasource() {
return datasource;
}
public void setDatasource(DataSource datasource) {
this.datasource = datasource;
}
public Student getStudent(int id){
Connection con = null;
Student student=null;
try{
/* Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting to database...");*/
con = datasource.getConnection();
PreparedStatement stmt=con.prepareStatement("select * from contact where contact_id =?");
stmt.setInt(1, id);
//Excute the query
ResultSet rs=stmt.executeQuery();
while(rs.next()){
String name=rs.getString("name");
student=new Student(id, name);
}
//close the statement and Resultset
stmt.close();
rs.close();
return student;
}catch(Exception e){
e.printStackTrace();
}
finally{
if(con!=null)
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return student;
}
}
Student.java
package com.rajdeo.jdbcspring;
public class Student {
private int id;
private String name;
public Student(int id, String name) {
// TODO Auto-generated constructor stub
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
spring.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.rajdeo" />
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/student" />
<property name="username" value="root" />
<property name="password" value="xxxx" />
</bean>
</beans>
What is error I am not able to understand it any help is appreciated.
Your spring.xml says to scan the package com.rajdeo for components, but your class JdbcDaoImpl is in package com.x.jdbcspring and so it will not be picked up, even though it has a #Component annotation.
Make sure to include the package that contains JdbcDaoImpl in the component scanning process:
<context:component-scan base-package="com.rajdeo, com.x.jdbcspring" />
Looks like you are getting a bean from the context
ctx.getBean("JdbcDaoImpl",JdbcDaoImpl.class)
but in the spring.xml this bean is not defined. As a result you get NPE = java.lang.NullPointerException.
To resolve this issue you have to configure JdbcDaoImpl service. E.g.
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/student" />
<property name="username" value="root" />
<property name="password" value="xxxx" />
</bean>
<bean id="JdbcDaoImpl"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property name="datasource" ref="datasource"/>
</bean>
Related
I am trying to start a spring mvc application,
and keep receiving the following error which I cannot solve
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerController': Unsatisfied dependency expressed through field 'customerDAO'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerDAOImpl': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-mvc-crud-demo-servlet.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
And this is only the first error shown in the console.
Well, I am trying to understand the first part of the whole line, which is
Unsatisfied dependency expressed through field customerDAO Unsatisfied dependency expressed through field customerDAO. It is giving a 500 server error. I cannot find any similar solution, neither see where the error is. Here are my source code files so far:
the entity class
package com.wcorp.springdemo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="customer")
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
#Column(name="email")
private String email;
public Customer() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
}
}
the dao Interface and its implementation
import com.wcorp.springdemo.entity.Customer;
public interface CustomerDAO {
public List<Customer> getCustomers();
}
import javax.transaction.Transactional;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.wcorp.springdemo.entity.Customer;
#Repository
public class CustomerDAOImpl implements CustomerDAO {
// need to inject the session factory
#Autowired
private SessionFactory sessionFactory;
#Override
#Transactional
public List<Customer> getCustomers() {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// create a query
Query<Customer> theQuery =
currentSession.createQuery("from Customer", Customer.class);
// execute query and get result list
List<Customer> customers = theQuery.getResultList();
// return the results
return customers;
}
}
The controller
package com.wcorp.springdemo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.wcorp.springdemo.dao.CustomerDAO;
import com.wcorp.springdemo.entity.Customer;
#Controller
#RequestMapping("/customer")
public class CustomerController {
// need to inject the customer dao
#Autowired
private CustomerDAO customerDAO;
#RequestMapping("/list")
public String listCustomers(Model theModel) {
// get customers from the dao
List<Customer> theCustomers = customerDAO.getCustomers();
// add the customers to the model
theModel.addAttribute("customers", theCustomers);
return "list-customers";
}
}
Here is the spring config 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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Add support for component scanning -->
<context:component-scan base-package="com.wcorp.springdemo" />
<!-- Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Step 1: Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/web_customer_tracker?useSSL=false&serverTimezone=UTC" />
<property name="user" value="springstudent2" />
<property name="password" value="springstudent2" />
<!-- these are connection pool properties for C3P0 -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.wcorp.springdemo.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager" />
</beans>
the project build path, jars and tomcat server is fine eclipse is not complaining, spring version is 5.0.2, hibernate version 5.2.17
I found a similar problem described here
Please try to run under Java 8. The problem comes that you use Java 11.
Most of the frameworks are not compatible and are not fully tested on Java 11.
when i am going to execute this program.
my program is successfully executed but it doesn't store data in database.
what is the problem in this program.
this is my Employee.java class
package com.spring.demo;
public class Employee {
private int id;
private String name;
private float salary;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
}
this is my EmployeeDao.java class
package com.spring.demo;
import org.springframework.orm.hibernate5.HibernateTemplate;
public class EmployeeDao {
HibernateTemplate template;
public void setTemplate(HibernateTemplate template) {
this.template = template;
}
public void saveEmployee(Employee e) {
Integer i = (Integer) template.save(e);
if (i > 0) {
System.out.println("Success");
} else {
System.out.println("Not Success");
}
}
public void updateEmployee(Employee e) {
template.update(e);
}
public void deleteEmployee(Employee e) {
template.delete(e);
}
}
this is my Test.java class
package com.spring.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext bean = new
ClassPathXmlApplicationContext("spring.xml");
EmployeeDao emp = (EmployeeDao) bean.getBean("obj");
Employee e = new Employee();
e.setId(2);
e.setName("Amit Goyal");
e.setSalary(40000);
emp.saveEmployee(e);
// emp.updateEmployee(e);
bean.close();
}
}
this is my Employee.hbm.xml file
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.spring.demo.Employee" table="amit1234">
<id name="id">
<generator class="assigned"></generator>
</id>
<property name="name"></property>
<property name="salary"></property>
</class>
</hibernate-mapping>
and last this is my spring.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-
4.2.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="tiger" />
</bean>
<bean id="mysessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>Employee.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="template"
class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="mysessionFactory"></property>
<property name="checkWriteOperations" value="false"></property>
</bean>
<bean id="obj" class="com.spring.demo.EmployeeDao">
<property name="template" ref="template"></property>
</bean>
</beans>
In this configuration you are missing transaction management configuration. Use #transactional annotation over your service method.
In you situation data is not committing in the database it just save the data and not commit the data in database.
I'm training Spring persistence with LocalContainerEntityManagerFactoryBean and getting error:
Caused by: java.sql.SQLException: Table not found in statement [insert into PERSON (ID, email, name) values (null, ?, ?)]
Don't really know what I did wrong
My Main class (for test only)
package com.me.test;
import com.me.model.Person;
import com.me.service.PersonService;
import java.util.List;
import java.util.logging.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
/**
*
*/
public static final Logger log = Logger.getLogger(Main.class.getName());
public static void main(String[] args) {
log.info("************** BEGINNING PROGRAM **************");
ApplicationContext context = new ClassPathXmlApplicationContext("WEB-INF/spring-config.xml");
PersonService personService = (PersonService) context.getBean("personService");
Person person = new Person();
person.setName("name");
person.setEmail("name#name.com");
personService.addPerson(person);
log.info("Person : " + person + " added successfully");
List<Person> persons = personService.fetchAllPersons();
log.info("The list of all persons = " + persons);
log.info("************** ENDING PROGRAM *****************");
}
}
My application context:
<?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:aop="http://www.springframework.org/schema/aop"
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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.me" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="personPersistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:file:/home/me/Pulpit/hsql1/db3; shutdown=true" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<bean id="dbUtil" class="com.me.service.DbUtil">
<!-- init-method="initialize">-->
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="personPersistenceUnit" transaction-type="RESOURCE_LOCAL" >
<class>com.me.model.Person</class>
</persistence-unit>
</persistence>
PersonService class
package com.me.service;
import com.me.dao.PersonDao;
import com.me.model.Person;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class PersonService {
private PersonDao personDao;
public PersonDao getPersonDao() {
return personDao;
}
#Autowired
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
public void addPerson(Person person) {
getPersonDao().insert(person);
}
public List<Person> fetchAllPersons() {
return getPersonDao().selectAll();
}
}
personDAO class
package com.me.dao;
import com.me.model.Person;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
#Repository("personDao")
#Transactional(propagation = Propagation.REQUIRED)
public class PersonDao {
private static final String SELECT_QUERY = "select p from Person p";
#PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void insert(Person person) {
entityManager.persist(person);
}
public List<Person> selectAll() {
Query query = entityManager.createQuery(SELECT_QUERY);
List<Person> persons = (List<Person>) query.getResultList();
return persons;
}
}
What's wrong here guys?
edit:
adding person class:
package com.me.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "PERSON")
public class Person implements Serializable{
private Integer id;
private String name;
private String email;
#Id
#GeneratedValue
#Column(name = "ID")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", email=" + email + "]";
}
}
and persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="personPersistenceUnit" transaction-type="RESOURCE_LOCAL" >
<class>com.me.model.Person</class>
</persistence-unit>
</persistence>
The problem is that you have not told Hibernate anywhere that it needs to create the tables when it loads.
An easy way to do that would be to add
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
inside persistence.xml after <class>
I have some problems with autowire annotation in one of my services. I have spent a lot of hours to find a solution but I don't have idea what I'm doing wrong. My app looks like this.
Here is my controller:
package control.peso.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import control.peso.data.ResumenMedicionPeso;
import control.peso.service.HomeService;
#Controller
public class HomeController {
#Autowired
private HomeService homeService; //NOPMD
#RequestMapping(value = "json/resumen_mediciones.action")
#ResponseBody
public final ResumenMedicionPeso
dataJsonPeso(final HttpServletRequest req) {
final ResumenMedicionPeso peso = homeService.getResumenMediciones();
return peso;
}
}
My service layer:
package control.peso.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import control.peso.dao.PesoDAO;
import control.peso.data.ResumenMedicionPeso;
#Service
#Transactional(readOnly = true)
public class HomeService {
#Autowired
private PesoDAO pesoDAO; //NOPMD
public final ResumenMedicionPeso getResumenMediciones() {
final ResumenMedicionPeso resumMedicionPeso = new ResumenMedicionPeso();
resumMedicionPeso.setMaxPeso(pesoDAO.getMaxPeso());
resumMedicionPeso.setMinPeso(pesoDAO.getMinPeso());
resumMedicionPeso.setMaxGrasa(pesoDAO.getMaxGrasa());
resumMedicionPeso.setMinGrasa(pesoDAO.getMinGrasa());
resumMedicionPeso.setMaxPorcenGrasa(pesoDAO.getMaxPorcenGrasa());
resumMedicionPeso.setMinPorcenGrasa(pesoDAO.getMinPorcenGrasa());
resumMedicionPeso.setMaxMusculo(pesoDAO.getMaxMusculo());
resumMedicionPeso.setMinMusculo(pesoDAO.getMinMusculo());
resumMedicionPeso.setMaxPorcenMusculo(pesoDAO.getMaxPorcenMusculo());
resumMedicionPeso.setMinPorcenMusculo(pesoDAO.getMinPorcenMusculo());
return resumMedicionPeso;
}
}
My dao:
package control.peso.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import control.peso.model.MedicionPeso;
public class PesoDAO implements IPesoDAO {
private SessionFactory sessionFactory;
public final SessionFactory getSessionFactory() {
return sessionFactory;
}
public final void setSessionFactory(
final SessionFactory pSessionFactory) {
this.sessionFactory = pSessionFactory;
}
#Override
public final void addPeso(final MedicionPeso peso) {
getSessionFactory().getCurrentSession().save(peso); //NOPMD
}
#Override
public final void updatePeso(final MedicionPeso peso) {
getSessionFactory().getCurrentSession().update(peso); //NOPMD
}
#Override
public final void deletePeso(final Integer idPeso) {
getSessionFactory().getCurrentSession()
.delete(new MedicionPeso(idPeso));
}
#Override
public final MedicionPeso getPesoById(final Integer idPeso) {
#SuppressWarnings("unchecked") //NOPMD
final List<MedicionPeso> list = getSessionFactory() // NOPMD
.getCurrentSession()
.createQuery("from MedicionPeso where idPeso = ?")
.setParameter(0, idPeso).list();
return list.get(0); //NOPMD
}
#Override
public final List<MedicionPeso> getPesos() {
#SuppressWarnings("unchecked")
final List<MedicionPeso> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("from MedicionPeso medicionPeso "
+ "order by medicionPeso.fechaMedicion desc")
.list();
return list;
}
public final Float getMaxPeso() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(peso) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMinPeso() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select min(peso) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMaxGrasa() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(pesoGrasa) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMinGrasa() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select min(pesoGrasa) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMaxPorcenGrasa() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(pesoGrasa) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMinPorcenGrasa() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select min(porcentajeGrasa) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
/**
* Recupera la medicion de musculo con valor maximo.
* #return El valor maximo de las mediciones de musculo.
*/
public final Float getMaxMusculo() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(porcentajeGrasa) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMinMusculo() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select min(pesoMusculo) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMaxPorcenMusculo() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(porcentajeMusculo) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
public final Float getMinPorcenMusculo() {
#SuppressWarnings("unchecked")
final List<Float> list = getSessionFactory() //NOPMD
.getCurrentSession()
.createQuery("select max(porcentajeMusculo) from MedicionPeso")
.list();
return (Float) list.get(0); //NOPMD
}
}
My dao interface:
package control.peso.dao;
import java.util.List;
import control.peso.model.MedicionPeso;
public interface IPesoDAO {
void addPeso(MedicionPeso peso);
void updatePeso(MedicionPeso peso);
void deletePeso(Integer idPeso);
MedicionPeso getPesoById(Integer idPeso);
List<MedicionPeso> getPesos();
}
This is my dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--Routes -->
<mvc:view-controller path="/" view-name="home"/>
<mvc:view-controller path="/home" view-name="home"/>
<mvc:view-controller path="/medicion" view-name="medicion_peso"/>
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="control.peso" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<!-- misc -->
<!--
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
-->
<!-- Tiles Resolver -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.tiles2.TilesView
</value>
</property>
</bean>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<!-- Application Message Bundle -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- JSON Objets Definition -->
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
<!-- Beans Declaration -->
<bean id="MedicionPeso" class="control.peso.model.MedicionPeso" />
<!-- User DAO Declaration -->
<bean id="PesoDAO" class="control.peso.dao.PesoDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<!-- Data Source Declaration -->
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/juan" />
<property name="user" value="root" />
<property name="password" value="" />
<property name="maxPoolSize" value="10" />
<property name="maxStatements" value="0" />
<property name="minPoolSize" value="5" />
</bean>
<!-- Session Factory Declaration -->
<bean id="SessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="annotatedClasses">
<list>
<value>control.peso.model.MedicionPeso</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- Transaction Manager is defined -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
</beans>
So when I launch my web-app, my controller Autowires correctly the service, but my DAO object in my service has null value (not injected properly).
Any ideas?
It's curious because from another service, the same DAO is properly injected.
Thanks
in your HomeService, you've specified the implementation of IPesoDAO, not the interface. try changing it to IPesoDAO instead and see if that helps.
in addition, you may also want to create an interface IHomeService and have your existing HomeService implement it, again, changing the controller to reference the interface, not the implementation
Main thing to grasp is that your service is #Transactional that means that Spring will have to create transactional proxy around it. It is a separate object that is injected instead of bean, that will delegate all its method calls to the original bean, opening and closing transactions before and after.
As incomplete-co.de has suggested your service is injected as class, and not as interface.
The only way to automatically create a separate proxy object in this case is to subclass your original service class HomeService. If everything would go normal than a subclass would be created:
The first notable side effect will be that the constructor of HomeService would be called twice - because in Java you are forced to call the constructor of super class, so the constructor of the proxy will call the constructor of HomeService in addition to the construction of the bean itself.
The second effect will be that the subclass in Java inherits all the base fields of the superclass, they are not initialized, i.e. pesoDAO reference of the proxy instance will be null. It's okay because field values are not needed for proxy, because it will call the method of original bean, which fields are initialized.
The third thing is that this scheme will work only if the methods of the super class are not declared final.
In your case when the method of proxy is called instead of delegating the call to original bean it behaves as the superclass but with its fields left uninitialized.
So I recommend to follow incomplete-co.de advice and inject the service as interface, interfaces are more suitable for proxying because the proxying framework don't have to fight with the subclassing restrictions.
P.S. another minor restriction is that in subclassing the framework will need to have a strategy to decide which inherited constructor to call - in Spring/CGLIB the parameterless constructor is preferred, so you will be forced to create one if the compiler did not do this automatically.
So these are some practical reasons(I'm not mentioning good OOD principles here) why in Spring we are offen forced to to inject services as interfaces.
You have a strange mix of annotation based and XML based beans declaration, which makes code not clear - it is really better to use annotations as much as possible and use XML configuration only for specific stuff (datasources, jpa related stuff, third party beans).
Use of #Autowired alone is also misleading - in this case Spring will try to find bean named as your annotated class member.
In your particular case you declare DAO bean in XML as:
<!-- User DAO Declaration -->
<bean id="PesoDAO" class="control.peso.dao.PesoDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
And then you are trying to inject it as:
#Service
#Transactional(readOnly = true)
public class HomeService {
#Autowired
private PesoDAO pesoDAO; //NOPMD
}
This will likely cause injection failure since Spring will try to find bean named as 'pesoDao' (this is default naming convention), but you have 'PesoDao' in XML.
To resolve this as well as never worry of such issues further, you can explicitly name your annotated beans and also explicitly provide this name when autowiring (use #Qualifier annotation).
Example:
#Component("pesoDao")
public class PesoDAO implements IPesoDAO {
private SessionFactory sessionFactory;
}
#Service("homeService")
#Transactional(readOnly = true)
public class HomeService {
#Autowired
#Qualifier("pesoDao")
private PesoDAO pesoDAO; //NOPMD
}
In this case, you always know what is going to be injected.
I'm trying to write a simple application to learn how Transaction works in Spring (Declarative AOP Style). I'm inserting one record into customer table and then throwing NullPointerException to see if the inserted data is rolled back or not. But to my surprise it's not rolling back the data. Here is the code
ApplicationContext.xml file
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
">
<aop:aspectj-autoproxy />
<bean id="BoardingService" class="com.learning.maven.services.BoardingServiceImpl"/>
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="getUser*" rollback-for="throwable" propagation="REQUIRES_NEW"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="boardingServiceOperation" expression="execution(* com.learning.maven.services.BoardingService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="boardingServiceOperation"/>
</aop:config>
<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:#localhost:1521:XE"/>
<property name="username" value="system"/>
<property name="password" value="Manager"/>
</bean>
<bean id="customerDAO" class="com.learning.maven.dao.CustomerDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
This is how I call method
public static void main(String[] args) {
context = new FileSystemXmlApplicationContext("C:\\workspace\\learning\\cxf\\SpringTransaction\\cxf.xml");
BoardingService bean = (BoardingService) context.getBean("BoardingService");
bean.getUser("1");
}
And the BoardingService Class Looks like below
public class BoardingServiceImpl implements BoardingService, ApplicationContextAware {
ApplicationContext context = null;
public String getUser(String id) {
String response = "SUCCESS";
try{
System.out.println("Testing");
CustomerDAO customerDAO = (CustomerDAO) Testing.context.getBean("customerDAO");
Customer c = new Customer();
c.setAge(31);
c.setCustId(1);
c.setName("Jagadeesh");
customerDAO.insert(c);
customerDAO.insert(null);
}
catch(Exception e){
throw new RuntimeException();
}
return response;
}
#Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
this.context = arg0;
}
and the CustomerDAOImpl
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void insert(Customer customer) {
String sql = "INSERT INTO CUSTOMER (CUST_ID, NAME, AGE) VALUES (?, ?, ?)";
Connection conn = null;
try {
conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, customer.getCustId());
ps.setString(2, customer.getName());
ps.setInt(3, customer.getAge());
ps.executeUpdate();
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {}
}
}
}
public Customer findByCustomerId(int custId) {
// TODO Auto-generated method stub
return null;
}
Not sure where am I going wrong. Any Pointers will be of great help.
You have rollback-for "throwable" instead of "Throwable".
P.S. Not sure that you should use REQUIRES_NEW as the default strategy.
update: From DataSourceTransactionManager documentation
Application code is required to retrieve the JDBC Connection via
DataSourceUtils.getConnection(DataSource) instead of a standard
J2EE-style DataSource.getConnection() call. Spring classes such as
JdbcTemplate use this strategy implicitly. If not used in combination
with this transaction manager, the DataSourceUtils lookup strategy
behaves exactly like the native DataSource lookup; it can thus be used
in a portable fashion.
In your case you open connection directly and then Oracle commits transaction on close(this is a feature of Oracle RDBMS).
You can also just omit the rollback-for attribute. Then it will rollback if any RuntimeException occurs.