Spring SockJS unable to find registered handlers - spring

I have registered handler for the SockJS service as
#Bean
public SimpleUrlHandlerMapping handlerMapping() {
SockJsService sockJsService = new DefaultSockJsService(sockJsTaskScheduler());
Map<String, Object> urlMap = new HashMap<String, Object>();
urlMap.put("/sockjs/cobrowse/agent/**", new SockJsHttpRequestHandler(sockJsService, coBrowseSockJsAgentHandler()));
urlMap.put("/sockjs/cobrowse/customer/**", new SockJsHttpRequestHandler(sockJsService, coBrowseSockJsCustomerHandler()));
urlMap.put("/sockjs/cobrowse/admin/**", new SockJsHttpRequestHandler(sockJsService, coBrowseSockJsAdminHandler()));
SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
hm.setOrder(-1);
hm.setUrlMap(urlMap);
return hm;
}
But when I try calling from client using one of registered URLs, it throws an exception!
org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator - ERROR - Closing due to exception for SockJS session id=8cf_1l_6
java.lang.IllegalArgumentException: WebSocketHandler not found for SockJS session id=8cf_1l_6
at org.springframework.util.Assert.isTrue(Assert.java:65)
at org.springframework.web.socket.support.PerConnectionWebSocketHandler.getHandler(PerConnectionWebSocketHandler.java:91)
at org.springframework.web.socket.support.PerConnectionWebSocketHandler.handleTransportError(PerConnectionWebSocketHandler.java:97)
at org.springframework.web.socket.support.ExceptionWebSocketHandlerDecorator.handleTransportError(ExceptionWebSocketHandlerDecorator.java:79)
at org.springframework.web.socket.support.WebSocketHandlerDecorator.handleTransportError(WebSocketHandlerDecorator.java:64)
at org.springframework.web.socket.support.LoggingWebSocketHandlerDecorator.handleTransportError(LoggingWebSocketHandlerDecorator.java:66)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.delegateError(AbstractSockJsSession.java:188)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.tryCloseWithSockJsTransportError(AbstractSockJsSession.java:255)
at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.initializeDelegateSession(WebSocketServerSockJsSession.java:122)
at org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler.afterConnectionEstablished(SockJsWebSocketHandler.java:72)
at org.springframework.web.socket.adapter.StandardWebSocketHandlerAdapter.onOpen(StandardWebSocketHandlerAdapter.java:93)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:130)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:653)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1584)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1543)
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:722)
This is even more surprising because same code was running till yesterday -No major changes on my side. My guess is, it's something to do with spring jars, may be nightly update -I am using "4.0.0.BUILD-SNAPSHOT", but then I do not have previous libs!
Posting it here, if someone have came across this, meanwhile I am trying to get hold of old libs to try out - i do not know how to get it from official repo (Older version of same release!).

I spend couple of hours comparing my code against repository and tried to figure out what went wrong -when I was confident enough that I have not broken anything, I guessed that it might be that its due to the latest JAR. I use maven so my repo got updated today morning. Since libs are from Spring -this guess has to com last!
My guess turned out to be correct -when I replaced current version "4.0.0.BUILD-20130823.020236" with an earlier one which is "4.0.0.BUILD-20130814.154539-172" -Issue got resolved. Thanks a lot microsoft recycle bin!

Related

NPE SpringLookupInitializer createLookup Spring-Vaadin 19+

