TransactionSynchronizationRegistry vs TransactionSynchronizationManager - spring

I have an application running no weblogic with ejb, with JTA provided by WLS. Now I am trying to adapt all application to work in tomcat without ejb, using spring instead. Also will use JPATransactionManager that spring provides, instead of JTA.
I used to use TransactionSynchronizationRegistry.getTransactionKey() in order to get tx object and use it for cache purposes. Now I am adapting spring and I have TransactionSynchronizationManager of spring, where I can't findv such an API.
My question is - do you know some analog of TransactionSynchronizationRegistry.getTransactionKey() in spring ?
Or where I could get some unique object with info about transaction?

Problem was solved by using some generated logical transaction ID. This transaction ID is stored by calling TransactionSynchronizationManager.bindResource(key, value) and retrieved by TransactionSynchronizationManager.getResource(key).
However it will not work properly in case if transaction interleaving.
Assume that you have flow with transaction interleaving when upstream transaction A is suspended whereas downstream transaction B is running.
In case if in two this transaction you try to store transaction ID with some key as mentioned above, you could have an issue that you mixing your resources.
In this case recommended use ResourceHolderSupport which is responsible to listen various states of transaction and bind or unbind resources.
In our case assume that tx1 is stores resource = "txID", "123456", and tx1 suspended because tx2 is starting to run, resource holder will unbind resource and when tx1 will be resumed - it will bind it again.

Related

Spring Boot DB connection release mode

