Error TIMEOUT WAITING FOR ACK - RabbitMq Publiser Confirms Async Implementation - asynchronous

We have implemented publisher confirms asynchronously i.e. we have setup callbacks on RabbitTemplates to get response from RabbitMq; but we are getting below exception in the logs:-
{"ts":"02 24 2021 14:33:21.308","th":"connectionFactory4002","tenant":"","user":"null","trxid":"","level":"DEBUG","logger":"org.springframework.amqp.rabbit.connection.PublisherCallbackChannelImpl","msg":Sending confirm PendingConfirm [correlationData=CorrelationData [id=7d329ab2-2472-4222-91d0-9bc68dc405c7] cause=clean channel shutdown; protocol method: #method<channel.close>(reply-code=406, reply-text=TIMEOUT WAITING FOR ACK, class-id=0, method-id=0)] }
"ERROR","logger":"com.rabbitmq.client.impl.ChannelN","msg":{​​​​​[com.rabbitmq.client.impl.ChannelN.waitForConfirmsOrDie(ChannelN.java:254),org.springframework.amqp.rabbit.connection.PublisherCallbackChannelImpl.waitForConfirmsOrDie(PublisherCallbackChannelImpl.java:676),org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler.lambda$asyncClose$1(CachingConnectionFactory.java:1371),java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142),java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617),java.lang.Thread.run(Thread.java:745)]}​​​​​ ,"ERR": {​​​​​ java.util.concurrent.TimeoutException
at com.rabbitmq.client.impl.ChannelN.waitForConfirms(ChannelN.java:223)
at com.rabbitmq.client.impl.ChannelN.waitForConfirmsOrDie(ChannelN.java:249)
at org.springframework.amqp.rabbit.connection.PublisherCallbackChannelImpl.waitForConfirmsOrDie(PublisherCallbackChannelImpl.java:676)
at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$CachedChannelInvocationHandler.lambda$asyncClose$1(CachingConnectionFactory.java:1371)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
--Connection Factory Config
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="#{messagingProperties['mq.hostname']}" />
<property name="virtualHost" value="#{messagingProperties['mq.virtual-host']}" />
<property name="username" value="#{messagingProperties['mq.username']}" />
<property name="password" value="#{messagingProperties['mq.password']}" />
<property name="connectionTimeout" value="10000"/>
<property name="channelRpcTimeout" value="60000"/>
<property name="channelCacheSize" value="25" />
</bean>
We have following queries regarding this :
How to prevent this error/log?
Is there message loss due to the above error?
Apart from resource utilization, is there any side impact of this error?
Do the confirmCallBack/returnCallBack call this method(waitForConfirmsOrDie) behind the scenes?

Related

Switch on/off IBM MQ listener based on flag from DB

This is an existing monolith app and fix is required without a drastic change of the setup.
Project setup:
project 1 (config) - > where all mq-xml files are present (e.g - ibm_mq_config.xml)
e.g - content of dev_bm_mq.xml
${hname}
${port}
${qmgr}
1
<!-- JMS Queue Connection Factory -->
<bean id="jmsQueueIdsConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="mqIdsConnectionFactory" />
</property>
</bean>
<!-- JMS Destination Resolver -->
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.DynamicDestinationResolver">
</bean>
<!-- JMS Queue Template -->
<bean id="jmsQueueIdsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="jmsQueueIdsConnectionFactory" />
</property>
<property name="defaultDestinationName">
<value>${myQUEUE}</value>
</property>
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="receiveTimeout">
<value>20000</value>
</property>
</bean>
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="destinationName">
<value>${myQUEUE}</value>
</property>
<property name="messageListener" ref="simpleMessageListener" />
<property name="concurrentConsumers" value="2" />
<property name="maxConcurrentConsumers" value="3" />
<property name="idleTaskExecutionLimit" value="4" />
<property name="maxMessagesPerTask" value="4" />
<property name="receiveTimeout" value="5000" />
<property name="recoveryInterval" value="5000" />
<property name="sessionTransacted" value="true" />
</bean>
****Project B (App)****
loads the spring xml from project config as below:
WebContent/WEB-INF/spring/sprint-context.xm
<import resource="classpath*:com/my/package/${config.env}-${config-broker}.mq.xml"
public class TestMessageListener implements MessageListener {
public void onMessage(Message message) {
//process the message
}
}
When the server starts up, it's able to start the server and setup the listener without any issues.
Issue with the above setup : When we scale the app horizontally (add few nodes ), it's gives max channel issues which I am trying to solve.
Requirement:
based on a DB table I want to turn off the mq listener on few nodes on the fly. or when I horizontally scale the app.
e.g -
Table:mq-config
|host|broker|flag
-----------------------------
|qa5|ibm|false
|qa2|ibm|true
So, I want mq listener on qa5 not to start and qa2 to start and listen to the Queue. Also, I want to stop/start listener on the fly (just by updating the DB)
Question - Any thoughts on how do I achieve the above use case without re-writing the entire setup.
Inject the listener container (e.g. #Autowired).
Then
jmsContainer.stop();
jmsContainer.shutdown();
...
jmsContainer.initialize();
jmsContainer.start();
You can also set the autoStartup property to false to prevent the container from starting during application initialization (but don't call initialize() before the first start() - only after calling shutdown().

Spring Integration Proxy Settings using HttpCllient

I am using spring integration 4.1.2 (ws and core) trying to use HTTPClient (apache) on transport.
I thought that following some reading and configuring the messageSender and messageFactory Spring would use the settings configured on XML (application context) but the configuration is not working as expected.
My xml to configure the HttpClient follows:
<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig" factory-method="custom">
<property name="socketTimeout" value="${saog.connection.timeout}" />
<property name="connectTimeout" value="${saog.connection.timeout}" />
</bean>
<bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />
<bean id="httpHostProxy" class="org.apache.http.HttpHost">
<constructor-arg index="0" value="10.1.6.91" ></constructor-arg>
<constructor-arg index="1" value="80"></constructor-arg>
</bean>
<!-- <property name="defaultHeaders" ref="defaultHeaders"></property> -->
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
<property name="defaultRequestConfig" ref="requestConfig" />
<property name="proxy" ref="httpHostProxy"></property>
</bean>
<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build" />
<bean id="httpComponentsClientHttpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
</bean>
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory">
</bean>
<bean id="defaultMessageSender" class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<constructor-arg ref="httpClient"/>
</bean>
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender" ref="defaultMessageSender" />
</bean>
From here using the ws:outbound-gateway i am facing some problems with configuration:
I made a service with the following parameter as configuration:
<ws:outbound-gateway
uri="${server.address}/${endpoint}"
interceptor="anintercerptor"
message-factory="messageFactory" message-sender="defaultMessageSender">
<ws:request-handler-advice-chain>
<ref bean="retryAdvice" />
</ws:request-handler-advice-chain>
</ws:outbound-gateway>
But when I'm debugging the proxy is not being set (but the timeout it is and the timeout is in the same bean config). and the ApplicationServer is throwing an exception and by my surprise the transport (http) is the JavaNative transport.
A sample of the error follow bellow:
java.io.IOException:
java.net.ConnectException: Connection timed out: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:412)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:271)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:258)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:376)
at java.net.Socket.connect(Socket.java:546)
at java.net.Socket.connect(Socket.java:495)
at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:437)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:551)
at com.ibm.net.ssl.www2.protocol.https.c.<init>(c.java:143)
at com.ibm.net.ssl.www2.protocol.https.c.a(c.java:67)
at com.ibm.net.ssl.www2.protocol.https.d.getNewHttpClient(d.java:55)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:935)
at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:10)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1043)
at com.ibm.net.ssl.www2.protocol.https.b.getOutputStream(b.java:62)
at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:85)
at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:106)
at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:64)
at com.ibm.ws.webservices.utils.LowFlushFilter.write(LowFlushFilter.java:70)
at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:355)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:425)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:429)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:175)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:274)
at com.ibm.ws.webservices.utils.BufferedWriter.flush(BufferedWriter.java:318)
at com.ibm.ws.webservices.engine.SOAPPart.writeTo(SOAPPart.java:841)
at com.ibm.ws.webservices.engine.Message.writeTo(Message.java:669)
at org.springframework.ws.soap.saaj.SaajSoapMessage.writeTo(SaajSoapMessage.java:275)
at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:46)
at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:654)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:603)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
at org.springframework.integration.ws.SimpleWebServiceOutboundGateway.doHandle(SimpleWebServiceOutboundGateway.java:93)
at org.springframework.integration.ws.AbstractWebServiceOutboundGateway.handleRequestMessage(AbstractWebServiceOutboundGateway.java:188)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler$AdvisedRequestHandler.handleRequestMessa
And clue how to solve the Proxy config setting using the HttpClient on SpringIntegration?
Regards.
Jose Carlos Canova.

