I have an application based on Spring and hibernate.
My task is to create two connectors in this application to database - one connector is only to READ and second is to READ, WRITE etc.
How my configuration should looks like.
Now in WEB-INF folder i have 3 files:
hibernate-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:p="http://www.springframework.org/schema/p"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<context:property-placeholder location="/WEB-INF/spring.properties" />
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
<!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="${hibernate.config}"
p:packagesToScan="com.esb.scs"/>
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${app.jdbc.username}"
p:password="${app.jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
</beans>
hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>
spring.properties:
# database properties
app.jdbc.driverClassName=com.mysql.jdbc.Driver
app.jdbc.url=jdbc:mysql://localhost/database
app.jdbc.username=user
app.jdbc.password=password
#hibernate properties
hibernate.config=/WEB-INF/hibernate.cfg.xml
how can i create two connections to database in one application?
My question is becouse i have two databases with replication, where one is only for read and the secound is for write...
With your help i've created file like this:
<?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"
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/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<context:property-placeholder location="/WEB-INF/spring.properties" />
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven transaction-manager="transactionManagerr" />
<!-- Declare the Hibernate SessionFactory for retrieving Hibernate sessions -->
<!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/SessionFactory.html -->
<!-- See http://docs.jboss.org/hibernate/stable/core/api/index.html?org/hibernate/Session.html -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="${hibernate.config}"
p:packagesToScan="com.esb.scs"/>
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${app.jdbc.username}"
p:password="${app.jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory" />
<bean id="sessionFactoryr" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
p:dataSource-ref="dataSourcer"
p:configLocation="${hibernate.config}"
p:packagesToScan="com.esb.scs"/>
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSourcer" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}"
p:user="${appr.jdbc.username}"
p:password="${appr.jdbc.password}"
p:acquireIncrement="5"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="100"
p:maxStatements="50"
p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManagerr" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactoryr" />
</beans>
and now when i have in service :
#Resource(name="sessionFactory")
private SessionFactory sessionFactory;
#Resource(name="sessionFactoryr")
private SessionFactory sessionFactoryr;
and when i trying to make query with sessionFactoryr
i get Error:
No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
but i have
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
in web.xml
To set up two transaction managers, just declare them in your app context, I use a properties file and read in connection details. I set what type of access hibernate has in that prop file (and also restrict permissions on the db server) :
<bean id="sessionFactoryOne"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" p:configLocation="WEB-INF/classes/hibernate.cfg.xml"
p:packagesToScan="com.mycompany" />
<bean id="dataSourceONE" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" p:driverClass="${app.jdbc.driverClassName}"
p:jdbcUrl="${app.jdbc.url}" p:user="${app.jdbc.username}" p:password="${app.jdbc.password}"
p:acquireIncrement="5" p:idleConnectionTestPeriod="60" p:maxPoolSize="10"
p:maxStatements="50" p:minPoolSize="10" />
<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory">
<bean id="sessionFactoryTWO" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSourceTWO"
p:configLocation="WEB-INF/classes/hibernateTWO.cfg.xml"
p:packagesToScan="com.mycompany"/>
<!-- Declare a datasource that has pooling capabilities-->
<bean id="dataSourceTWO" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close"
p:driverClass="${two.jdbc.driverClassName}"
p:jdbcUrl="${two.jdbc.url}"
p:user="${two.jdbc.username}"
p:password="${two.jdbc.password}"
p:acquireIncrement="2"
p:idleConnectionTestPeriod="60"
p:maxPoolSize="5"
p:maxStatements="50"
p:minPoolSize="1" />
<!-- Declare a second transaction manager-->
<bean id="transactionManagerTWO" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactoryTWO">
<qualifier value="Traveller"/>
and then you can reference them like in yr service layer like so :
#Resource(name = "sessionFactoryTWO")
private SessionFactory sessionFactoryTWO;
#Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
then for methods in your service layer you will have to make methods transactional :
#Transactional(readOnly = true)
public void myReadOnlyMethod(Whatever whatever)
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void myWriteMethod(Whatever whatever)
Related
With Spring 4.3.5, we have been using an application architecture where we initialize some of the beans at a go and then use the beans as "Reference" for other beans.
Something like this
<bean id="handleUncheckedEndpointExceptionAdvice"
class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
<constructor-arg ref="exceptionFactory"/>
<property name="exceptionSenderService" ref="exceptionSenderService" />
</bean>
But once we upgraded our library to Spring 5.2.x, we started getting the below exception at Jboss 7.3.1 startup:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handleUncheckedEndpointExceptionAdvice' defined in ServletContext resource [/WEB-INF/context-web.xml]: Cannot resolve reference to bean 'exceptionSenderService' while setting bean property 'exceptionSenderService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'exceptionSenderService' available
What all I did:
Enabled TRACE logging and found this - 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.InjectionMetadata] (ServerService Thread Pool -- 65) Processing injected element of bean 'exceptionSenderService': AutowiredFieldElement for private com.gehcit.cp.serviceability.service.ExceptionSenderService com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl.exceptionSender 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.support.DefaultListableBeanFactory] (ServerService Thread Pool -- 65) Returning cached instance of singleton bean 'exceptionSenderServiceImpl' 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] (ServerService Thread Pool -- 65) Autowiring by type from bean name 'exceptionSenderService' to bean named 'exceptionSenderServiceImpl'
Now the bean is getting initialized but when the reference is being searched, being searched from the Spring cache, we get nothing.
But then we tried shifting the bean initialization from a different xml to the same xml where the bean is being referred and that worked. So we concluded that somehow the cross XML configurations are not working.
Bean being referred from context-web.xml
<?xml version="1.0"?>
<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:cxf="http://cxf.apache.org/core"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/security
https://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/security/oauth2
https://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<task:annotation-driven/>
<!-- Define placeholder for application properties -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/web.properties</value>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
<!-- Load CXF modules from cxf.jar -->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<import resource="context-cem-web.xml"/>
<!-- define an auto-proxy generator for our advisors -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<property name="proxyTargetClass" value="false"/>
</bean>
<!-- id generator for exceptions -->
<bean id="exceptionIdGenerator"
class="com.gehcit.cp.ws.infrastructure.exception.HostTimeExceptionIdGenerator">
<property name="prefix" value="CEN"/>
</bean>
<!-- system fault factory -->
<bean id="systemFaultFactory"
class="com.gehcit.cp.ws.infrastructure.exception.StandardSystemFaultFactory">
<property name="exceptionIdGenerator" ref="exceptionIdGenerator"/>
<property name="appendExceptionIdToErrorMessage" value="true"/>
</bean>
<bean id="defaultParamConverterProvider"
class="org.apache.cxf.jaxrs.ext.search.DefaultParamConverterProvider"/>
<!-- factory for mapping runtime exceptions to wire faults -->
<bean id="exceptionFactory"
class="com.gehcit.cp.ws.infrastructure.exception.ExceptionMapperExceptionFactory">
<property name="exceptionMappers">
<list>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.IllegalArgumentFaultFromIllegalArgumentExceptionMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.SecurityFaultFromCPSecurityExceptionMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.ApplicationFaultFromApplicationErrorMapper"/>
<bean
class="com.gehcit.cp.ws.infrastructure.exception.SystemFaultFromRuntimeExceptionMapper">
<constructor-arg ref="systemFaultFactory"/>
</bean>
</list>
</property>
</bean>
<!-- aspect for handling unchecked endpoint exceptions -->
<bean id="handleUncheckedEndpointExceptionAdvice"
class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
<constructor-arg ref="exceptionFactory"/>
<property name="exceptionSenderService" ref="exceptionSenderService" />
</bean>
<bean id="handleUncheckedEndpointExceptionPointcut"
class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
<constructor-arg type="java.lang.Class">
<null/>
</constructor-arg>
<constructor-arg type="java.lang.Class"
value="com.gehcit.cp.ws.infrastructure.aop.annotations.HandleUncheckedEndpointException"/>
</bean>
<bean id="handleUncheckedEndpointExceptionAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="advice" ref="handleUncheckedEndpointExceptionAdvice"/>
<property name="pointcut"
ref="handleUncheckedEndpointExceptionPointcut"/>
</bean>
The bean is being initialized in context-applix.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms.xsd">
<!-- Activemq connection factory start -->
<bean id ="connectionAmqFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL"
value="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"
/>
</bean>
<!-- A POJO that implements the JMS message listener -->
<bean id="aplixSubscriberQueueService"
class="com.gehcit.cp.cem.aplix.jms.listener.AplixSubscriberQueueListener"
/>
<bean id="exceptionSenderService"
class="com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl"
/>
<!-- A destination in ActiveMQ -->
<!--amq:topic id="destination" physicalName="APLIX.ERRORINFO" /-->
<!-- A destination in ActiveMQ -->
<amq:queue id="destination" physicalName="APLIX.ERRORINFO" />
<!-- A destination in ActiveMQ end-->
<!-- A cached connection to wrap the ActiveMQ connection -->
<bean id="cachedAmqConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory"
p:targetConnectionFactory-ref="connectionAmqFactory"
p:sessionCacheSize="10" />
<!-- Adding JMS transaction Manager -->
<bean id="TransactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="cachedAmqConnectionFactory"/>
</bean>
<!-- Adding JMS transaction Manager -End -->
<!-- A JmsTemplate instance that uses the connection and destination -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="cachedAmqConnectionFactory"
p:defaultDestination-ref="destination" />
<!-- A JmsTemplate instance that uses the connection and destination end -->
<!--Cofiguring JMS container and listener-->
<jms:listener-container container-type="default"
connection-factory="cachedAmqConnectionFactory" destination-type="queue" >
<jms:listener destination="APLIX.ERRORINFO"
ref="aplixSubscriberQueueService" method="onMessage" />
</jms:listener-container>
<!--Cofiguring JMS container and listener end-->
<!-- The Spring message listener container configuration -->
<amq:broker start="true" persistent="false"
brokerName="broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"
deleteAllMessagesOnStartup="false" >
<amq:managementContext>
<amq:managementContext createConnector="false"/>
</amq:managementContext>
<amq:systemUsage>
<amq:systemUsage>
<amq:memoryUsage>
<amq:memoryUsage limit="512 mb"/>
</amq:memoryUsage>
<amq:tempUsage>
<amq:tempUsage limit="2 gb"/>
</amq:tempUsage>
</amq:systemUsage>
</amq:systemUsage>
<amq:transportConnectors>
<amq:transportConnector name="vm"
uri="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"/>
</amq:transportConnectors>
</amq:broker>
</beans>
Can someone help me find a way to refer beans from other xml files in Spring 5.2.x.
Note: We have changed the classloading part with Spring 5.2.
Added this to the web.xml
<listener-class>com.gehcit.cp.ws.infrastructure.security.BeanFactoryContextLoaderListener</listener-class>
</listener>
<!-- <context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>/beanRefFactory.xml</param-value>
</context-param> -->
BeanFactoryContextLoaderListener.java
package com.gehcit.cp.ws.infrastructure.security;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
public class BeanFactoryContextLoaderListener extends ContextLoaderListener {
private static Logger log = Logger.getLogger(BeanFactoryContextLoaderListener.class)
#Override
protected ApplicationContext loadParentContext(ServletContext servletContext) {
log.info("Entered loadParentContext");
ApplicationContext ctx = new ClassPathXmlApplicationContext("beanRefFactory.xml");
log.info("Exit loadParentContext" + ctx.toString());
return ctx;
}
}
This has something to do with ApplicationContext which I am unable to resolve.
I am facing a null pointer exception on my app , I am annotating Dao with #Repository , the servive by #Service , controller with #Controller and service inside it with #ManagedProperty, I am suspecting my application context is not well configured so here there 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"
xmlns:context="http://www.springframework.org/schema/context"
xml:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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">
<!-- Enable Spring Annotation Configuration -->
<context:annotation-config/>
<!-- Scan for all of Spring components such as Spring Service -->
<context:component-scan base-package="com.domain.nameOfapp.*" />
<!-- Necessary to get the entity manager injected into the factory bean -->
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<!-- Define Hibernate JPA Vendor Adapter -->
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
<!-- Entity Manager Factory -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="jpa-persistence" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan">
<list>
<value>com.domain.nameOfapp.*</value>
</list>
</property>
</bean>
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Detect #Transactional -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Any help would be great! thanks
Your component scan needs to be as below,
<context:component-scan base-package="com.domain.nameOfapp" />
This will scan all the classes under this package including any sub-packages.
Also using #ManagedProperty, are you trying to autowire the spring service bean? I believe you should be using #Autowired.
I am using Spring 3.2 mvc and Hibernate 4 in my project.
hibernate.cfg.xml
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.validator.apply_to_ddl">false</property>
<property name="hibernate.validator.autoregister_listeners">false</property>
servlet-context.xml
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<security:global-method-security pre-post-annotations="enabled"/>
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.abc" />
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
</beans:beans>
DaoImpl Class:
public void add(Entity entity) {
try {
this.sessionFactory.getCurrentSession().save(entity);
this.sessionFactory.getCurrentSession().flush();
} catch (Exception e) {
logger.error("Exception occured " + e);
}
}
This is my project configuration and dao impl class file.
root-context.xml
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<!-- <tx:annotation-driven transaction-manager="transactionManager" /> -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.abc" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <property name = "dataSource" ref = "dataSource"></property> -->
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="entityInterceptor" ref ="auditLogInterceptor"/>
</bean>
Issue
As of now in hibernate.cfg.xml, I have mentioned hibernate.connection.autocommit = true and in daoimpl while saving entity I need to call flush after .save .
If I remove hibernate.connection.autocommit = true and .flush from daoimpl class, I observed that .save method in daoimpl is not working, means my data is not inserting and even I cannot see insert query executed by hibernate on console.
hibernate.connection.autocommit = true should not be there in hibernate cfg xml as if I doing operation on multiple table in same transaction and if some error occurred then rollback will not happen.
I want that .save in daoimpl should work even I don't write hibernate.connection.autocommit = true in hibernate cfg xml and .flush.
I am using #Transactional annotation for transaction.
You haven't added any TransactionManager to your configuration:
Remove the following properties:
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
Add a connection pooling DataSource (DBCP2 is a much better alternative than C3P0)
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="your-oracle-driver-url"/>
<property name="username" value="your-username"/>
<property name="password" value="your-password"/>
</bean>
Now add the Sessionfactory Spring proxy:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
Add the TransactionManager bean
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Update
If you have the transaction manager set in a separate spring application context (e.g. root-context.xml), then move these lines from your web context to where the back-end context:
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.abc.service" />
<context:component-scan base-package="com.abc.dao" />
And only allow the web context to scan its own beans:
<context:component-scan base-package="com.abc.web" />
It's not good to mix the web and the back-end contexts responsibilities.
My problem solved, I just wrote the annotation #Transactional in the
#Repository
#Transactional
public class AbstractHibernateDao<T extends Serializable> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
And that solved that I couldnt Delete or Save without using Flush.
I am trying to get the following configured.
Spring, Hibernate, Jboss 5.1, Mysql 5.14
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:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring- mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="au.com.kiche" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- Most controllers will use the ControllerClassNameHandlerMapping above,
but for the index controller we are using ParameterizableViewController,
so we must define an explicit mapping for it. -->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
<!-- the following bean description should be moved to applicationContext. I'm leaving this decision to Chief. -->
<jee:jndi-lookup id="dataSource" jndi-name="java:/MyDS"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
hibernate.cfg.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration- 3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.datasource">java:/MyDS</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.show_sql">true</property>
<mapping class="au.com.kiche.model.User"/>
</session-factory>
</hibernate-configuration>
The data source file "kiche-ds.xml" is:
<datasources>
<local-tx-datasource>
<jndi-name>MyDS</jndi-name>
<connection-url>jdbc:mysql://localhost:3306/kiche</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>root</user-name>
<password>root5</password>
<min-pool-size>5</min-pool-size>
<max-pool-size>100</max-pool-size>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
<!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml -->
<metadata>
<type-mapping>mySQL</type-mapping>
</metadata>
</local-tx-datasource>
</datasources>
The followis is my class that is try to get all users from the DB:
#Repository
public class UserDAOImpl implements UserDAO{
#Autowired
SessionFactory sessionFactory;
#Override
public List<User> getUserByLogin() {
Criteria criteria=sessionFactory.getCurrentSession().createCriteria(User.class);
List<User> users=criteria.list();
System.out.println("**** The size of the user is: "+users.size());
return users;
}
.
.
.
}
The strange part is that I am able to get the data form the DB when I use Tomcat(not the one with JBOSS). But when I try to run this application in JBOSS, NO data is retrived, there are no errors or exceptions.
Any help will be highly appraciated.
Regards
Adofo
You should use the Java EE convention of resource mapping. For your case:
application context:
<jee:jndi-lookup id="dataSource"
jndi-name="MyDS"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"
resource-ref="true"
/>
WEB-INF/web.xml:
<resource-ref>
<res-ref-name>MyDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
WEB-INF/jboss-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC
"-//JBoss//DTD Web Application 4.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
<jboss-web>
<resource-ref>
<res-ref-name>MyDS</res-ref-name>
<jndi-name>java:MyDS</jndi-name>
</resource-ref>
</jboss-web>
This will work for both JBoss and pure Tomcat.
I have just started with Spring Framework and trying to develop and run a simple a app using Spring + Hibernate + Maven for dependency management.
I have a ContactController in which a property of type ContactService is Autowired. But when i packaged it into war and deployed on tomcat it throws a org.springframework.beans.factory.BeanCreationException with following messages :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'sessionFactory' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]:
Invocation of init method failed; nested exception is org.hibernate.MappingException:
An AnnotationConfiguration instance is required to use <mapping
class="org.kodeplay.contact.form.Contact"/>
So I commented out that property from the ContactController Class along with all its references and re deployed it. But still it shows the same error.
This is the only controller in the entire application and an object implementing the ContactService interface is not being used any where else.
Whats going on here ? Am I missing something ?
Edit : Adding the code for spring-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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<context:annotation-config/>
<context:component-scan base-package="org.kodeplay.contact" />
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Internationalization -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- To load database connection details from jdbc.properties file -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<!-- To establish a connection to the database -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<!-- Hibernate configuration -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
<list>
<value>org.kodeplay.contact.form.Contact</value>
</list>
</property>
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
code for hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="org.kodeplay.contact.form.Contact" />
</session-factory>
</hibernate-configuration>
Thanks
I suspect this be a clash between AnnotationSessionFactoryBean and hibernate.cfg.xml. If you're using the former, you shouldn't need the latter. If you use both, you're going to have to duplicate some settings, and the cfg file might be eclipsing the Spring config.
Whatever you have in hibernate.cfg.xml you should be able to move into the bean definition for the AnnotationSessionFactoryBean, and that should resolve your error.
I guess you try to configure Hibernate with org.springframework.orm.hibernate3.LocalSessionFactoryBean. However, you use annotations in Hibernate mapping, therefore you need to use org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean instead.