In trying to update to the latest version of Vaadin (20 at time of question), my application will not start due to NPE in the SpringLookupInitializer. When I was using Vaadin 19, which is where SpringLookupInitializer first started being used and I first started encountering the error I had to always use Spring-Vaadin 12.4.0 for the application to start up. The error seems to be coming from this change...
In 12.4.0 there is code in SpringLookupInitializer defined as:
#Override
protected Lookup createLookup(VaadinContext context,
Map<Class<?>, Collection<Class<?>>> services) {
WebApplicationContext appContext = getApplicationContext(context);
return new SpringLookup(appContext,
(spi, impl) -> instantiate(appContext, spi, impl), services);
}
private WebApplicationContext getApplicationContext(VaadinContext context) {
VaadinServletContext servletContext = (VaadinServletContext) context;
WebApplicationContext appContext = WebApplicationContextUtils
.getWebApplicationContext(servletContext.getContext());
if (appContext == null) {
// Spring behavior is always unbelievably surprising: under some
// circumstances {#code appContext} may be null even though the app
// context has been set via ApplicationContextAware: no idea WHY
ApplicationContextWrapper wrapper = context
.getAttribute(ApplicationContextWrapper.class);
appContext = wrapper == null ? null : wrapper.appContext;
}
return appContext;
}
It works this way because it is doing a check and correcting it before proceeding (basically what the comment says). In the newest version the getApplicationContext is removed and the check no longer performed
#Override
protected Lookup createLookup(VaadinContext context,
Map<Class<?>, Collection<Class<?>>> services) {
WebApplicationContext appContext = WebApplicationContextUtils
.getWebApplicationContext(
((VaadinServletContext) context).getContext());
return new SpringLookup(appContext,
(spi, impl) -> instantiate(appContext, spi, impl), services);
}
I am not using spring boot just MVC and everything works fine with the older spring-vaadin version. Is there a reason it no longer performs this check or something else that has been implemented that I can do to stop this from happening?
Thanks
Thanks for the report - it seems that those changes (in PR #740) have been overlooked for the latest versions of the Vaadin Spring add-on. We're going through the changes and making sure those get forward-ported and will be released soon for Vaadin 20 too.
For similar cases, when updating the Vaadin version breaks something, it is recommended to just directly open a new issue to the corresponding repository (like vaadin/spring or vaadin/flow) so it will be noticed immediately by the development team. Thanks
EDIT: The fix has been released in the Vaadin Spring add-on version 17.0.1. You can specify your project to explicitly use that version of vaadin-spring artifact. It will be included in Vaadin 20.0.2 release which is coming by next Monday 14th of June at latest.

Deploying Spring Integration to WebSphere ND 8.5.5

I am looking for some guidance on deploying a simple Spring Integration application to WebSphere. The overall scope of the application is quite simple - it reads from a RabbitMQ endpoint, transforms any messages received to a specific xml format, and then posts the message to a JMS endpoint in WAS.
Initially, I built the application as a JAR. I was able to get it to work well enough with SSL turned off on the IIOP endpoints in WAS, but despite hours of debugging I never could get it to communicate properly with WAS over SSL. The initial handshake and communication with the bootstrap port was successful, but the SIB endpoint rejected the exact same certificate chain with the usual PKIX chaining error, and no amount of certificate importing made any difference.
So I elected to work out deploying the application as a web app into WAS itself, which would have been the end goal anyways. This caused a number of issues that i've had to work through:
I have not gotten properties to work in the normal Spring fashion. I assume that in this context Spring needs to be explicitly told where to look, but i've sidestepped this with hardcoding for now. Perhaps using #Resource annotations would be the way to do this in this context?
Various jar versioning issues, which i've mostly worked out by setting the application classloader as PARENT_LAST, and judiciously removing things that seemed redundant.
Oddly I did have to add some jars related to Parameter validation which don't seem to have been present in my original maven build.
Needing to set some values in the web.xml in order for spring to location configuration beans, specifically setting init-param with contextClass (org.springframework.web.context.support.AnnotationConfigWebApplicationContext) and contextConfigLocation set to a list of the objects that would normally be loaded via the #Configuration annotation.
May or may not be necessary but I did move from Maven to IID in order to hopefully avoid versioning issues with IBM related jars.
Now I would like to know if there are other items generally needed to be done to deploy Spring (especially Spring Integration) to WAS, and whether the above seems like enough.
In addition, I have an issue with the actual JMS connection to WAS. I have tried to use the UserCredentialsConnectionFactoryAdapter, and was successful with this with Spring standalone. However when deployed in WAS, an exception is thrown:
Caused by: java.lang.ClassCastException: com.ibm.ws.sib.api.jms.impl.JmsManagedQueueConnectionFactoryImpl incompatible with javax.jms.ConnectionFactory
I believe this is thrown when the setTargetConnectionFactory method is called, since if I use the connection factory without the UserCredentialsConnectionFactoryAdapter, it works fine, except the connection by "anonymous" is rejected by the bus:
[03/03/21 15:23:32:934 EST] 0000016c SibMessage W [BPM.WorkflowServer.Bus:Node1.server1-BPM.WorkflowServer.Bus] CWSII0212W: The bus BPM.WorkflowServer.Bus denied an anonymous user access to the bus.
If you want to see the code, this works fine (but doesn't authenticate):
#Bean
public ConnectionFactory jmsConnectionFactory() throws NamingException {
ConnectionFactory connectionFactory = null;
Context ctx = null;
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
p.put(Context.PROVIDER_URL, providerUrl);
p.put(Context.SECURITY_AUTHENTICATION,"simple");
p.put(Context.SECURITY_PRINCIPAL,jmsUsername);
p.put(Context.SECURITY_CREDENTIALS,jmsPassword);
ctx = new InitialContext(p);
if (null != ctx)
System.out.println("Got naming context");
connectionFactory = (QueueConnectionFactory) ctx.lookup("javax.jms.QueueConnectionFactory");
if (null != connectionFactory)
System.out.println("Got connection factory");
return connectionFactory;
}
Whereas this throws the class cast exception:
#Bean
public UserCredentialsConnectionFactoryAdapter jmsConnectionFactory() throws NamingException {
ConnectionFactory connectionFactory = null;
Context ctx = null;
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
p.put(Context.PROVIDER_URL, providerUrl);
p.put(Context.SECURITY_AUTHENTICATION,"simple");
p.put(Context.SECURITY_PRINCIPAL,jmsUsername);
p.put(Context.SECURITY_CREDENTIALS,jmsPassword);
ctx = new InitialContext(p);
if (null != ctx)
System.out.println("Got naming context");
connectionFactory = (ConnectionFactory) ctx.lookup("javax.jms.QueueConnectionFactory");
if (null != connectionFactory)
System.out.println("Got connection factory");
UserCredentialsConnectionFactoryAdapter adapter = new UserCredentialsConnectionFactoryAdapter();
adapter.setTargetConnectionFactory(connectionFactory);
adapter.setUsername(jmsUsername);
adapter.setPassword(jmsPassword);
return adapter;
// return connectionFactory;
}
Note: the credentials set in the Context properties seem to have no effect.
I am using this connection factory with Spring Integration Java DSL:
.handle(Jms.outboundAdapter(jmsConfig.jmsConnectionFactory())
.destination(jmsDestination))
I understand from WebSphere documentation that supplying credentials happens on the ConnectionFactory.getConnection() call. So I wonder whether there is any hook in the DSL where I could override the getConnection so as to provide parameters and avoid the class cast exception that I am seeing.
Alternately I am considering just explicitly calling jms template methods to send the message using a lambda in the handler and creating the connection manually.
So, finally what I would like to ask for is:
Any overall guidance on deploying a Spring application to WebSphere traditional
What may be causing the class cast exception
ps, I have placed all of the spring, et al jars in a shared library. This is the contents:
c:/IBM/IID/sharedlibs/spring/accessors-smart-1.2.jar
c:/IBM/IID/sharedlibs/spring/amqp-client-5.10.0.jar
c:/IBM/IID/sharedlibs/spring/android-json-0.0.20131108.vaadin1.jar
c:/IBM/IID/sharedlibs/spring/apiguardian-api-1.1.0.jar
c:/IBM/IID/sharedlibs/spring/asm-5.0.4.jar
c:/IBM/IID/sharedlibs/spring/assertj-core-3.18.1.jar
c:/IBM/IID/sharedlibs/spring/byte-buddy-1.10.19.jar
c:/IBM/IID/sharedlibs/spring/byte-buddy-agent-1.10.19.jar
c:/IBM/IID/sharedlibs/spring/hamcrest-2.2.jar
c:/IBM/IID/sharedlibs/spring/hamcrest-core-2.2.jar
c:/IBM/IID/sharedlibs/spring/hamcrest-library-2.2.jar
c:/IBM/IID/sharedlibs/spring/http-client-3.8.0.RELEASE.jar
c:/IBM/IID/sharedlibs/spring/jackson-annotations-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-core-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-databind-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-dataformat-xml-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-datatype-jdk8-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-datatype-jsr310-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-module-jaxb-annotations-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jackson-module-parameter-names-2.11.4.jar
c:/IBM/IID/sharedlibs/spring/jakarta.activation-api-1.2.2.jar
c:/IBM/IID/sharedlibs/spring/jakarta.annotation-api-1.3.5.jar
c:/IBM/IID/sharedlibs/spring/jakarta.el-3.0.3.jar
c:/IBM/IID/sharedlibs/spring/json-path-2.4.0.jar
c:/IBM/IID/sharedlibs/spring/json-smart-2.3.jar
c:/IBM/IID/sharedlibs/spring/jsonassert-1.5.0.jar
c:/IBM/IID/sharedlibs/spring/objenesis-3.1.jar
c:/IBM/IID/sharedlibs/spring/reactive-streams-1.0.3.jar
c:/IBM/IID/sharedlibs/spring/reactor-core-3.4.2.jar
c:/IBM/IID/sharedlibs/spring/snakeyaml-1.27.jar
c:/IBM/IID/sharedlibs/spring/spring-amqp-2.3.4.jar
c:/IBM/IID/sharedlibs/spring/spring-aop-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-beans-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-autoconfigure-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-starter-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-starter-amqp-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-starter-json-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-starter-logging-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-boot-starter-web-2.4.2.jar
c:/IBM/IID/sharedlibs/spring/spring-context-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-core-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-expression-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-integration-amqp-5.4.3.jar
c:/IBM/IID/sharedlibs/spring/spring-integration-core-5.4.3.jar
c:/IBM/IID/sharedlibs/spring/spring-integration-jms-5.4.3.jar
c:/IBM/IID/sharedlibs/spring/spring-integration-xml-5.4.3.jar
c:/IBM/IID/sharedlibs/spring/spring-jcl-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-jms-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-messaging-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-oxm-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-rabbit-2.3.4.jar
c:/IBM/IID/sharedlibs/spring/spring-rabbit-junit-2.3.4.jar
c:/IBM/IID/sharedlibs/spring/spring-retry-1.3.1.jar
c:/IBM/IID/sharedlibs/spring/spring-tx-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-web-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-webmvc-5.3.3.jar
c:/IBM/IID/sharedlibs/spring/spring-xml-3.0.10.RELEASE.jar
c:/IBM/IID/sharedlibs/spring/stax2-api-4.2.1.jar
c:/IBM/IID/sharedlibs/spring/woodstox-core-6.2.4.jar
c:/IBM/IID/sharedlibs/spring/xmlunit-core-2.7.0.jar
c:/IBM/IID/sharedlibs/spring/slf4j-api-1.7.30.jar
c:/IBM/IID/sharedlibs/spring/jakarta.validation-api-2.0.2.jar
c:/IBM/IID/sharedlibs/spring/hibernate-validator-6.1.7.Final.jar
c:/IBM/IID/sharedlibs/spring/jboss-logging-3.4.1.Final.jar
c:/IBM/IID/sharedlibs/spring/classmate-1.5.1.jar
c:/IBM/IID/sharedlibs/spring/javax.jms-api-2.0.1.jar
UPDATE
So what I finally realized is that:
WAS 8.5.5 is using J2EE v6, which means JMS 1.1
Spring JMS is using JMS 2.0
When I switched to using the UserCredentialsConnectionFactoryAdapter, this tries to use the JmsContext interface which is part of JMS 2.0 classes, and not provided by the WAS jee container, so this was the reason for the class cast exception.
What I did was to do the JMS sending manually instead of using any spring integration gateway. A better solution might be to create my own adapter that extends connection factory and uses credentials in the connect method, but this works well enough for now:
.handle( m -> {
try {
jmsConfig.sendMessage( m.getPayload().toString() );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} )
JmsConfig being a bean that manages the connection.

QFJ upgrade issue from 2.1.1 to 2.2.0 due to XMLConstants.ACCESS_EXTERNAL_DTD

I am trying to upgrade the QFJ version 2.2.0 from 2.1.1 facing below issue.
java.lang.IllegalArgumentException: Property 'http://javax.xml.XMLConstants/property/accessExternalDTD' is not recognized.
at org.apache.xerces.jaxp.DocumentBuilderFactoryImpl.setAttribute(Unknown Source)
I have analysed this is because of QFJ DataDictionary.java's load method using below code.
private void load(InputStream inputStream) throws ConfigError {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
...}
Reason of error is not clearly understood by me(please try to explain) but found that Xerces, xercesImpl jar causing this error.
we are using these jar in some our project code that is why it is needed.
Can anyone try to explain why we have placed these lines? and we are placing then it should be under try and catch block. Is there any way to fix it. Without doing source code changes provide by QFJ.
Answer from QFJ team really appreciated.

Tomcat 8 + Spring #EnableAsync = app deployment error

I'm a mobile developer trying to develop a server side app ;-(. It is going well but now, I am facing an annoying problem, trying to run a method in asynchronous way using Spring multitasking. Basically the method is sending an email. I was reading a little about #Async spring annotation and tried to use it in my implementation.
In order to do this I had created this class:
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
#Configuration
#EnableAsync
public class AsynchConfiguration
{
#Bean(name = "asyncExecutor")
public Executor asyncExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(3);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("AsynchThread-");
executor.initialize();
return executor;
}
}
And then in my email service I added a new method:
#Async("asyncExecutor")
public void lostPetSeeAddressAsync(String nameComplete, String to, String petName, String ip, String address, String lat, String lon) throws MessagingException {
lostPetSeeAddress(nameComplete, to, petName, ip, address, lat, lon);
}
Which is just calling my previous synchro method to send emails (lostPetSeeAddress).
But after this code Tomcat is failing to deploy the app. If I remove the AsynchConfiguration class it works well. I tried to set the Async on my xml config but it is failing in the same way. The annoying part of this is the lack of error messages in Tomcat's console.
Perhaps somebody can help me with what I need to do or at least with some hint about how to debug or where to get logs about where and why is Tomcat failing.
Thanks in advance.
Edit: This is the error trace on Eclipse console, when deploy fail:
INFO: Server startup in 33305 ms
Jan 30, 2020 9:37:46 AM org.apache.coyote.http11.AbstractHttp11Processor process
INFO: Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the HTTP protocol
at org.apache.coyote.http11.AbstractNioInputBuffer.parseRequestLine(AbstractNioInputBuffer.java:345)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1065)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I finally got an error message and could solve the problem. It was caused by a cyclic dependency on com.lowagie library for itext. Here the error message:
Caused by: java.lang.IllegalStateException: Unable to complete the scan for annotations for web application [/app] due to a StackOverflowError. Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies. The class hierarchy being processed was [org.bouncycastle.asn1.ASN1EncodableVector->org.bouncycastle.asn1.DEREncodableVector->org.bouncycastle.asn1.ASN1EncodableVector]
After solving the com.lowagie library problem, Spring Async configuration works fine.
This is not a real solution but a hint for other people. Because to be honest I still having no idea about why, adding Async Spring configuration rise com.lowagie cyclic dependency problem. Perhaps Async on Spring is using org.bouncycastle? Weird, but perhaps other Spring wise people can enlighten us.

Pre-bound JDBC Connection found

We have an app that is using hibernate, spring, and DB2 in websphere 7. We have audit triggers and we need to set so the triggers can know the logged in user (we use generic logon to the database). We came up with a new scheme for setting this in a new app so that it can automatically join in new transactions. We overrode the transaction manager and did the work in the doBegin.
These scheme worked great in one app, and seemed to work great in a second app, but now, weeks later, and not consistently (behavior is intermittent and does not happen in local development), we are getting this Pre-bound JDBC Connection found error. Looking online most posts say this is when you use two transaction managers against one data source. That is now what we are doing.
I also read one post wondering if it was because he mixed annotation and AOP based transactions. This app does some of that. I don't really buy that theory, but thought I'd mention it.
Exception:
Caused by:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC Connection found! HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.
at java.lang.Throwable.<init>(Throwable.java:67)
at org.springframework.core.NestedRuntimeException.<init>(NestedRuntimeException.java:54)
at org.springframework.transaction.TransactionException.<init>(TransactionException.java:34)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:475)
at gov.usdoj.afms.umc.utils.hibernate.AfmsHibernateTransactionManager.doBegin(AfmsHibernateTransactionManager.java:28)
Code (note that the exception comes from the super.doBegin()):
protected void doBegin(Object arg0, TransactionDefinition arg1) {
super.doBegin(arg0, arg1);
if (!Db2ClientInfo.exists()) {
clearDBProperty();
} else {
setDBProperty(Db2ClientInfo.getClientUserId(), Db2ClientInfo.getClientApplicationId());
}
}
private void setDBProperty(String uId, String appName) {
Session session = getSessionFactory().getCurrentSession();
Properties props = new Properties();
props.setProperty(WSConnection.CLIENT_ID, uId);
props.setProperty(WSConnection.CLIENT_APPLICATION_NAME, appName);
try {
Connection nativeConn = new SimpleNativeJdbcExtractor().getNativeConnection(session.connection());
if (nativeConn instanceof WSConnection) {
WSConnection wconn = (WSConnection) nativeConn;
wconn.setClientInformation(props);
} else {
logger.error("Connection was NOT an instance of WSConnection so client ID and app could not be set");
}
} catch (Exception e) {
throw new RuntimeException("Cannot set DB parameters!", e);
}
}
I just realized I never answered this. It turns out that the exception had nothing whatever to do with our Tx manager. It was the fact that this particular EAR has two apps in it, each pointing to the same data source. Evidently this confuses hibernate. We've plans to separate the apps some day, but creating an identical (except in name) data source and pointing the apps at them separately fixes the issue for now.
Instead of modifying the transaction manager it might be easier (better?) to create a wrapper around your datasource (extending DelegatingDataSource from spring) and override the 2 getConnection methods. For the cleanup you could wrap the connection in a proxy and intercept the close method.
That should be a safer (and easier I guess) way then trying to fiddle with the transaction manager and it works for every technology (JDBC, Hibernate, JPA etc.) as long as you use the wrapped datasource. (The registration could be done with a BeanPostProcessor which detects DataSource instances and simply wraps them in the delegate).
If that is to radical (as it means changing your current applications instead of updating a library). It could be a configuration problem, make sure that you are only loading your configuration (and thus DataSource and TransactionManager) only once, duplicating bean instances might lead to a similair behavior.
For posterity, I just got this problem and the answers here weren't very helpful. We resolved the problem by removing a double import of a core XML file which had the AOP transaction manager definition in it:
<tx:annotation-driven transaction-manager="..."
proxy-target-class="true" />
I'm thinking that it causes there to be 2 transaction managers overlapping the same namespace. To fix it, we moved the imports around so they were being done once.
Hope this helps someone else.

Resources