Instantiate service in GUI over spring - java

my problem is that I get a NullPointerException in my GUI. The object that is null should be intatiated by Spring. Please see my applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<context:component-scan base-package="com.Person"
annotation-config="true" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean id="mainGUI" class="com.Person.MainWindow" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost/testDB" />
<property name="username" value="sa" />
<property name="password" value="" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="jpaData" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManager"
class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
I am getting the error here List<Person> test = personService.getAll(), personService is null:
#Component
public class PersonDataPanel extends JPanel {
public PersonTableModel atm;
#Autowired
public PersonServiceImpl personService;
public JPanel placePersonTable() {
log.info("enter placePersonTable method");
JPanel selectionArea = new JPanel(new FlowLayout(FlowLayout.CENTER));
List<Person> test = personService.getAll(); //here I am getting the error
log.info(test.toString());
atm = new PersonTableModel(test);
JTable PersonTable = new JTable(atm);
PersonTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN );
PersonTable.setFillsViewportHeight(true);
repaint();
return selectionArea;
}
}
Why is this the chase for my desktop application? I thought my annotations are correct. I have used #Autowired, so the service should be instantiated?
I really appreciate your answer!
UPDATE
My PersonServiceImpl class:
#Component
public class PersonServiceImpl {
/**
* PersonDAO Access
*/
#Autowired
private PersonDaoImpl PersonDAO;
public List<Person> getAll() {
log.info("reveiving all data in the Person Service");
return PersonDAO.getAll();
}
}

Related

SessionFactory is null with Spring 4 and Hibernate 4

When I try to save data to DB the SessionFactory is null. Find the code below.
Spring configuration
<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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Specifying base package of the Components like Controller, Service, DAO -->
<context:component-scan base-package="com.service.jaxws" />
<!-- Getting Database properties -->
<!-- <context:property-placeholder location="classpath:application.properties" /> -->
<mvc:annotation-driven />
<!-- Specifying the Resource location to load JS, CSS, Images etc -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- View Resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- DataSource -->
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/hrms"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.service.jaxws"></property>
</bean>
<!-- Transaction -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
Repository Bean
#Repository
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addUser(UserBO user) {
if (sessionFactory != null) {
sessionFactory.getCurrentSession().save(user);
} else {
System.out.println("Null");
}
}
}
When debugging each and every time the SessionFactory is null. Could anyone please tell me what I am missing?
Thanks in advance
Serin
Matt the issue has been resolved. The main problem was with the #Autowired. it was not working as expected. I tried this in my #Webservice class. After using the extends SpringBeanAutowiringSupport it is working properly. Anyway thanks for your support.

Configuration hibernate jpa and spring mvc (entityManager is always null)