Is there a way to control database connection release strategy in Spring Boot? Something like Hibernate's ConnectionReleaseMode?
My test code would be rougly following:
INSERT query
HTTP call
UPDATE query
INSERT and UPDATE queries are their own methods in a repository bean (either extending CrudRepository, or as a Mybatis #Mapper). HTTP call is in it's own bean.
Now my service bean is where I experiment with different #Transactional settings as my ultimate goal is to have these three steps executed within a single transaction.
The problem is, the HTTP call can take hundreds of millis and Spring is holding the database connection during that time. This quickly leads to an empty connection pool, while the connections themselves are idle.
I have done the same experiments with default configuration using spring-boot-starter-data-jpa and also using mybatis-spring-boot-starter.
The only thing which got me closer to my goal was setting spring.jpa.open-in-view=false for data-jpa, which would release db connections in case of not using #Transactional at all or with propagation set to NEVER. It doesn't work if it's all wrapped in a transactin though.
I'm feeling like I'm missing some vital part of the transaction concept in Spring. Though the Spring reference docs mentions release mode only in relation to JTA transaction manager + JEE container + Hibernate.
Transactions are bound to a connection/session so you can't release the connection in the middle of a transaction. You have to finish the transaction to close/release the connection. Keep in mind that a transaction could abort at any time, and since the HTTP call is not "part of" the transaction, but just runs while the transaction is in progress, it won't help you to keep the transaction open while the HTTP call is running. I'd suggest you go with one of the following solutions:
Use a circuit breaker to cancel the HTTP call if it hits a timeout to have an upper bound for how long a connection/transaction can be open/held
Move the HTTP call out of the transaction, either before or after the transaction
Use two database transactions
Note that you could use a transactional Job Scheduler to schedule a job in the first TX. The job could then, with at least once semantics, try to invoke the HTTP call and then continue with the second transaction or do some compensation if something fails.

Running Hazelcast put() and replace() calls in the calling thread

Is it possible to force Hazelcast to run put(), replace(), and delete() methods on the TransactionalMap on the calling thread? I want the XA transaction to carry over from writing to Hazelcast to writing to the database in the MapStore, but Hazelcast is queueing the changes to be run on other threads, so they aren't in the same transaction context.
I've got it set up as a write-through persistence, but I see that it's queueing the TxnSetOperation and running them on a separate thread.
This is in a Spring Boot application using the Hazelcast autoconfiguration with a JPA / Hibernate store backing to PostgreSQL.
MapStore operations don't run in the same transactional context. If you want transactional persistent updates with Hazelcast, you need to use XA transactions and not enable MapStore. Then you can set the persistent store as a different XA resource in your context. You can have a check the related section in Hazelcast's reference manual: http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#providing-xa-transactions
Alsparlan's answer is partially correct, but there's no way to enlist a resource in a MapStore with the same transactional context as your actions against the Hazelcast TransactionalMap. The link he provided does NOT talk about this (unfortunately), but the Javadoc for TransactionalMap does:
When using MapStore, the call to any MapStore method is outside the transactional boundary. If you need to have an XATransaction spanning Hazelcast operations and one more other XAResources (such as a database), you should not use MapStore. Instead, enlist both resources in a transaction
I've removed my MapStore usage and wired my Spring Boot repositories directly into my services so I can make my changes to Hazelcast and my datasource in the same service methods inside the same transaction. Along with this solution to declaratively enlisting the Hazelcast XAResource this is working for me now.

Wildfly 10 jms send Message to queue as part of XA transaction

I have recently had to support a colleague in verifying why some system tests are not passing in wildfly, system tests that pass consistently on weblogic and glass fish.
After analysing the log, it became clear the reason is related to a JMS message sent by a backed thread getting committed to a queue too soon, when the expectation was the message would be committed when the entry point Container Managed Transaction of an MDB commits. So the message is going out before the MDB that sends it is done running.
In weblogic, to achieve the expected behaviour, you need to make sure that when you take the connection factory given by the container , which is XA configured, you set the connection.createseesion with
transacted = true and
acknowledgement = session transacted.
In a process similar to the one depicted in this URL
http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as
Except in the snippet above auto acknowledge is set and the first parameter is set to false.
In wildly when our weblogic and glass fish configuration is used, nothing is committed and the system behaves as if the JMS message sent were to be rolled back.
If configuration as in the example above were to be used, instead what would happen is that the JMS message is immediately and the consumer MDB immediately launches being trigerred before the producer transaction actually ends, causing the system test to fail.
According to the official JMS configuration, by using a connection-pooled factory with the transaction=XA attribute, the container should immediately bind the commit of the transaction to the lifecycle of the parent transaction.
See official documentation bellow in particular in respect to the Java:/JmsXa connection factory.
https://docs.jboss.org/author/display/WFLY10/Messaging+configuration
My colleague was initially using a non pooled connection factory, but the injection info reference has since then been fixed. I have tried all possible combinations of parameters in the shed message, but my outcome is sitll:
Either sent too soon or never sent.
To conclude all the other resources are XA. Namely the oracle db is using the XA driver.
Can anyone confirm if in wildly the send JMS message only when parent transaction commits is working and if so how the session is being configured?
I will check if perhaps my colleague has not made a mistake in terms of the configuration of the connection factory used by the Men's themselves to consume messages out of the queue.but if that one is also XA... Then it is a big problem.
So the issues is fixed.
The commit of the JMS message to the queue at the end of the transaction works perfectly.
The issue was two fold:
(a) First spot of code I was looking at address the issue was not correct. Someone had decided to write his own send telegram to queue API elsewhere, and was not using the central API for sneding telegrams, so any modification I to the injection connection factory was actually not taking effect. The stale connection factories were still being used.
(b) Once the correct API was spotted it was easy to make the mechanism work by using the widlfy XA pooled connection factory mentioned in the post above.
The one thing that was tweaked was the connection.CreationSession api.
The API in JEE 7 has been enlarged and it is now better documented than in jEE 6.
To send a JMS message in a container as part of an XA transaction one should do:
connection.createSession() without any parameters.
This can easily be seen in the connection javadoc:
https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html
QUOTE 1:
This method has been superseded by the method createSession(int
sessionMode) which specifies the same information using a single
argument, and by the method createSession() which is for use in a Java
EE JTA transaction. Applications should consider using those methods
instead of this one.
QUOTE 2:
In a Java EE web or EJB container, when there is an active JTA
transaction in progress:
Both arguments transacted and acknowledgeMode are ignored. The session will participate in the JTA transaction and will be committed
or rolled back when that transaction is committed or rolled back, not
by calling the session's commit or rollback methods. Since both
arguments are ignored, developers are recommended to use
createSession(), which has no arguments, instead of this method.
Which means, the code snippet in:
http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as
Is not appropriate. What one should be doing is creating the session without any parameter and leting the container handle the rest.
Which it does just fine.

Websphere, JAXWS, WS-Transaction - WTRN0127E: Operation blocked by policy type configuration

We have never used the WS-Transaction policy before in Websphere, therefore I am in the process of developing a prototype to evaluate it.
This is how the prototype is structured.
I have developed two applications, APP_A and APP_B using eclipse.
APP_A contains two JAXWS web services, service_X and service_Y
service_X accepts minimal data, writes it to a table on an oracle database and then returns the primary key in the response
service_y accepts the primary key returned from service_X and some other minimal data, writes it to a different table on the same oracle database and then returns the primary key in the response
APP_B contains one JAXWS web service, service_Z
service_z accepts all data required to post a request to service_x and service_y, and does so returning both primary keys returned from service_x and service_y in its response
both APP_A and APP_B are deployed to Websphere 8.5.5.9, and have been tested successfully.
Then via the Websphere admin console, I created a new application policy set and included the ws-transaction policy. I then attached this policy to the provider policies within APP_A and the client policies within APP_B, and then restarted Websphere.
I then submitted a request to APP_B, from the log files I can see that the request is being successfully received by service_z in APP_B, but when it attempts to post a request to service_x in APP_A the following error is reported:
[02/06/16 11:53:43:040 BST] 00000076 AxisEngine E org.apache.axis2.engine.AxisEngine receive WTRN0127E: Operation blocked by policy type configuration.
I have followed several online articles from IBM developer works that all imply everything should work by just applying the policies via the admin console, but unfortunately I still encounter this error.
I suspect that I may need to include something within the header of the service call, but I am not sure what this is or how to achieve it.
One of the articles suggested using the IBM Rational Application Developer tool, exporting the policies from the admin console and then importing them into the project prior to deployment. I tried this using IBM RAD 9.11 as per the instructions, but it still does not resolve the issues.
Any help/advice would be appreciated, thanks in advance for your help.
I think that you have specified mandatory WS-AT Policy but there is no JTA transaction on the thread. Presumably you want to start a transaction in APP_B and use WS-AT to propagate that transaction on the requests to service_X and service_Y so that all work is coordinated under a single transaction. If service_Z is a POJO you can use UserTransaction to begin/commit the transaction or you could just use a single request to an EJB with CMT to wrap the multiple web service requests to the backend services. NOTE the PolicySet won't automatically start the JTA transaction for you - the easiest way to think of WS-AT is that it is for webservices what JTS/OTS is for CORBA/IIOP (ie EJB requests) - so transaction lifecycle is via JTA in a J2EE app server and transaction propagation and 2PC coordination is via WS-AT for webservices. The way to think about the WS-AT PolicySet config is that on the requester-side it determines whether an existing JTA transaction on the thread is propagated on the request (and whether it should police that a transaction must be present) - on the provider-side it determines whether it should import and execute under a WS-AT transaction context if present and whether it is valid to invoke the sevice if no tran context is present.
Hope this helps.
Not sure if you are referring to the spring class WebSphereUowTransactionManager or WebSphere's UOWManager. If you want a single transaction that all the web services execute under you'll need to start that in service_Z - since we seem to be talking POJOs/mock servlets then in standard J2EE you'd just lookup the UserTransaction interface in jndi and call begin/commit (if you're using Spring then their interfaces will do the equivalent thing under the covers - within the app server it's simply a JTA transaction associated with the current thread that matters).
With the PolicySets configured for mandatory WS-AT that transaction will be propagated on the JAX-WS requests and the target services will execute under that transaction so you don't need (or want) any explicit interaction with the JTA transaction manager (vanilla JTA or Spring) in those services.
On the other hand if you're just hoping that the PolicySet config will create separate transactions in service_X and service_Y ie like having Required/RequiresNew for CMT EJBs so you don't need explicit code to scope the transactions then I'm afraid there isn't a WS-AT policy set equivalent. It's basically JTA for transaction scoping and WS-AT for propagation/2PC with policyset config allowing some configurability over the propagation.

Sharing JMS and Hibernate transactions in a Spring MDB using Oracle Streams AQ?

I'm using Oracle 11g for my database and its Oracle Streams AQ feature as JMS implementation.
For all I know, it should be possible to implement a Spring based message-driven POJO (MDP) that uses the same data source for both transactional data access and JMS transactions -- all without XA-Transactions (IIRC, this was marketed as a feature of SpringSource Advanced Pack for Oracle).
Is this possible using Hibernate as well? Ideally, my MDP would start a JMS transaction and read a message from a queue, then re-use the transaction for data access through Hibernate. If anything goes wrong, the JMS and database transaction would both be rolled back, without using 2-phase commit (2PC).
I'm not much of a transaction guru, so before I start digging deeper, can anyone confirm that this is possible and makes sense as well?
Update:
What I want is an implementation of the Shared Transaction Resource pattern. The sample code demonstrates it for ActiveMQ and JDBC, but I need to use Oracle Streams AQ and Hibernate.
Update2:
The SpringSource Advanced Pack for Oracle has been open sourced as part of Spring Data JDBC and it "provides the option of using a single local transaction manager for both
database and message access without resorting to expensive distributed 2-phase commit
transaction management".
2PC shouldn't be necessary, as you say, since the appserver should take care of it. However, you'll pretty much have to use JTA (i.e. JavaEE container) transactions, rather than vanilla DataSource transactions, since JMS only works with JTA.
This isn't a big deal, it's just a bit more fiddly:
Your Spring config should use
<jee:jndi-lookup/> to get a
reference to your container's
DataSource, and you inject that
data source into your spring-managed
hibernate SessionFactory.
You then need to introduce a transaction manager into the context (<tx:jta-transaction-manager/> should work in most app-servers).
In your Spring JMS MessageListenerContainer, plug the above transaction manager reference into it.
Does that all make sense, or should I elaborate? This setup should ensure that the container-managed transactions are held across JMS and Hibernate interactions.

Resources