Current implementation forcibly binds ANY jdbc connection to current
transaction (if any) regardless on the kind of that transaction and declared
need in such binding. This obviously works only in case of XA or when
bridging the same datasource.
I have a working (at least for me :-) ) implementation of JDBC transport
(Connector, Transaction etc.), that overloades getConnection by
getConnection(UMOImmutableEndpoint endpoint) and doesn't bind a connection
to the transaction if not explicitly required. This allows to utilize
RollbackExceptionStrategy to discard transactional changes (e.g. made by
.ack statement) assuming that non-transactional ones have not been made due
to the failure.
Can anybody explain the idea behind the current implementation or the
drawbacks of mine? Actually I plan to donate my code to the project but not
sure whether anybody needs it :-)
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17079142.html
Sent from the Mule - User mailing list archive at Nabble.com.
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email
Andrew, in both cases:
if (tx != null) //I suggest smth like &&
endpoint.getTransactionConfig().isTransacted()
{
logger.debug("Binding connection to current transaction");
try
{
tx.bindResource(dataSource, con);
}
catch (TransactionException e)
{
JdbcUtils.close(con);
throw new RuntimeException("Could not bind connection to
current transaction", e);
}
}
Maybe it's possible to bind different transactions to one service flow, but
here an attempt is made to bind different resources to a single-resource
JDBC transaction, that obviously fails. I'm talking about
I don't see any difference, could you shed some light on it?
Dmitry
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17083150.html
Andrew,
I'm sorry, but I don't understand you. Here's my 1.4.4 example:
<mule-descriptor name="bridge"
implementation="org.mule.components.simple.BridgeComponent">
<inbound-router>
<endpoint address="jdbc://read"
connector="jdbcINConnector">
<transaction action="ALWAYS_BEGIN"
factory="org.mule.providers.jdbc.JdbcTransactionFactory" />
</endpoint>
</inbound-router>
<outbound-router>
<router
className="org.mule.routing.outbound.OutboundPassThroughRouter">
<endpoint address="jdbc://write"
connector="jdbcOUTConnector">
</endpoint>
</router>
</outbound-router>
<exception-strategy className="org.mule.impl.DefaultExceptionStrategy"/>
</mule-descriptor>
It fails because of [unauthorized] attempt to bind a new resource to a
single-resource transaction. Note that outbound endpoint is defined as
non-transactional, but is made transactional due to some reason nobody can
explain me :-)
Here's a log:
********************************************************************************
Message : Only a single resource can be bound to this type of
transaction
Type :
org.mule.transaction.IllegalTransactionStateException
Code : MULE_ERROR-91380
JavaDoc :
http://mule.mulesource.org/docs/apidocs/org/mule/transaction/IllegalTransactionStateException.html
********************************************************************************
Exception stack is:
1. Only a single resource can be bound to this type of transaction
(org.mule.transaction.IllegalTransactionStateException)
org.mule.transaction.AbstractSingleResourceTransaction:130
(http://mule.mulesource.org/docs/apidocs/org/mule/transaction/IllegalTransactionStateException.html)
********************************************************************************
Root Exception stack trace:
org.mule.transaction.IllegalTransactionStateException: Only a single
resource can be bound to this type of transaction
at
org.mule.transaction.AbstractSingleResourceTransaction.bindResource(AbstractSingleResourceTransaction.java:130)
at
org.mule.providers.jdbc.JdbcTransaction.bindResource(JdbcTransaction.java:55)
at
org.mule.providers.jdbc.JdbcConnector.getConnection(JdbcConnector.java:469)
at
org.mule.providers.jdbc.JdbcMessageDispatcher.executeWriteStatement(JdbcMessageDispatcher.java:106)
at
org.mule.providers.jdbc.JdbcMessageDispatcher.doSend(JdbcMessageDispatcher.java:240)
at
org.mule.providers.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:224)
at org.mule.providers.AbstractConnector.send(AbstractConnector.java:1629)
at org.mule.impl.ImmutableMuleEndpoint.send(ImmutableMuleEndpoint.java:950)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:327)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:210)
at
org.mule.routing.outbound.AbstractOutboundRouter$2.doInTransaction(AbstractOutboundRouter.java:147)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:40)
at
org.mule.routing.outbound.AbstractOutboundRouter.send(AbstractOutboundRouter.java:154)
at
org.mule.routing.outbound.FilteringOutboundRouter.route(FilteringOutboundRouter.java:66)
at
org.mule.routing.outbound.OutboundPassThroughRouter.route(OutboundPassThroughRouter.java:79)
at
org.mule.routing.outbound.OutboundRouterCollection$1.doInTransaction(OutboundRouterCollection.java:66)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:40)
at
org.mule.routing.outbound.OutboundRouterCollection.route(OutboundRouterCollection.java:71)
at
org.mule.routing.inbound.ForwardingConsumer.process(ForwardingConsumer.java:84)
at
org.mule.routing.inbound.InboundRouterCollection.route(InboundRouterCollection.java:86)
at
org.mule.providers.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:581)
at
org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:322)
at
org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:257)
at
org.mule.providers.jdbc.JdbcMessageReceiver.processMessage(JdbcMessageReceiver.java:106)
at
org.mule.providers.TransactedPollingMessageReceiver$MessageProcessorWorker.doInTransaction(TransactedPollingMessageReceiver.java:194)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:108)
at
org.mule.providers.TransactedPollingMessageReceiver$MessageProcessorWorker.run(TransactedPollingMessageReceiver.java:180)
at org.mule.impl.work.WorkerContext.run(WorkerContext.java:310)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Thread.java:595)
********************************************************************************
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.transaction.TransactionTemplate: Exception caught: rollback
transaction
org.mule.umo.routing.RoutingException: Failed to route event via endpoint:
MuleEndpoint{endpointUri=jdbc://read, connector=JdbcConnector{this=510e39,
started=true, initialised=true, name='jdbcINConnector', disposed=false,
numberOfConcurrentTransactedReceivers=4,
createMultipleTransactedReceivers=true, connected=true,
supportedProtocols=[jdbc], serviceOverrides=null}, transformer=null,
name='endpoint.jdbc.read', type='receiver', properties={},
transactionConfig=Transaction{factory=org.mule.providers.jdbc.JdbcTransactionFactory@1958cc2,
action=ALWAYS_BEGIN, timeout=30000}, filter=null,
deleteUnacceptedMessages=false, initialised=true, securityFilter=null,
synchronous=null, initialState=started, createConnector=0, remoteSync=false,
remoteSyncTimeout=null, endpointEncoding=null}. Message payload is of type:
BasicRowProcessor$CaseInsensitiveHashMap
at
org.mule.routing.inbound.ForwardingConsumer.process(ForwardingConsumer.java:99)
at
org.mule.routing.inbound.InboundRouterCollection.route(InboundRouterCollection.java:86)
at
org.mule.providers.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:581)
at
org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:322)
at
org.mule.providers.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:257)
at
org.mule.providers.jdbc.JdbcMessageReceiver.processMessage(JdbcMessageReceiver.java:106)
at
org.mule.providers.TransactedPollingMessageReceiver$MessageProcessorWorker.doInTransaction(TransactedPollingMessageReceiver.java:194)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:108)
at
org.mule.providers.TransactedPollingMessageReceiver$MessageProcessorWorker.run(TransactedPollingMessageReceiver.java:180)
at org.mule.impl.work.WorkerContext.run(WorkerContext.java:310)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.mule.umo.routing.RoutingException: Failed to route event via
endpoint: null. Message payload is of type:
BasicRowProcessor$CaseInsensitiveHashMap
at
org.mule.routing.outbound.OutboundRouterCollection.route(OutboundRouterCollection.java:75)
at
org.mule.routing.inbound.ForwardingConsumer.process(ForwardingConsumer.java:84)
... 12 more
Caused by: org.mule.umo.routing.CouldNotRouteOutboundMessageException:
Failed to route event via endpoint: MuleEndpoint{endpointUri=jdbc://write,
connector=JdbcConnector{this=12c5431, started=true, initialised=true,
name='jdbcOUTConnector', disposed=false,
numberOfConcurrentTransactedReceivers=4,
createMultipleTransactedReceivers=true, connected=true,
supportedProtocols=[jdbc], serviceOverrides=null}, transformer=null,
name='endpoint.jdbc.write', type='sender', properties={},
transactionConfig=Transaction{factory=null, action=NONE, timeout=30000},
filter=null, deleteUnacceptedMessages=false, initialised=true,
securityFilter=null, synchronous=null, initialState=started,
createConnector=0, remoteSync=null, remoteSyncTimeout=null,
endpointEncoding=null}. Message payload is of type:
BasicRowProcessor$CaseInsensitiveHashMap
at
org.mule.routing.outbound.FilteringOutboundRouter.route(FilteringOutboundRouter.java:75)
at
org.mule.routing.outbound.OutboundPassThroughRouter.route(OutboundPassThroughRouter.java:79)
at
org.mule.routing.outbound.OutboundRouterCollection$1.doInTransaction(OutboundRouterCollection.java:66)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:40)
at
org.mule.routing.outbound.OutboundRouterCollection.route(OutboundRouterCollection.java:71)
... 13 more
Caused by: org.mule.umo.routing.RoutingException: Failed to route event via
endpoint: null. Message payload is of type:
BasicRowProcessor$CaseInsensitiveHashMap
at
org.mule.routing.outbound.AbstractOutboundRouter.send(AbstractOutboundRouter.java:158)
at
org.mule.routing.outbound.FilteringOutboundRouter.route(FilteringOutboundRouter.java:66)
... 17 more
Caused by: org.mule.umo.provider.DispatchException: Failed to route event
via endpoint: MuleEndpoint{endpointUri=jdbc://write,
connector=JdbcConnector{this=12c5431, started=true, initialised=true,
name='jdbcOUTConnector', disposed=false,
numberOfConcurrentTransactedReceivers=4,
createMultipleTransactedReceivers=true, connected=true,
supportedProtocols=[jdbc], serviceOverrides=null}, transformer=null,
name='endpoint.jdbc.write', type='sender', properties={},
transactionConfig=Transaction{factory=null, action=NONE, timeout=30000},
filter=null, deleteUnacceptedMessages=false, initialised=true,
securityFilter=null, synchronous=null, initialState=started,
createConnector=0, remoteSync=null, remoteSyncTimeout=null,
endpointEncoding=null}. Message payload is of type:
BasicRowProcessor$CaseInsensitiveHashMap
at
org.mule.providers.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:252)
at org.mule.providers.AbstractConnector.send(AbstractConnector.java:1629)
at org.mule.impl.ImmutableMuleEndpoint.send(ImmutableMuleEndpoint.java:950)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:327)
at org.mule.impl.MuleSession.sendEvent(MuleSession.java:210)
at
org.mule.routing.outbound.AbstractOutboundRouter$2.doInTransaction(AbstractOutboundRouter.java:147)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:40)
at
org.mule.routing.outbound.AbstractOutboundRouter.send(AbstractOutboundRouter.java:154)
... 18 more
Caused by: java.lang.RuntimeException: Could not bind connection to current
transaction
at
org.mule.providers.jdbc.JdbcConnector.getConnection(JdbcConnector.java:473)
at
org.mule.providers.jdbc.JdbcMessageDispatcher.executeWriteStatement(JdbcMessageDispatcher.java:106)
at
org.mule.providers.jdbc.JdbcMessageDispatcher.doSend(JdbcMessageDispatcher.java:240)
at
org.mule.providers.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:224)
... 25 more
Caused by: org.mule.transaction.IllegalTransactionStateException: Only a
single resource can be bound to this type of transaction
at
org.mule.transaction.AbstractSingleResourceTransaction.bindResource(AbstractSingleResourceTransaction.java:130)
at
org.mule.providers.jdbc.JdbcTransaction.bindResource(JdbcTransaction.java:55)
at
org.mule.providers.jdbc.JdbcConnector.getConnection(JdbcConnector.java:469)
... 28 more
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.transaction.TransactionTemplate: Transaction has been marked
rollbackOnly, rolling it back:
org.mule.providers.jdbc.JdbcTransaction@134263a
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.providers.jdbc.JdbcTransaction: Rolling back transaction
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.config.i18n.MessageFactory: Loading resource bundle:
META-INF.services.org.mule.i18n.core-messages for locale uk_US
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.config.i18n.MessageFactory: Loading resource bundle:
META-INF.services.org.mule.i18n.core-messages for locale uk_US
DEBUG 2008-05-06 18:46:56,484 [jdbcINConnector.receiver.2]
org.mule.config.i18n.MessageFactory: Loading resource bundle:
META-INF.services.org.mule.i18n.core-messages for locale uk_US
ERROR 2008-05-06 18:46:56,500 [jdbcINConnector.receiver.2]
org.mule.impl.DefaultExceptionStrategy:
********************************************************************************
Message : Transaction rollback failed
Type : org.mule.transaction.TransactionRollbackException
Code : MULE_ERROR-92098
JavaDoc :
http://mule.mulesource.org/docs/apidocs/org/mule/transaction/TransactionRollbackException.html
SQL Code : 17008
SQL State : 99999
********************************************************************************
Exception stack is:
1. Closed Connection(SQL Code: 17008, SQL State: + 99999)
(java.sql.SQLException)
oracle.jdbc.driver.SQLStateMapping:70
(http://java.sun.com/j2se/1.5.0/docs/api/java/sql/SQLException.html)
2. Transaction rollback failed
(org.mule.transaction.TransactionRollbackException)
org.mule.providers.jdbc.JdbcTransaction:85
(http://mule.mulesource.org/docs/apidocs/org/mule/transaction/TransactionRollbackException.html)
********************************************************************************
Root Exception stack trace:
java.sql.SQLException: Closed Connection
at
oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:110)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:171)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:227)
at
oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:439)
at
oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:3369)
at
org.mule.providers.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:80)
at
org.mule.transaction.AbstractTransaction.rollback(AbstractTransaction.java:122)
at
org.mule.transaction.AbstractSingleResourceTransaction.rollback(AbstractSingleResourceTransaction.java:62)
at
org.mule.transaction.TransactionTemplate.resolveTransaction(TransactionTemplate.java:183)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:150)
at
org.mule.providers.TransactedPollingMessageReceiver$MessageProcessorWorker.run(TransactedPollingMessageReceiver.java:180)
at org.mule.impl.work.WorkerContext.run(WorkerContext.java:310)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Thread.java:595)
************************************************************
I expect the same with Mule 2.0. There's nothing to do with RESOLUTION, only
BINDING. Or am I missing something obvious?
Dmitry
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17086264.html
<service name="JDBC Bridge">
<inbound>
<jdbc:inbound-endpoint address="jdbc://read"
connector-ref="jdbcINConnector">
<jdbc:transaction action="ALWAYS_BEGIN" />
</jdbc:inbound-endpoint>
</inbound>
<outbound>
<outbound-pass-through-router>
<jdbc:outbound-endpoint address="jdbc://write"
connector-ref="jdbcOUTConnector">
<jdbc:transaction action="NONE" />
</jdbc:outbound-endpoint>
</outbound-pass-through-router>
</outbound>
</service>
It fails the same way:
org.mule.transaction.IllegalTransactionStateException: Only a single
resource can be bound to this type of transaction
at
org.mule.transaction.AbstractSingleResourceTransaction.bindResource(AbstractSingleResourceTransaction.java:130)
at
org.mule.transport.jdbc.JdbcTransaction.bindResource(JdbcTransaction.java:55)
at
org.mule.transport.jdbc.JdbcConnector.getConnection(JdbcConnector.java:211)
at
org.mule.transport.jdbc.JdbcMessageDispatcher.executeWriteStatement(JdbcMessageDispatcher.java:73)
at
org.mule.transport.jdbc.JdbcMessageDispatcher.doSend(JdbcMessageDispatcher.java:172)
at
org.mule.transport.AbstractMessageDispatcher.send(AbstractMessageDispatcher.java:157)
at org.mule.transport.AbstractConnector.send(AbstractConnector.java:1889)
at
org.mule.endpoint.DefaultOutboundEndpoint.send(DefaultOutboundEndpoint.java:76)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:324)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:210)
at
org.mule.routing.outbound.AbstractOutboundRouter.send(AbstractOutboundRouter.java:122)
at
org.mule.routing.outbound.FilteringOutboundRouter.route(FilteringOutboundRouter.java:68)
at
org.mule.routing.outbound.OutboundPassThroughRouter.route(OutboundPassThroughRouter.java:70)
at
org.mule.routing.outbound.DefaultOutboundRouterCollection$1.doInTransaction(DefaultOutboundRouterCollection.java:65)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:44)
at
org.mule.routing.outbound.DefaultOutboundRouterCollection.route(DefaultOutboundRouterCollection.java:70)
at
org.mule.service.AbstractService.sendToOutboundRouter(AbstractService.java:894)
at org.mule.model.seda.SedaService.doSend(SedaService.java:235)
at org.mule.service.AbstractService.sendEvent(AbstractService.java:510)
at org.mule.DefaultMuleSession.sendEvent(DefaultMuleSession.java:347)
at
org.mule.routing.inbound.DefaultInboundRouterCollection.send(DefaultInboundRouterCollection.java:196)
at
org.mule.routing.inbound.DefaultInboundRouterCollection.route(DefaultInboundRouterCollection.java:164)
at
org.mule.transport.AbstractMessageReceiver$DefaultInternalMessageListener.onMessage(AbstractMessageReceiver.java:604)
at
org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:346)
at
org.mule.transport.AbstractMessageReceiver.routeMessage(AbstractMessageReceiver.java:275)
at
org.mule.transport.jdbc.JdbcMessageReceiver.processMessage(JdbcMessageReceiver.java:107)
at
org.mule.transport.TransactedPollingMessageReceiver$MessageProcessorWorker.doInTransaction(TransactedPollingMessageReceiver.java:194)
at
org.mule.transaction.TransactionTemplate.execute(TransactionTemplate.java:112)
at
org.mule.transport.TransactedPollingMessageReceiver$MessageProcessorWorker.run(TransactedPollingMessageReceiver.java:180)
at org.mule.work.WorkerContext.run(WorkerContext.java:310)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
at
edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
at java.lang.Thread.run(Thread.java:595)
And of course (since one and the only condition to bind to a transaction is
its existence) the same error I get with action="ALWAYS_BEGIN" on outbound
endpoint.
Any other suggestions how to make current JDBC connector implementation to
work in predictable manner? IMHO action "NONE" and "ALWAYS_BEGIN" should
NOT bind resource to current transaction.
Dmitry
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17105937.html
work in predictable manner? IMHO action "NONE"
and "ALWAYS_BEGIN" should
NOT bind resource to current transaction.
I tested this first with 1.3.2 if I remember :-).
Since then I maintain my own personal branch of this transport as I want to
get the features I described above along with nice enhancements added by
others.
As the [b]intended[/b] behaviour is not known for me (I always supposed that
BEGIN means "start new, not join" and NONE means "just do nothing", but this
was just my opinion), then I can not state that this is an issue. Thus I
posted it to the User forum as a matter for discussion rather than a claim.
Note, that at this moment I'm the only who brings it up, so probably others
are satisfied with the current state. If so, I'll just continue to work with
my own version.
Dmitry
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17106211.html
Your last suggestion doesn't work either, though with another error.
Starting a new transaction on outbound router closes (commits) a currently
running one, thus in case of outbound failure the last can not be rolled
back.
I don't know where you've found it, but the example from the cookbook is
much simpler
(http://mule.mulesource.org/display/MULECB/Jms+Provider+Bridging). Actually
I started my "branch" right after discovering that JMS connector allows such
constructs with single resource transactions and does check
endpoint.getTransactionConfig().isTransacted() before attempting to bind.
Maybe I'm a bit annoying but I do try to make JDBC behaviour the same as
JMS, which I find more reasonable.
BTW could you recommend some reading about the difference between Mule
transactions and all other ones?
Dmitry.
--
View this message in context: http://www.nabble.com/Binding-JDBC-connection-to-current-transaction-tp17079142p17120967.html