Good morning , I'm still new with hibernate jpa and spring this is my first projet I make and every time i try to execute it I got npe. This is my code
applicationContext.xml
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dao" class="com.talan.springmvc.dao.AdminDaoImpl">
</bean>
<bean id="metier" class="com.talan.springmvc.metier.AdminMetier">
<property name="dao" ref="dao" />
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:#localhost:1521/XE"></property>
<property name="username" value="system"></property>
<property name="password" value="Islem1992"></property>
</bean>
<bean id="persistenceUnitManager"
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="datasource"></property>
</bean>
<bean id="entityManagerFactory
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"></property>
<property name="dataSource" ref="datasource" />
<property name="persistenceUnitName" value="myapp"></property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">none</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
</bean>
</property>
</bean>
<!-- <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myapp"></property> </bean> -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="myapp"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
</persistence-unit>
</persistence>
Test.java
package test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.talan.springmvc.entities.Agence;
import com.talan.springmvc.entities.User;
import com.talan.springmvc.metier.IAdminMetier;
public class Test {
public static void main(String[] args){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
IAdminMetier admin = (IAdminMetier) context.getBean("metier");
User u = new User(1,"islem", "yeddes", "salesAgent");
admin.addUser(u);
}
}
I forgot to post my DAO
package com.talan.springmvc.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.talan.springmvc.entities.User;
public class AdminDaoImpl implements IAdminDao {
#PersistenceContext
private EntityManager em;
#Override
public User addUser(User u) {
em.persist(u);
return u;
}
}
First of all, there is a problem with your DataSource, which is unable to handle a database pool for db connections.
org.springframework.jdbc.datasource.DriverManagerDataSource is creating a new Connection for each HttpRequest, which is suitable for test purposes only...
Use dbcp from Tomcat:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>8.0.32</version>
</dependency>
or from other providers as c3p0 or vibur which are able to handle that job greatly.
Second, you'll need to add #Service("serviceName") and some #Autowired annotations in order to provide your code dependencies with Spring IoC mecanism. Maybe adding some #ComponentScan("com.talan.springmvc.dao") inside your Service too.
In one of my project, I have a Service which is defined with that:
#Service("utilisateurService")
public class UtilisateurService implements UserDetailsService {
public static final Logger logger = LoggerFactory.getLogger(UtilisateurService.class);
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager newEm){
this.entityManager = newEm;
}
#Override
#Transactional
public UserSpringSecurity loadUserByUsername(final String username) throws UsernameNotFoundException {
}
// etc.
}
And of course there is some beans to define my "utitisateurService". In XML:
<context:annotation-config />
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dsn1" class="org.vibur.dbcp.ViburDBCPDataSource"
init-method="start" destroy-method="terminate">
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="poolInitialSize" value="10" />
<property name="poolMaxSize" value="50" />
<property name="connectionIdleLimitInSeconds" value="30" />
<property name="testConnectionQuery" value="SELECT 1" />
<property name="logQueryExecutionLongerThanMs" value="500" />
<property name="logStackTraceForLongQueryExecution" value="true" />
<property name="statementCacheMaxSize" value="200" />
</bean>
<bean id="crmEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" autowire="byName">
<property name="persistenceUnitName" value="crmPersistenceUnit" />
<property name="dataSource" ref="dsn1" />
<property name="packagesToScan" value="crm.db.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="crmEmf"></property>
</bean>
<tx:annotation-driven proxy-target-class="true" mode="proxy" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<!-- Logging -->
<bean id="loggerListener"
class="org.springframework.security.authentication.event.LoggerListener" />
<bean id="customAuthenticationProvider" class="crm.security.CustomAuthenticationProvider" />
<bean id="utilisateurService" class="crm.service.UtilisateurService"/>
Try that way and tell us if it works!

Spring-dispatcher-servlet.xml to Java Config

Hi i'm trying to convert my Xml configuration to Java Config. I'm really lost now.
Here is the spring-dispatcher-servlet.xml
<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" 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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- package of spring controller -->
<context:component-scan base-package="com.test" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="cacheSeconds" value="0" />
</bean>
<mvc:resources mapping="/Resources/**" location="/Resources/"
cache-period="31556926" />
<bean id="viewResolver1" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="location" value="/WEB-INF/excel-view.xml" />
</bean>
<bean id="viewResolver2"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- setting maximum upload size -->
<property name="maxUploadSize" value="100000" />
</bean>
<!-- Read test.properties -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:test.properties</value>
</property>
</bean>
<bean id="entityManagerFactoryBean"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- This makes /META-INF/persistence.xml is no longer necessary -->
<property name="packagesToScan" value="com.beo.model" />
<!-- JpaVendorAdapter implementation for Hibernate EntityManager. Exposes
Hibernate's persistence provider and EntityManager extension interface -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<!-- <prop key="hibernate.hbm2ddl.auto">create</prop> -->
<!-- <prop key="hibernate.show_sql">true</prop> -->
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<!-- Hikari Config -->
<property name="dataSourceClassName" value="${hikari.dataSourceClassName}" />
<property name="maximumPoolSize" value="${hikari.maximumPoolSize}" />
<property name="maxLifetime" value="${hikari.maxLifetime}" />
<property name="idleTimeout" value="${hikari.idleTimeout}" />
<property name="dataSourceProperties">
<props>
<prop key="url">${jdbc.url}</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
</props>
</property>
</bean>
<!-- This transaction manager is appropriate for applications that use a
single JPA EntityManagerFactory for transactional data access. JTA (usually
through JtaTransactionManager) is necessary for accessing multiple transactional
resources within the same transaction. -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<!-- responsible for registering the necessary Spring components that power
annotation-driven transaction management; such as when #Transactional methods
are invoked -->
<tx:annotation-driven />
</beans>
Here is what i came up for the Java Config.
#Configuration
#EnableWebMvc
#ComponentScan("com.test")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/Resources/**")
.addResourceLocations("/Resources/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public ViewResolver setupViewResolver(ContentNegotiationManager manager) {
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
InternalResourceViewResolver InternalResourceResolver = new InternalResourceViewResolver();
InternalResourceResolver.setPrefix("/WEB-INF/jsp/");
InternalResourceResolver.setSuffix(".jsp");
resolvers.add(InternalResourceResolver);
ContentNegotiatingViewResolver resolver2 = new ContentNegotiatingViewResolver();
resolver2.setViewResolvers(resolvers);
resolver2.setContentNegotiationManager(manager);
return resolver2;
}
}
Thank you so much in advance for the help.