WSO2 APIM The system cannot infer the transport information from the /devtest/1.0/users/admin

Hi I have an API with a custom sequence (dblookup & switch sequence) that will verify if a user is existing on the database, if not it should send a http status 401: Unauthorized, below is the case code but I always get an error cannot infer the transport information. What is the correct way of sending the back the response message.
THanks,
Drew
<case regex="0">
<log level="custom">
<property name="ucount" expression="fn:concat('User login - ', get-property('employee_count'))"/>
</log>
<send>
<property name="RESPONSE" value="true" scope="default"/>
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<property name="HTTP_SC" value="401" scope="axis2"/>
<header name="To" action="remove"/>
<payloadFactory media-type="xml">
<format>
<response>
<result>Unauthorized</result>
</response>
</format>
<args/>
</payloadFactory>
<send/>
</case>
ERROR:
TID: [0] [AM] [2014-12-02 08:16:30,852] ERROR {org.apache.synapse.core.axis2.Axis2Sender} - Unexpected error during sending message out {org.apache.synapse.core.axis2.Axis2Sender}
org.apache.axis2.AxisFault: The system cannot infer the transport information from the /devtest/1.0/users/admin URL.
at org.apache.axis2.description.ClientUtils.inferOutTransport(ClientUtils.java:81)
at org.apache.synapse.core.axis2.DynamicAxisOperation$DynamicOperationClient.executeImpl(DynamicAxisOperation.java:115)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:149)
at org.apache.synapse.core.axis2.Axis2FlexibleMEPClient.send(Axis2FlexibleMEPClient.java:482)
at org.apache.synapse.core.axis2.Axis2Sender.sendOn(Axis2Sender.java:59)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.send(Axis2SynapseEnvironment.java:338)
at org.apache.synapse.mediators.builtin.SendMediator.mediate(SendMediator.java:94)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.config.xml.AnonymousListMediator.mediate(AnonymousListMediator.java:30)
at org.apache.synapse.config.xml.SwitchCase.mediate(SwitchCase.java:66)
at org.apache.synapse.mediators.filters.SwitchMediator.mediate(SwitchMediator.java:123)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:77)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
at org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler.mediate(APIManagerExtensionHandler.java:64)
at org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler.handleRequest(APIManagerExtensionHandler.java:180)
at org.apache.synapse.rest.API.process(API.java:285)
at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:83)
at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:64)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:220)
at org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:83)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:344)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:168)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
TID: [0] [AM] [2014-12-02 08:16:30,853] INFO {org.apache.synapse.mediators.builtin.LogMediator} - STATUS = Executing default 'fault' sequence, ERROR_CODE = 0, ERROR_MESSAGE = Unexpected error during sending message out {org.apache.synapse.mediators.builtin.LogMediator}
Within send mediator you can not define other mediators.
Correct like this;
<property name="RESPONSE" value="true" scope="default"/>
<property name="NO_ENTITY_BODY" action="remove" scope="axis2"/>
<property name="HTTP_SC" value="401" scope="axis2"/>
<header name="To" action="remove"/>
<payloadFactory media-type="xml">
<format>
<response>
<result>Unauthorized</result>
</response>
</format>
<args/>
</payloadFactory>
<send>
endpoint>
<address uri="ADDRESS OF YOUR ENDPOINT"/>
</endpoint>
</send>
In my case there were invisible characters prepended to otherwise correct (Production/Sandbox) URL.
WSO2 seems very strict and didn't manage to interpret such definition, resulting in vague error:
The system cannot infer the transport information from the https://...
Notice the two spaces between the and https. It may have been a tabulator character.

