I have a Java project which uses Spring + Hibernate + JasperReports to generate a report on PDF format. The report is properly generated using JasperReports based on a .jrxml file I generated with iReport using a MySQL JDBC connection. On Java code I use Hibernate/Spring with annotations. Only using annotations and without the file: hibernate.cfg.xml I could create the PDF report after fetching data from MySQL database.
So, Java application works correctly using Hibernate and iRport works correctly using JDBC connection.
The problem is when I try to connect iReport to the MySQL database with a Hibernate connection to take advanatage of the Hibernate functionality. I wanna use the same Hibernate configuration who was successful on Java.
As I have seen iReport always looks for the file: hibernate.cfg.xml. Then I created one on src/main/resources (especifically for this purpose) and after build the project it gets copied to: <project_dir>\target\classes, and this is the folder I will add to iReport classpath below.
The full content of: hibernate.cfg.xml is as follows:
<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-2.5.xsd">
<annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.elkiosko" />
</beans>
To test it, I changed the test method who generates the PDF report to use this XML file, then, I replaced:
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
for:
AbstractApplicationContext context = new ClassPathXmlApplicationContext("classpath:hibernate.cfg.xml");
and the PDF report was generated properly too again.
Going now to iReport...
I have configured the classpath of iReport adding the folder where the file: hibernate.cfg.xml is located on.
and when trying to set up a Hibernate connection on iReport I get:
Error - Invalid Configuration
when click on Test button.
I also tried checking: Use Hibernate Annotations with no success.
I don't understand why with Java the Hibernate connection works but it doesn't with iReport.
Remember I took the way of annotations and not xml. I created the file: hibernate.cfg.xml just to let iReport knows what package scan for configuration.
The mapping of classes are done in the model class as you can see below:
package com.elkiosko.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Producto {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "price", nullable = false)
private float price;
#Column(name = "stock", nullable = false)
private int stock;
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 getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Producto))
return false;
Producto other = (Producto) obj;
if (this == other)
return true;
if (this.id != other.id)
return false;
if (!this.name.equals(other.name))
return false;
if (this.price != other.price)
return false;
if (this.stock != other.stock)
return false;
return true;
}
#Override
public String toString() {
return "Producto [id=" + id + ", name=" + name +
", price=" + price + ", stock=" + stock + "]";
}
}
Also I have other classes implemented, for example: HibernateConfiguration.java which is annotated as: #Configuration (Java code works OK, the problem is with iReport).
The content of the file: HibernateConfiguration.java is as follows:
package com.elkiosko.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.elkiosko" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
I have also tried setting up a Spring loaded Hibernate connection with no success:
It seems that it expcets a bean be defined inside hibernate.cfg.xml, but I have not defined any bean there because I have defined the sessionFactory bean inside the file: HibernateConfiguration.java. Anyway, this way is discarded because iReport use an old version of Spring which is incompatible with the version of Spring I use: 4.2.0. So, the only way I can take is create a Hibernate connection.
Any idea on how to configure the Hibernate connection with iReport?
Related
I'm trying to run OpenJPA with newest Spring Boot 2 and Gradle.
The problem is that Spring 5 does not support OpenJPA anymore.
When I run the application I see an error:
Caused by: org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "
aero.onair.accground.aft.TestEntity".
There was some plugin for older Gradle which was doing the entity enhancement with the use of openjpa library, but it does not work with the newer.
I have used an adapter and dialect like in this repo:
https://github.com/apache/syncope/tree/master/core/persistence-jpa/src/main/java/org/springframework/orm/jpa/vendor
I have the persistence.xml file in resources/jpa/persistence.xml
I have also tried to move it to resources/META-INF/
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="2.0">
<persistence-unit name="aftDbUnitName">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>aero.onair.accground.aft.TestEntity</class>
</persistence-unit>
</persistence>
My configuration for OpenJPA:
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.openjpa.persistence.PersistenceProviderImpl;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.transaction.jta.JtaTransactionManager;
#Configuration
public class OpenJpaConfig extends JpaBaseConfiguration {
protected OpenJpaConfig(DataSource dataSource,
JpaProperties properties,
ObjectProvider<JtaTransactionManager> jtaTransactionManager,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
super(dataSource, properties, jtaTransactionManager, transactionManagerCustomizers);
}
#Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
OpenJpaVendorAdapter jpaVendorAdapter = new OpenJpaVendorAdapter();
jpaVendorAdapter.setShowSql(true);
return jpaVendorAdapter;
}
#Override
protected Map<String, Object> getVendorProperties() {
return new HashMap<>(0);
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(getDataSource());
factory.setPersistenceProviderClass(PersistenceProviderImpl.class);
factory.setJpaVendorAdapter(new OpenJpaVendorAdapter());
factory.setPersistenceXmlLocation("jpa/persistence.xml");
return factory;
}
}
Test Entity:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class TestEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And finally the main Application class:
#SpringBootApplication(exclude = {XADataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
#Slf4j
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Autowired
TestEntitiyRepository testEntitiyRepository;
#PostConstruct
public void test() {
long count = testEntitiyRepository.count();
log.info("Count = {}", count);
TestEntity entitiy = new TestEntity();
entitiy.setName("testtttt");
testEntitiyRepository.save(entitiy);
count = testEntitiyRepository.count();
log.info("Count after save = {}", count);
}
}
The best solution for me was to add a plugin from this page:
https://github.com/radcortez/openjpa-gradle-plugin
Another solution is to set a javaagent in VM options:
-javaagent:/path/openjpa-all-3.1.0.jar
I am beginner in Spring and trying to learn different ways of configuring Spring beans using XML and Java Config classses. In below demo program, i have configured EmployeeService and EmployeeDAO beans in Java Config classes and Employee bean in XML file. And then i am trying to Reference JavaConfig in XML configuration and use this XML configuration file in Main Class to get the Employee Service bean. I am getting NoSuchBeanDefinitionException while executing the below program. Can someone please help me to understand what is wrong here.
DAOConfig.java
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.demo.dao.EmployeeDAO;
#Configuration
public class DAOConfig {
#Bean
public EmployeeDAO getEmployeeDAO(){
return new EmployeeDAO();
}
}
ServiceConfig.java
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.demo.dao.EmployeeDAO;
import com.demo.service.EmployeeService;
#Configuration
public class ServiceConfig {
#Bean(name="myEmployeeService")
public EmployeeService getEmployeeService(EmployeeDAO empDAO){
EmployeeService empService = new EmployeeService();
empService.setEmpDAO(empDAO);
return empService;
}
}
MainConfig.java
package com.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration
#Import({ DAOConfig.class, ServiceConfig.class })
public class MainConfig {
}
EmployeeService.java:
package com.demo.service;
import com.demo.dao.EmployeeDAO;
public class EmployeeService {
private EmployeeDAO empDAO;
public void setEmpDAO(EmployeeDAO empDAO) {
this.empDAO = empDAO;
}
public void insertEmployee() {
System.out.println("insertEmployee called..");
empDAO.insertEmployeeDetails();
}
public void updateEmployee() {
System.out.println("updateEmployee called..");
empDAO.updateEmployeeDetails();
}
public void deleteEmployee() {
System.out.println("deleteEmployee called..");
empDAO.deleteEmployeeDetails();
}
}
EmployeeDAO.java
package com.demo.dao;
public class EmployeeDAO {
public void insertEmployeeDetails(){
System.out.println("insertEmployeeDetails called..");
}
public void updateEmployeeDetails(){
System.out.println("updateEmployeeDetails called..");
}
public void deleteEmployeeDetails(){
System.out.println("deleteEmployeeDetails called..");
}
}
Employee.java:
package com.demo.dto;
public class Employee {
private String name;
private String id;
private String salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
#Override
public String toString() {
return "Employee [name=" + name + ", id=" + id + ", salary=" + salary + "]";
}
}
mixAppContext.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean class="com.demo.config.MainConfig" />
<bean id="employeeObj" class="com.demo.dto.Employee">
<property name="name" value="ABC"></property>
<property name="id" value="123"></property>
<property name="salary" value="10000"></property>
</bean>
</beans>
JavaConfigInXmlMixDemo.java:
package com.demo.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.demo.dto.Employee;
import com.demo.service.EmployeeService;
public class JavaConfigInXmlMixDemo {
public static void main(String args[]){
//ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
ApplicationContext context = new ClassPathXmlApplicationContext("mixAppContext.xml");
EmployeeService service = (EmployeeService) context.getBean("myEmployeeService");
Employee employee = (Employee) context.getBean("employeeObj");
service.insertEmployee();
service.updateEmployee();
service.deleteEmployee();
System.out.println(employee);
}
}
I am getting below exception:
Exception:
INFO: Loading XML bean definitions from class path resource [mixAppContext.xml]
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myEmployeeService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:701)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1180)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076)
at com.demo.main.JavaConfigInXmlMixDemo.main(JavaConfigInXmlMixDemo.java:15)
Like described here you need include <context:annotation-config /> in your xml. Without this tag spring will ignore all annotation and create instance of your configuration bean as it's a simple bean.
When i run my project It sun successfully but table is not created. where i am doing wrong
My Hibernate configuration class
package com.quickstart.com.springmvc.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#ComponentScan({ "com.quickstart.com.springmvc.config" })
#PropertySource(value = { "classpath:application.properties" })
public class HibernateConfigration {
#Autowired
private Environment environment;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.quickstart.com.springmvc.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
System.out.println(environment.getRequiredProperty("jdbc.username"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
My SpringConfigration class
package com.quickstart.com.springmvc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan(basePackages="com.quickstart.com.springmvc")
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
My User Class
package com.quickstart.com.springmvc.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.stereotype.Service;
#Service
#Entity
#Table(name="user")
public class User {
#Id
#Column(name="user_id")
private int id;
#Column(name="Name")
private String name;
#Column(name="Email")
private String email;
#Column(name="Age")
private int age;
#Column(name="Password")
private String password;
#Column(name="Contact")
private String contact;
#Column(name="User_Name")
private String username;
User(){
}
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
User(String name){
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
my properties file
jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url =
jdbc:mysql://localhost:3306/HibernateTestDB jdbc.username = root
jdbc.password = root hibernate.dialect =
org.hibernate.dialect.MySQLDialect hibernate.show_sql = true
hibernate.format_sql = true
You forgot this option hibernate.hbm2ddl.auto in your properties :
properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
This property can have the following values :
create creates the schema, destroying previous data
create-drop drop the schema when the SessionFactory is closed explicitly, typically when the application is stopped.
update update the schema.
validate validate the schema, makes no changes to the database.
Add a property in your hibernate configuration properties file
hibernate.hbm2ddl.auto = create
The other available values are "update" "create-drop" "validate" etc
See "Table 3.7. Miscellaneous Properties" https://docs.jboss.org/hibernate/orm/5.0/manual/en-US/html/ch03.html
I am using Spring 3 with Hibernate 3. I would like to update the last modification date automatically when an entity is updated. Below is the sample code:
HibernateConfig:
#Configuration
public class HibernateConfig {
#Bean
public DataSource dataSource() throws Exception {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
Properties properties = new Properties();
properties.load(ClassLoader.getSystemResourceAsStream(new String("hibernate.properties")));
dataSource.setUrl(properties.getProperty(new String("jdbc.url")));
dataSource.setUsername(properties.getProperty(new String("jdbc.username")));
dataSource.setPassword(properties.getProperty(new String("jdbc.password")));
dataSource.setDriverClassName(properties.getProperty(new String("jdbc.driverClassName")));
return dataSource;
}
#Bean
public AnnotationSessionFactoryBean sessionFactory() throws Exception {
AnnotationSessionFactoryBean sessionFactory = new AnnotationSessionFactoryBean();
Properties hibernateProperties = new Properties();
Properties properties = new Properties();
properties.load(ClassLoader.getSystemResourceAsStream(new String("hibernate.properties")));
// set the Hibernate Properties
hibernateProperties.setProperty(new String("hibernate.dialect"), properties.getProperty(new String("hibernate.dialect")));
hibernateProperties.setProperty(new String("hibernate.show_sql"), properties.getProperty(new String("hibernate.show_sql")));
hibernateProperties.setProperty(new String("hibernate.hbm2ddl.auto"), properties.getProperty(new String("hibernate.hbm2ddl.auto")));
sessionFactory.setDataSource(dataSource());
sessionFactory.setHibernateProperties(hibernateProperties);
sessionFactory.setAnnotatedClasses(new Class[]{Message.class})
return sessionFactory;
}
#Bean
public HibernateTemplate hibernateTemplate() throws Exception {
HibernateTemplate hibernateTemplate = new HibernateTemplate();
hibernateTemplate.setSessionFactory(sessionFactory().getObject());
return hibernateTemplate;
}
}
DAOConfig:
#Configuration
public class DAOConfig {
#Autowired
private HibernateConfig hibernateConfig;
#Bean
public MessageDAO messageDAO() throws Exception {
MessageDAO messageDAO = new MessageHibernateDAO(hibernateConfig.hibernateTemplate());
return messageDAO;
}
}
Message:
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
#Table
#EntityListeners(value = MessageListener.class)
public class Message implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private int id;
#Column(nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date lastMod;
public Message() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getLastMod() {
return lastMod;
}
public void setLastMod(Date lastMod) {
this.lastMod = lastMod;
}
}
MessageListener:
import java.util.Date;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import org.springframework.stereotype.Component;
#Component
public class MessageListener {
#PrePersist
#PreUpdate
public void setLastMod(Message message) {
message.setLastMod(new Date());
}
}
When running this the MessageListener is not being invoked. I use a DAO design pattern and when calling dao.update(Message) it throws the following Exception:
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.persistence.entities.MessageStatus.lastMod; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.persistence.entities.Message.lastMod
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:665)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:683)
at com.persistence.dao.hibernate.GenericHibernateDAO.save(GenericHibernateDAO.java:38)
Having looked at a number of websites there seems not to be a solution.
You don't appear to be using an EntityManager, rather straightforward Hibernate SessionFactory. Another answer, Hibernate/JPA - Entity listener not being called properly, seems to suggest that this will not work without manually setting up the listeners.
In order to have JPA listeners working with Hibernate using SessionFactory and thus being able to use the annotations (#PostPersist, #PostUpdate, ...),
I had to do the following ugly thing, using the JPAIntegrator class.
Here is my Spring bean :
#Autowired
private LocalSessionFactoryBean sessionFactoryBean;
#PostConstruct
public void init() throws ClassNotFoundException {
SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) sessionFactoryBean.getObject();
SessionFactoryServiceRegistry serviceRegistry = (SessionFactoryServiceRegistry)sessionFactory.getServiceRegistry();
Configuration configuration = sessionFactoryBean.getConfiguration();
new JpaIntegrator().integrate(configuration, sessionFactory, serviceRegistry);
}
If it's just to keep a date field updated, you should have a look at the JPA #Version annotation. It's main purpose is to provides Optimistic Locking to manage concurrent update to your data.
I'm trying to configure an example JPA application in Eclipse, and deploy it to TomEE+. The datasource is container managed. I keep seeing the following error when attempting to create the EntityManager:
The persistence provider is attempting to use properties in the persistence.xml file to resolve the data source. A Java Database Connectivity (JDBC) driver or data source class name must be specified in the openjpa.ConnectionDriverName or javax.persistence.jdbc.driver property. The following properties are available in the configuration: "org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl#414793b4".
Any idea what is wrong with this configuration?
Below is the code.
tomee.xml
<tomee>
<Resource id="jdbc/MyAppDS" type="DataSource">
JdbcDriver com.microsoft.sqlserver.jdbc.SQLServerDriver
JdbcUrl jdbc:sqlserver://localhost:1433/db_dev
UserName user
Password password
JtaManaged true
DefaultAutoCommit false
</Resource>
</tomee>
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0">
<persistence-unit name="Simplest" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/MyAppDS</jta-data-source>
<class>social.Media</class>
</persistence-unit>
</persistence>
Media.java
package social;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "media")
public class Media {
#Id
#Column(name = "id")
private String id;
private String description;
private String title;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
Controller.java
package social;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/hello")
public class Controller {
#Inject private Media media;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Simplest");
EntityManager em = emf.createEntityManager(); // exception reported on this line
.
.
.
return media.getDescription();
}
}
You are using JTA-managed Entity Manager Factory, I think that instead of manual creation of EntityManagerFactory you should let application server do it for you, like this in controller:
#Path("/hello")
public class Controller {
#PersistenceContext(unitName="Simplest")
private EntityManager em;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
// get Media from database - replace with your own code
Media media = em.find(Media.class, "1");
return media.getDescription();
}
}