NULL Database Record Returned After Reading Database Record Immediately After Insert

I'm using Spring JMS with the JPA Hibernate implementation and I'm seeing an intermittent issue with a insert and then instant read of the same record.
web application flow:
-Data gets posted to my web applications web service and the data is sent to a Glassfish OpenMQ queue (STUInputQ below).
-com.api.listener.backoffice.STUMessageListener reads the STUInputQ queue and does a insert into our Oracle Database and then sends a message (with the new database primary key) to another queue (ArchiveQ below).
-com.api.listener.backoffice.StorableMessageListener reads the ArchiveQ queue and attempts to do an read of the database using the primary key of the database record that was inserted by com.api.listener.backoffice.STUMessageListener.
Problem:
Sometimes (about 18%) the read operation in StorableMessageListener returns null, even though the record does exist. It seems to me the insert commit hasn't processed before the read occurs even though the insert returns the sequence generated primary key. I've put a unix timestamp at the end of the method that inserts the data and the one that reads it and when the issue occurs the unix timestamps are the same, so it seems as though the read gets the message before the commit is final.
Temporary Solution:
I've added some logic to sleep the thread and that ensures that I never get a null with the database read. I don't really think the thread sleep is a long term solution. Any ideas on why it seems the STUMessageListener isn't able to commit the transaction before the StorableMessageListener reads it?
Dependencies:
hibernate-core.3.3.2.GA
hibernate-entitymanager-3.4.0.GA
spring 3.0.6.RELEASE
Java 1.5
Spring Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:hz="http://www.hazelcast.com/schema/spring"
xsi:schemaLocation="
http://www.hazelcast.com/schema/spring
http://www.hazelcast.com/schema/spring/hazelcast-spring-2.5.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-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-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- Generic -->
<context:annotation-config />
<context:component-scan base-package="myapp.api" />
<aop:aspectj-autoproxy/>
<!-- JPA -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="persistenceUnitName" value="MyApp" />
<property name="jpaProperties">
<props>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.archive.autodetection">class</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">com.hazelcast.hibernate.provider.HazelcastCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_minimal_puts">true</prop>
</props>
</property>
</bean>
<hz:hazelcast id="instance">
<hz:config>
//rest of Hazelast config maps here
</hz:config>
</hz:hazelcast>
<hz:hibernate-region-factory id="regionFactory" instance-ref="instance"/>
<!-- Define JPA Provider Adapter -->
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.OracleDialect" />
</bean>
<bean id="dataSourceTarget" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close">
<property name="URL" value="jdbc:oracle:thin:#server:1525:name" />
<property name="user" value="test" />
<property name="password" value="123" />
<property name="connectionCachingEnabled" value="true" />
<property name="connectionCacheProperties">
<props merge="default">
<prop key="MinLimit">5</prop>
<prop key="MaxLimit">50</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="dataSourceTarget"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false"/>
<bean id="genericDAO" class="myapp.api.dao.impl.GenericDAOImpl">
<constructor-arg>
<value>java.io.Serializable</value>
</constructor-arg>
</bean>
<bean id="springContextHolder" class="myapp.api.util.SpringContextHolder" factory-method="getInstance" />
<bean id="executionInterceptor" class="myapp.api.listener.backoffice.ExecutionInterceptor" />
<!-- JNDI-->
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"/>
<!-- JMS -->
<bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate"/>
</property>
<property name="jndiName" value="${jms.jndi.qconnectionfactory}">
</property>
</bean>
<bean id="myJMSConnectionFactory" class="com.api.model.vo.backoffice.OpenMqConnectionFactoryBean">
<property name="imqAddressList" value="${jms.imq.url}" />
<property name="imqDefaultUsername" value="${jms.imq.user}" />
<property name="imqDefaultPassword" value="${jms.imq.password}" />
<property name="imqHost" value="${jms.imq.host}" />
<property name="imqPort" value="${jms.imq.port}" />
</bean>
<bean id="stuMessageListener" class="com.api.listener.backoffice.STUMessageListener" />
<bean id="storeListener" class="com.api.listener.backoffice.StorableMessageListener"/>
<bean id="executionInterceptor" class="com.api.listener.backoffice.ExecutionInterceptor" />
<bean id="stuJmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
<property name="destinationName" value="STUInputQ"/>
<property name="sessionTransacted" value="false"/>
<property name="messageListener" ref="stuMessageListener" />
<property name="concurrentConsumers" value="5" />
<property name="maxConcurrentConsumers" value="100" />
<property name="receiveTimeout" value="30000" />
<property name="cacheLevelName" value="CACHE_NONE" />
</bean>
<bean id="storeJmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
<property name="destinationName" value="ArchiveQ"/>
<property name="sessionTransacted" value="false"/>
<property name="messageListener" ref="storeListener" />
<property name="concurrentConsumers" value="5" />
<property name="maxConcurrentConsumers" value="100" />
<property name="receiveTimeout" value="30000" />
<property name="cacheLevelName" value="CACHE_NONE" />
</bean>
</beans>
Persistence Configuration:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="com" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>
Classes that insert record:
public class STUMessageListener implements javax.jms.MessageListener{
#Autowired
StoringService storingService;
#Transactional
public void onMessage(Message message) throws RuntimeException {
try {
Object omsg = ((ObjectMessage) message).getObject();
if (omsg instanceof StorableMessage) {
StorableMessage storableMessage = (StorableMessage) omsg;
//StorableMessage insert into Database
storingService.store(storableMessage);
//jms logic here to send message to next queue (ArchiveQ)
}
catch (Throwable ex) {
throw new RuntimeException(ex);
}
}
#Service("storingService")
public class StoringServiceImpl{
#Autowired
MessagesDAO messagesDAO;
#Transactional
public StorableMessage store(StorableMessage storableMessage) {
messagesDAO.save(storableMessage);
}
}
#Repository("messagesDAO")
public class MessagesDAOImpl{
private Class<T> type
#PersistenceContext
EntityManager entityManager;
public void save(T object) {
entityManager.persist(object);
}
public T findById(Serializable id) {
return entityManager.find(type, id);
}
}
Classes that Read the Database Record:
public class StorableMessageListener implements javax.jms.MessageListener {
#Autowired
MessageDAO messageDAO;
#Transactional
public void onMessage(Message message) throws RuntimeException {
if (omsg instanceof StorableMessage) {
//this is where null is returned for the Messages object 18% of the time
//sleep thread by 1 second logic here helps eliminate the null Messages object
//uses same MessageDAO as above
Messages msg = messageDAO.findById(storableMessage.getMessageKey());
}
}
Try to change the annotation of the insert method as
#Transactional(propagation = Propagation.REQUIRES_NEW)
This will commit the insert as soon as the method finishes.

If TransactionProxyFactoryBean is used for service layer bean then is there any need of transaction annotation driven in dao?

The interface for service layer is :
EMS.java:
public interface EMS extends UserDetailsService {
public void saveUser(User user);
}
and its implementation:
EMSImpl.java:
#Service("emsImpl")
#Transactional(readOnly=true)
public class EMSImpl implements EMS {
private final Logger logger = LoggerFactory.getLogger(getClass());
#Autowired
#Qualifier("dao")
private EMSDao dao;
#Transactional(readOnly=false)
public void saveUser(User user) {
dao.saveUser();
}
}
The interface for dao:
EMSDao.java:
public interface EMSDao {
public void saveUser(User user);
}
And its implementation:
HibernateEMSDao.java
#Repository("EMSDao")
public class HibernateEMSDao extends HibernateDaoSupport implements EMSDao {
private final Logger logger = LoggerFactory.getLogger(getClass());
private SchemaHelper schemaHelper;
public void setSchemaHelper(SchemaHelper schemaHelper) {
this.schemaHelper = schemaHelper;
}
#Transactional(readOnly=false)
public synchronized void saveUser(final User user) {
Session session = getSessionFactory().getCurrentSession();
session.merge(user);
}
private void storeUser(User user) {
getHibernateTemplate().save(user);
}
public void createSchema() {
try {
getHibernateTemplate().find("from User user where user.id = 1");
} catch (Exception e) {
logger.warn("expected database schema does not exist, will create. Error is: " + e.getMessage());
schemaHelper.createSchema();
User admin = new User();
admin.setUsername("admin");
admin.setName("Admin");
admin.setEmail("admin");
admin.setPassword("21232f297a57a5a743894a0e4a801fc3");
admin.setRoles(new HashSet<Role>(Arrays.asList(new Role("admin", "ADMINISTRATOR"))));
logger.info("inserting default admin user into database");
storeUser(admin);
logger.info("schema creation complete");
return;
}
logger.info("database schema exists, normal startup");
}
}
The bean ems in appliactionContext.xml is created by TransactionProxyFactoryBean. Also I am using <tx:annotation-driven />
The complete applicationContext.xml is:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean class="info.ems.config.EMSConfigurer"/>
<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
<bean id="ems" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target">
<bean class="info.ems.EMSImpl" init-method="init">
<property name="dao" ref="dao"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
<property name="localeList" value="${ems.locales}"/>
<property name="releaseVersion" value="${ems.version}"/>
<property name="releaseTimestamp" value="${ems.timestamp}"/>
<property name="emsHome" value="${ems.home}"/>
</bean>
</property>
<property name="transactionAttributes">
<props>
<prop key="store*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="bulkUpdate*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="dataSource" class="info.ems.datasource.DataSourceFactory">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="validationQuery" value="${database.validationQuery}"/>
<property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>/WEB-INF/hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</prop>
</props>
</property>
</bean>
<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
<property name="hibernateTemplate">
<bean class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
<property name="schemaHelper">
<bean class="info.ems.hibernate.SchemaHelper">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="hibernateDialect" value="${hibernate.dialect}"/>
<property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
</bean>
</property>
</bean>
</beans>
I want to know:
Is it the right configuration for handling database transaction by spring?
Is it needed to use TransactionProxyFactoryBean along with <tx:annotation-driven />?
Any information or web-link where I can get example will be very helpful.
Thanks and regards.
Edit: after getting suggestion from skaffman the modified appliactionContext.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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean class="info.ems.config.EMSConfigurer"/>
<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
<bean id="ems" class="info.ems.EMSImpl" init-method="init">
<property name="dao" ref="dao"/>
<property name="passwordEncoder" ref="passwordEncoder"/>
<property name="localeList" value="${ems.locales}"/>
<property name="releaseVersion" value="${ems.version}"/>
<property name="releaseTimestamp" value="${ems.timestamp}"/>
<property name="emsHome" value="${ems.home}"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="dataSource" class="info.ems.datasource.DataSourceFactory">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="validationQuery" value="${database.validationQuery}"/>
<property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>/WEB-INF/hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</prop>
</props>
</property>
</bean>
<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
<property name="hibernateTemplate">
<bean class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
<property name="schemaHelper">
<bean class="info.ems.hibernate.SchemaHelper">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="hibernateDialect" value="${hibernate.dialect}"/>
<property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
</bean>
</property>
</bean>
</beans>
Is it the right configuration for handling database transaction by spring?
It's perfectly valid, but it's confusing and duplicates work. This will probably generate two layers of transactional proxies, although I doubt that will behave any differently.
As you say, you probably don't want to use both TransactionProxyFactoryBean and <tx:annotation-driven /> at the same time.
Your TransactionProxyFactoryBean config is using externalised method name patterns to decide which methods get which transaction semantics. This is fine, although with current versions of Spring it's usually easier to use annotations instead of the transactionAttributes property on TransactionProxyFactoryBean.
Given your config, I suggest getting rid of the explicit TransactionProxyFactoryBean bean definition (<tx:annotation-driven /> will create its own one as required, behind the scenes). Replace that with the undecorated EMSImpl, and <tx:annotation-driven /> will generate the transaction proxy automatically.

Categories

Resources