Spring Transaction Management with legacy JDBC

I am trying to inject Spring Transaction Management on to legacy JDBC code.But it fails in transaction management.
My Spring.xml
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#sbsvmlx101.suntecsbs.com:1521:orcl11g" />
<property name="username" value="XLRT2_TEST_MAIN" />
<property name="password" value="XLRT2_TEST_MAIN" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
and annotated my service method with #Transactional.
#Transactional
public void createEmp(Employee employee, DataSourceTransactionManager dataSourceTransactionManager)throws Exception {
generaldao.createEmployee(employee,dataSourceTransactionManager);
}
I am trying to insert data into two different tables.First one got successfully inserted,and knowingly i made an error in second insertion ,expecting that the both insertions won't happen.
But surprisingly ,the first insertion got committed, and second has shown oracle error.
DAO
con = DataSourceUtils.doGetConnection(dataSource);
con.setAutoCommit(false);
insert = con.prepareStatement
("insert into emp500 values(?,?,?)");
insert.setInt(1, 1);
insert.setString(2, "test");
insert.setString(3, "data");
insert.execute();
insertdept = con.prepareStatement
("insert into department values(?,?)");
insertdept.setInt(1, 2);
insertdept.setString(2, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); //too large value for the column
insertdept.execute();
Please advice.
Thanks in Advance

Spring+Hibernate: No session found in the thread

I have made a project which is built on Maven+Spring 3.1+Spring MVC 3.1+Hibernate 4.1
In the transaction if I use the code:
Session session=sessionFactory.getCurrentSession();
session.save(user);
It gives the exception at the getCurrentSession():
SEVERE: Servlet.service() for servlet appServlet threw exception
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1024)
at com.company.cv.dao.UserDAO.saveUser(UserDAO.java:30)
at com.company.cv.service.UserService.saveUser(UserService.java:20)
at com.company.cv.HomeController.saveUser(HomeController.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
But if I use openSession instead of getCurrentSession no exceptions and code transaction completes successfully:
Session session = sessionFactory.openSession();
session.save(user);
What is the reason?
Thanks for the help
My applicationContext.xml:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/companycv" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.company.cv.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
servlet-context.xml:
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<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>
<context:component-scan base-package="com.company.cv" />
My service code:
#Service
public class UserService implements UserServiceIntf{
#Autowired
UserDAOIntf userDAO;
#Transactional
public void saveUser(User user) {
userDAO.saveUser(user);
}
}
My DAO code:
#Repository
public class UserDAO implements UserDAOIntf {
#Autowired
SessionFactory sessionFactory;
public void saveUser(User user) {
Session session=sessionFactory.getCurrentSession();
session.save(user);
}
}
You need add #Transactional annotation above your service method calling DAO method save. And since you have txManager defined in your app context you need not to manually manage the transactions.
One thing that I have observed you are doing wrong is that you are mixing the usage of Hibernate transaction API with the Spring managed transactions management abstraction. This is strictly not advised.
Session session=sessionFactory.getCurrentSession();
Transaction tx=session.beginTransaction(); // This is using Hibernate transaction API
session.save(user);
sessionFactory.getCurrentSession().save(user);
tx.commit();// This is using Hibernate transaction API
In the above code you are using hibernate transaction api to manage the transaction along with the Spring transaction management (when you annotate your Service method with transactional annotation)
You need to only use this
Session session=sessionFactory.getCurrentSession();
session.save(user);
sessionFactory.getCurrentSession().save(user);
Also as pointed out by others you have got duplicate datasource definitions listed.
And you mention that you can’t get sessionFactory which does not make sense as it is injected via Spring and you say that in the other case you have access to sessionFactory. There is no reason why this should happen.
UPDATE
So you are saying that you do have sessionFactory accessible in both cases but it’s not working in case of getCurrentSession. Having made all the changes suggested, the best advise will be to see what’s happening under the hood by enabling the Hibernate logging and Spring framework logging in log4j configuration ( if you are using log4j) track the relevant activity.
Your log4j configuration file would be something like this
# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=<file-path>
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
# Root logger
log4j.rootLogger=INFO, file
# Hibernate and Spring logging
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.springframework.transaction=DEBUG
This would give you a clear picture.
It was because of Hibernate4. If you look at the Hibernate4 DOC like I should have done in the first place ( :D ) Hibernate4 you have openSession every time. I think Hibernate guys made it so that noobies like me will be forced to use new session every time. Because session is not thread safe. FYI Hibernate openSession() vs getCurrentSession()

Resources