The Atomikos Blog
You are here: Blog

ExtremeTransactions 6.0.113
Release notes for 6.0.113

27 February 2025 | Guy Pardon | Release notes

Fea­ture211078
Add Spring Boot 3.4 starter

You can now use Atomikos with Spring Boot 3.4.

Tech­ni­cal de­tails

Spring Boot 3.4 re­quired a new starter project to make it work with Atomikos.

At­tempt­ing to use Spring Boot 3.4 with the old­er starter project would re­sult in er­rors like this:

Caused by: java.lang.NoSuchMethodError: 'void org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers.customize(org.springframework.transaction.PlatformTransactionManager)'
  at com.atomikos.spring.AtomikosAutoConfiguration.lambda$transactionManager$0(AtomikosAutoConfiguration.java:84)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.ifAvailable(DefaultListableBeanFactory.java:2382)
  at com.atomikos.spring.AtomikosAutoConfiguration.transactionManager(AtomikosAutoConfiguration.java:84)
  at java.base/java.lang.reflect.Method.invoke(Method.java:580)
  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.lambda$instantiate$0(SimpleInstantiationStrategy.java:171)
  ... 50 more

This was due to Spring's re­moval of some dep­re­cat­ed meth­ods in org.springframe­work.boot.au­to­con­fig­ure.trans­ac­tion.Trans­ac­tionMan­agerCus­tomiz­ers. A new starter project was need­ed to fix this.

Changes im­pact­ing client API

You can now just use the new starter for your project.

Fea­ture208173
Im­prove er­ror mes­sage when JDBC dri­ver does not re­turn a valid con­nec­tion

You now get a mean­ing­ful er­ror mes­sage when the JDBC dri­ver does not re­turn a valid con­nec­tion.

Tech­ni­cal de­tails

When the JDBC dri­ver does not re­turn a valid con­nec­tion, this would re­sult in a cryp­tic ex­cep­tion like this:

java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "this.delegate" is null
                at com.atomikos.util.DynamicProxySupport.getClassLoadersToTry(DynamicProxySupport.java:195) ~[atomikos-util-6.0.112.jar:na]
                at com.atomikos.util.DynamicProxySupport.createDynamicProxy(DynamicProxySupport.java:189) ~[atomikos-util-6.0.112.jar:na]
                at com.atomikos.jdbc.internal.AtomikosNonXAPooledConnection.doCreateConnectionProxy(AtomikosNonXAPooledConnection.java:108) ~[transactions-jdbc-6.0.112.jar:na]
                at com.atomikos.jdbc.internal.AtomikosNonXAPooledConnection.doCreateConnectionProxy(AtomikosNonXAPooledConnection.java:35) ~[transactions-jdbc-6.0.112.jar:na]
                at com.atomikos.datasource.pool.AbstractXPooledConnection.createConnectionProxy(AbstractXPooledConnection.java:101) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.datasource.pool.ConnectionPoolWithConcurrentValidation.concurrentlyTryToUse(ConnectionPoolWithConcurrentValidation.java:61) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.datasource.pool.ConnectionPoolWithConcurrentValidation.retrieveFirstAvailableConnection(ConnectionPoolWithConcurrentValidation.java:43) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.datasource.pool.ConnectionPool.retrieveFirstAvailableConnectionAndGrowPoolIfNecessary(ConnectionPool.java:140) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.datasource.pool.ConnectionPool.findOrWaitForAnAvailableConnection(ConnectionPool.java:128) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.datasource.pool.ConnectionPool.borrowConnection(ConnectionPool.java:119) ~[transactions-jta-6.0.112.jar:na]
                at com.atomikos.jdbc.internal.AbstractDataSourceBean.getConnection(AbstractDataSourceBean.java:375) ~[transactions-jdbc-6.0.112.jar:na]
                at com.atomikos.jdbc.AtomikosNonXADataSourceBean.getConnection(AtomikosNonXADataSourceBean.java:208) ~[transactions-jdbc-6.0.112.jar:na]

This has now been fixed: we now re­port that the "Driv­er didn't re­turn a valid Con­nec­tion".

Changes im­pact­ing client API

None.

Fea­ture207950
Avoid un­nec­es­sary XA con­nec­tion re­fresh on shut­down

We now avoid use­less XA con­nec­tion re­fresh­ing on shut­down.

Tech­ni­cal de­tails

The fol­low­ing would hap­pen upon shut­down, when for in­stance the JMS serv­er was gone:

Failed to refresh XAResource
com.atomikos.datasource.ResourceException: Error in getting XA resource
        at com.atomikos.datasource.xa.jms.JmsTransactionalResource.refreshXAConnection(JmsTransactionalResource.java:83) ~[!/:?]
        at com.atomikos.datasource.xa.XATransactionalResource.refreshXAResource(XATransactionalResource.java:413) ~[!/:?]
        at com.atomikos.datasource.xa.XATransactionalResource.getXAResource(XATransactionalResource.java:227) ~[!/:?]
        at com.atomikos.datasource.xa.XATransactionalResource.isSameRM(XATransactionalResource.java:317) ~[!/:?]
        at com.atomikos.datasource.xa.XATransactionalResource.equals(XATransactionalResource.java:430) ~[!/:?]
        at java.util.Vector.indexOf(Vector.java:413) ~[?:1.8.0_381]
        at java.util.Vector.indexOf(Vector.java:387) ~[?:1.8.0_381]
        at java.util.Vector.removeElement(Vector.java:646) ~[?:1.8.0_381]
        at java.util.Vector.remove(Vector.java:804) ~[?:1.8.0_381]
        at com.atomikos.icatch.config.Configuration.removeResource(Configuration.java:263) ~[!/:?]
        at com.atomikos.jms.AtomikosConnectionFactoryBean.close(AtomikosConnectionFactoryBean.java:597) ~[!/:?]

This has been im­proved / fixed - we now avoid such re­fresh.

Changes im­pact­ing client API

None.

Bug208965
Con­nec­tion pool: make wait­ing for con­nec­tions fair(er)

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.112

De­scrip­tion

Your getCon­nec­tion re­quests now get the (new) con­nec­tions they de­serve.

Tech­ni­cal de­tails

In our 6.0 re­lease the con­nec­tion pool grows via a sep­a­rate back­ground thread. When getCon­nec­tion finds no avail­able con­nec­tion, it will start wait­ing for this thread to grow the pool and add a new con­nec­tion to it.

The im­ple­men­ta­tion was "un­fair" in that a wait­ing getCon­nec­tion re­quest could (and would) see its new con­nec­tion "hi­jacked" by a dif­fer­ent, lat­er getCon­nec­tion re­quest.

This has now been fixed.

Changes im­pact­ing client API

None.

Bug211208
Tom­cat JNDI fac­to­ry for JDBC and JMS: make it tol­er­ate dou­ble lookups

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.x, 5.0.x

De­scrip­tion

You can now safe­ly re­peat JNDI lookups for our JDBC and JMS fac­to­ries bound in Tom­cat's JNDI space.

Tech­ni­cal de­tails

There was a race con­di­tion in our code that could lead to re­peat­ed ini­tial­i­sa­tion of JNDI re­sources with the same name, like JDBC data­sources or JMS con­nec­tion fac­to­ries.

This has now been fixed.

Changes im­pact­ing client API

None.

ExtremeTransactions 5.0.109
ExtremeTransactions 5.0.109 release notes

10 October 2024 | Guy Pardon | Release notes

Fea­ture200360
Sub­scrip­tion files are now re­quired for pro­duc­tion use

De­scrip­tion

We now re­quire cus­tomers to in­stall sub­scrip­tion files for pro­duc­tion use, sim­i­lar to what we do in 6.0.

Tech­ni­cal de­tails

We've had some bad ex­pe­ri­ences with sub­scrip­tions pur­chased via re­sellers / in­ter­me­di­aries, that were first used by a de­vel­op­ment team, then moved onto oth­er teams in pro­duc­tion with­out us be­ing able to keep track. This has lead to un­pleas­ant ex­pe­ri­ences for both our cus­tomers and our­selves.

For more de­tails, see this doc­u­men­ta­tion page.

Changes im­pact­ing client API

You need to in­stall 2 files as ex­plained on the doc­u­men­ta­tion page men­tioned above. Note: de­vel­op­ment or test­ing use does not need sub­scrip­tion files.

Fea­ture201309
De­tect vul­ner­a­ble de­pen­den­cies on class­path

De­scrip­tion

We now help you find out about known vul­ner­a­ble maven de­pen­den­cies that your ap­pli­ca­tion is us­ing.

Tech­ni­cal de­tails

With cur­rent hack­er ef­forts mov­ing more and more into the ap­pli­ca­tion stack via vul­ner­a­ble open source de­pen­den­cies, we no­tice cus­tomers are get­ting wor­ried (or fac­ing au­dits of their ap­pli­ca­tions). Log4j, any­one?

Our ap­proach has been two-fold:

  • We avoid 3rd par­ty de­pen­den­cies so you can't pull them in by ac­ci­dent, and
  • We now also de­tect known vul­ner­a­ble 3rd par­ty maven de­pen­den­cies on your ap­pli­ca­tion's class­path

Start­ing in the near fu­ture, ex­pect more and more "se­cu­ri­ty up­dates" in that re­spect.

Changes im­pact­ing client API

None.

Bug197240
Al­low spring.jta prop­er­ties in Spring Boot starter

Sever­i­ty:4
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

Any spring.jta prop­er­ties in Spring Boot should now be tak­en into ac­count.

Tech­ni­cal de­tails

After the Spring Boot team con­tributed the source code for their Atomikos starter we thought it was safer to ig­nore any prop­er­ties with the "lega­cy" pre­fix spring.jta.atom­ikos.prop­er­ties (in your ap­pli­ca­tion.prop­er­ties file for Spring Boot).

This has proven to con­fuse users, so we now take such spring.jta prop­er­ties into ac­count.

Changes im­pact­ing client API

Any spring.jta prop­er­ties in Spring Boot should now be tak­en into ac­count.

Bug197505
Avoid that de­faults in the Spring Boot starter over­ride jta.prop­er­ties

Sever­i­ty:4
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

You can now count on the prop­er­ty val­ues from jta.prop­er­ties to be tak­en into ac­count even with Spring Boot.

Tech­ni­cal de­tails

The Atomikos JTA prop­er­ties im­ple­men­ta­tion in our Spring Boot starter would de­fine de­fault val­ues for many prop­er­ties, mean­ing that their val­ue spec­i­fied jta.prop­er­ties would not be tak­en into ac­count. This has now been fixed.

Changes im­pact­ing client API

Your prop­er­ties spec­i­fied in jta.prop­er­ties should now work.

Bug197362
Clar­i­fy mes­sage if rest port not set in client

Sever­i­ty:1/2/3/4
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

You can now count on a bet­ter er­ror mes­sage when the AtomikosRestPort URL is not set (for trans­ac­tions across re­mot­ing calls).

Tech­ni­cal de­tails

When the AtomikosRestPort URL was not set, the client tem­plate would re­port a mis­lead­ing mes­sage say­ing that there is no trans­ac­tion for the thread. In­stead, the root cause is a URL that is miss­ing - so we fixed that for you.

Changes im­pact­ing client API

None.

Bug197506
Sup­port di­a­mond case ar­chi­tec­tures for read­On­ly re­mot­ing

Sever­i­ty:4
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

You can now use tran­si­tive read­On­ly re­mot­ing trans­ac­tions in all cas­es.

Tech­ni­cal de­tails

As out­lined in this GitHub is­sue there was a prob­lem with read­On­ly in­vo­ca­tions when:

  • the same shared ser­vice was called over dif­fer­ent paths, and
  • all in­vo­ca­tions were read­On­ly

This is known as a "di­a­mond case" be­cause the in­vo­ca­tion di­a­gram looks like a di­a­mond.

This is­sue has been fixed in the fol­low­ing way: our prod­uct will now avoid the read­On­ly op­ti­mi­sa­tion in this spe­cif­ic sce­nario. This is still cor­rect, at a mi­nor per­for­mance over­head in the ex­ot­ic cas­es where this does hap­pen.

Changes im­pact­ing client API

None.

Bug197253
Sus­pend/re­sume should not change lo­cal sib­ling count

Sever­i­ty:2
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

You can now use @Re­quiresNew with im­port­ed trans­ac­tions.

Tech­ni­cal de­tails

As ex­plained in this GitHub is­sue, there were prob­lems when a re­mote trans­ac­tion was im­port­ed and then sub­se­quent­ly called lo­cal log­ic that was marked with @Re­quiresNew. As re­quired by the spec­i­fi­ca­tion of @Re­quiresNew, this would sus­pend any ac­tive trans­ac­tion - and re­sume it lat­er.

Our code had a side ef­fect of sus­pend/re­sume that changed the lo­cal sib­ling count.

Si­b­ling counts help de­tect or­phaned in­vo­ca­tions (and their trans­ac­tion­al up­dates to per­sis­tent stor­age) that arise out of lost replies. For in­stance, con­sid­er this sce­nario with ser­vices A and B:

  1. A starts a trans­ac­tion.
  2. A calls B as part of that trans­ac­tion.
  3. B does work and re­turns a re­sult.
  4. A does not re­ceive the re­sult due to a net­work time­out (so B now has an or­phaned in­vo­ca­tion).
  5. A tries again, so B per­forms the changes again and re­turns a new re­sult (in the same trans­ac­tion).
  6. A com­mits the trans­ac­tion think­ing it only up­dat­ed B once.
  7. B com­mits the same trans­ac­tion with two sets of up­dates.

This risk here is the dif­fer­ent views of A and B re­gard­ing the scope of the trans­ac­tion: A thinks it com­mits one up­date to B, where­as B com­mits two dif­fer­ent up­dates. This can be a prob­lem for data con­sis­ten­cy, so we avoid this by keep­ing sib­ling counts at B and A. A con­structs its sib­ling count pic­ture with each re­sult it ac­tu­al­ly re­ceives with its replies from A. Be­fore com­mit, A pass­es on the "count" it has for in­vo­ca­tions at B, and if B finds that there is no match then it re­fus­es to com­mit.

This would avoid the prob­lem out­lined above, be­cause in step 4 ser­vice A will miss a count, so in step 6 ser­vice A will pass a count of 1 for ser­vice B, where­as B will see 2 and re­fus­es the com­mit process.

In short, sib­ling counts have their pur­pose. How­ev­er due to a bug, this was af­fect­ed by a sus­pend/re­sume at ser­vice B (when it has @Re­quiresNew log­ic in­side).

Changes im­pact­ing client API

You should now be able to con­fig­ure @Re­quiresNew on any ser­vice that needs it.

Bug211208
Avoid init-ing con­nec­tion fac­to­ry twice or more on Tom­cat JNDI lookups

Sever­i­ty:4
Af­fect­ed ver­sion(s):5.0.x

De­scrip­tion

You should now be able to per­form any num­ber of JNDI lookups in Tom­cat with­out get­ting warn­ings about the re­source al­ready ex­ist­ing with the same name.

Tech­ni­cal de­tails

Dur­ing JNDI lookups, Tom­cat ap­pli­ca­tions would some­times get warn­ings like be­low due to a race con­di­tion. This has been fixed.

WARNING: Cannot initialize AtomikosConnectionFactoryBean
java.lang.IllegalStateException: Another resource already exists with name XAConnectionFactory - pick a different name
      at com.atomikos.icatch.config.Configuration.addResource(Configuration.java:241)
      at com.atomikos.jms.AtomikosConnectionFactoryBean.doInit(AtomikosConnectionFactoryBean.java:440)
      at com.atomikos.jms.AtomikosConnectionFactoryBean.init(AtomikosConnectionFactoryBean.java:354)
      at com.atomikos.jms.AtomikosConnectionFactoryBean.createConnection(AtomikosConnectionFactoryBean.java:620)

Changes im­pact­ing client API

None.

ExtremeTransactions 6.0.112
Release notes for 6.0.112

02 October 2024 | Guy Pardon | Release notes

Fea­ture208965
Im­prove fair­ness even more while grow­ing the con­nec­tion pool

Re­leas­es 6.0.110 and 6.0.111 of­fered a fair­er way of grow­ing the con­nec­tion pool. This has been op­ti­mised fur­ther.

Tech­ni­cal de­tails

The two pri­or re­leas­es at­tempt­ed to of­fer a fair­er way of grow­ing the con­nec­tion pool, so a thread that re­quests an ex­tra con­nec­tion could also use it. How­ev­er, there the al­go­rithm was still not as good as it could be, be­cause it did the fol­low­ing:

  1. Thread A re­quests grow­ing the pool
  2. The pool adds an ex­tra con­nec­tion
  3. The ex­tra con­nec­tion is put into the pool of avail­able con­nec­tions
  4. Thread A then quick­ly fetch­es the new con­nec­tion

While this per­formed bet­ter than be­fore, this still al­lowed for an­oth­er thread to hi­jack the con­nec­tion be­tween steps 3 and 4.

We now changed this to the fol­low­ing:

  1. Thread A re­quests grow­ing the pool
  2. The pool adds an ex­tra con­nec­tion
  3. The pool marks the con­nec­tion as be­ing used
  4. The ex­tra con­nec­tion is put into the pool of avail­able con­nec­tions
  5. The ex­tra con­nec­tion is re­turned for Thread A to use

The ex­tra step 3 im­plies that no oth­er thread can take the con­nec­tion af­ter step 4. Thus, Thread A is al­ways able to use the new con­nec­tion.

Changes im­pact­ing client API

None.

Is­sue202334
Mod­i­fy Tom­cat ex­am­ples to use Dock­er

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.110

De­scrip­tion

The Tom­cat ex­am­ples have been mod­i­fied to user Dock­er, but this does not work on all plat­forms yet.

Tech­ni­cal de­tails

The Dock­er im­age gen­er­at­ed to run the Tom­cat ex­am­ples con­tains a Java JDK that is not bi­na­ry com­pat­i­ble with all plat­forms yet.

ExtremeTransactions 6.0.110
Release notes for 6.0.110

02 October 2024 | Guy Pardon | Release notes

Fea­ture207056
Im­proved core class­es for con­cur­ren­cy / thread­ing

You can now ben­e­fit from re­duced syn­chro­ni­sa­tion over­head thanks to con­cur­rent maps us­age in our core class­es.

Tech­ni­cal de­tails

We've added 2 new im­ple­men­ta­tion class­es: De­fault­Trans­ac­tionSer­vice and De­fault­Com­pos­iteTrans­ac­tionMan­ag­er. Th­ese com­ply with our new­ly doc­u­ment­ed Con­cur­ren­cy Model for cor­rect­ness in mul­ti-thread­ed ap­pli­ca­tions. We now also use con­cur­rent maps thanks to this this con­tri­bu­tion on github.

The new De­fault­Trans­ac­tionSer­vice also has bet­ter / sim­pler shut­down log­ic for the trans­ac­tion ser­vice.

Changes im­pact­ing client API

This fea­ture can (for now) be tog­gled with a flag in jta.prop­er­ties:

   om.atomikos.icatch.feature.207056 = true 

This is en­abled by de­fault be­cause we are con­fi­dent it works bet­ter than be­fore. If you ex­pe­ri­ence prob­lems af­ter up­grad­ing, set this to false...

Fea­ture203242
Retry file lock on start­up

You can now shift Ku­ber­netes pods by start­ing a new pod while the old one is still ter­mi­nat­ing.

Tech­ni­cal de­tails

In Ku­ber­netes en­vi­ron­ments pods might be ter­mi­nat­ed and shift­ed to oth­er nodes. Be­cause of this the con­fig­ured log path might be in use if the old pod is about to ter­mi­nate and the new one is start­ing up. To be able to use the same LogFileLock we now of­fer retry at­tempts for the new pod which is try­ing to ac­quire the lock.

Changes im­pact­ing client API

None, we have rea­son­able de­fault con­fig­u­ra­tion prop­er­ties in JTA Prop­er­ties, pre­fixed with com.atom­ikos.icatch.log_lock­_ac­qui­si­tion.

Fea­ture201646
Spring Boot 2 starter: use the jta and jms ver­sions of Spring Boot's POM in the starter project

You can now use the same JTA and JMS de­pen­den­cy ver­sions of Spring Boot's rather than the ones we spec­i­fy.

Tech­ni­cal de­tails

For Spring Boot 2 we used to spec­i­fy a par­tic­u­lar ver­sion for each of JTA and JMS. This would over­ride the ver­sions that Spring Boot prefers. We no longer do this.

Changes im­pact­ing client API

None.

Fea­ture207758
Ex­am­ples for Hiber­nate 7

You can now check the ex­am­ples for Hiber­nate 7.

Tech­ni­cal de­tails

We've added work­ing sam­ples for Hiber­nate 7.

Bug202474
Re­fine ex­cep­tion mes­sage when cre­at­ing a JDBC state­ment fails

Sever­i­ty:3
Af­fect­ed ver­sion(s):6.O.x, 5.0.x

De­scrip­tion

You can now ex­pect more ac­cu­rate ex­cep­tion mes­sages when cre­at­ing a JDBC state­ment fails

Tech­ni­cal de­tails

We used to have one gener­ic ex­cep­tion mes­sage when a state­ment could not be cre­at­ed, each time sug­gest­ing a time­out of the trans­ac­tion. This was con­fus­ing if the real rea­son was, for in­stance, the trans­ac­tion hav­ing been marked for roll­back only.

The code has been re­fined live this:

   TxState state = ct.getState();
   if (state == TxState.ACTIVE) {
      ct.registerSynchronization(new JdbcRequeueSynchronization(this, ct));
   } else if (state == TxState.MARKED_ABORT){
      AtomikosSQLException.throwAtomikosSQLException("The transaction has been set to rollback-only");
   } else {
      AtomikosSQLException.throwAtomikosSQLException("The transaction has timed out - try increasing the timeout if needed");
   }

Changes im­pact­ing client API

None.

Bug202466
In­ter­posed syn­chro­ni­sa­tion in­stances not called on reg­u­lar roll­back

Sever­i­ty:3
Af­fect­ed ver­sion(s):6.O.x

De­scrip­tion

In­ter­posed syn­chro­ni­sa­tion in­stances are now called on reg­u­lar roll­back also.

Tech­ni­cal de­tails

See this github is­sue for de­tails.

Changes im­pact­ing client API

None.

Bug208965
Bug in bor­row­ing con­nec­tion: make wait­ing for avail­able con­nec­tions fair(er)

Sever­i­ty:3
Af­fect­ed ver­sion(s):6.0.x

De­scrip­tion

Get­ting a new con­nec­tion is now more ef­fi­cient.

Tech­ni­cal de­tails

De­tails are ex­plained in this github is­sue.

Changes im­pact­ing client API

None.

Bug209260
Ex­pose AtomikosSQLEx­cep­tion in pub­lic pack­age (for OSGi)

Sever­i­ty:4
Af­fect­ed ver­sion(s):5.O.x, 6.0.x

De­scrip­tion

The class AtomikosSQLEx­cep­tion was not ex­posed as pub­lic in OSGi.

Tech­ni­cal de­tails

The class AtomikosSQLEx­cep­tion was not ex­posed as pub­lic in OSGi be­cause it was in an "in­ter­nal" pack­age. This class has been moved to a pub­lic pack­age in­stead, so it can be used with OSGi.

Changes im­pact­ing client API

You have to change the im­ports when your code ref­er­ences this ex­cep­tion.

Bug207055
Bug in time­out/roll­back of lo­cal sub trans­ac­tion fol­lowed by com­mit of its par­ent

Sever­i­ty:3
Af­fect­ed ver­sion(s):5.0.x, 6.0.x and pri­or (dec­o­rat­ed) re­leas­es

De­scrip­tion

Time­out / roll­back of a sub­trans­ac­tion no longer ap­pears as a com­mit to the par­ent trans­ac­tion.

Tech­ni­cal de­tails

Time­out with sub­se­quent roll­back of a sub­trans­ac­tion would in­ter­fere with a lat­er com­mit of the par­ent trans­ac­tion: the state han­dler for the sub­trans­ac­tion would er­ro­neous­ly re­ply with READONLY upon 2PC pre­pare. This would make it seem to the par­ent trans­ac­tion as though com­mit may pro­ceed. We've fixed this by check­ing for time­out upon pre­pare of a sub­trans­ac­tion. Most peo­ple are not us­ing sub­trans­ac­tion func­tion­al­i­ty, but those who do will ben­e­fit from this fix.

Changes im­pact­ing client API

None.

Bug207046
Im­prove 2-phase com­mit for im­port­ed trans­ac­tion to align with the new con­cur­ren­cy mod­el

Sever­i­ty:3
Af­fect­ed ver­sion(s):5.0.x, 6.0.x and pri­or (dec­o­rat­ed) re­leas­es

De­scrip­tion

We im­proved the way im­port­ed trans­ac­tions are han­dled in the case of net­work time­outs - so it aligns with our con­cur­ren­cy mod­el.

Tech­ni­cal de­tails

This re­lease in­cludes an im­proved con­cur­ren­cy im­ple­men­ta­tion (as per fea­ture 207056 above), along with a new­ly doc­u­ment­ed con­cur­ren­cy mod­el as shown in Con­cur­ren­cy Model. We've up­dat­ed the han­dling of im­port­ed trans­ac­tions to be con­sis­tent with the new con­cur­ren­cy mod­el. In par­tic­u­lar, the fol­low­ing sce­nario has been im­proved:

  • A re­mote client prop­a­gates a trans­ac­tion to your ser­vice, pos­si­bly on a num­ber of times on dif­fer­ent in­vo­ca­tions.
  • The last in­vo­ca­tion "I" ap­pears to "fail" at the re­mote client due to a net­work time­out, but the in­vo­ca­tion as ac­tu­al­ly still ac­tive at your ser­vice.
  • The re­mote client de­cides to ter­mi­nate the trans­ac­tion by ei­ther com­mit (which is pos­si­ble if "I" is con­sid­ered op­tion­al) or roll­back.
  • Depend­ing on the com­plex­i­ty of the re­mote trans­ac­tion, this will lead to ei­ther of an in­com­ing "PC": pre­pare, roll­back or 1-phase com­mit call in your ser­vice.
  • The clas­si­cal way we dealt with this was in­stant roll­back trig­gered by the in­com­ing "2PC", but this vi­o­lates our new con­cur­ren­cy mod­el.
  • So we now let the pend­ing ac­tive in­vo­ca­tion do the roll­back in­stead - in line with the con­cur­ren­cy mod­el.

Changes im­pact­ing client API

None.

Bug207146
High mem­o­ry con­sump­tion due to adding JDBC state­ments mul­ti­ple times to the same list

Sever­i­ty:3
Af­fect­ed ver­sion(s):6.0.x

De­scrip­tion

Creat­ing many JDBC state­ments no longer leads to high mem­o­ry con­sump­tion.

Tech­ni­cal de­tails

For tech­ni­cal rea­sons we keep a "cached" col­lec­tion of JDBC state­ments. Due to a bug, such state­ments were added mul­ti­ple times to a list. We fixed this by:

  • Chang­ing the list to a Set, and
  • Re­mov­ing the lines of code that added state­ments more than once.

Changes im­pact­ing client API

None.

Bug209259
Im­prove thread-safe­ty of CheckedEx­port­ingTrans­ac­tionMan­ag­er

Sever­i­ty:3
Af­fect­ed ver­sion(s):5.0.x, 6.0.x

De­scrip­tion

We im­proved the tread-safe­ty of CheckedEx­port­ingTrans­ac­tionMan­ag­er in mod­ule trans­ac­tions-re­mot­ing.

Tech­ni­cal de­tails

We changed the use of a HashMap to a Con­cur­ren­tHashMap for pend­ing re­quest syn­chro­ni­sa­tion in­stances.

Changes im­pact­ing client API

None.

Bug202750
Con­nec­tionPool: end­less loop on in­ter­rupt dur­ing wait­ForCon­nec­tion

Sever­i­ty:3
Af­fect­ed ver­sion(s):4.0.x, 5.0.x, 6.0.x

De­scrip­tion

In­ter­rup­tions dur­ing Spring Boot shut­down are now han­dled bet­ter by the con­nec­tion pool.

Tech­ni­cal de­tails

Full de­tails as dis­closed in the orig­i­nal re­port:

We ex­pe­ri­enced a some­what strange be­hav­iour with Atomikos in a sit­u­a­tion, where our ap­pli­ca­tion (Spring Boot) is shut­ting down while some threads are wait­ing for a con­nec­tion. In this shut­down-sit­u­a­tion, Spring Boot sends an 'in­terupt' to all run­ning threads. The Atomikos Con­nec­tionPool method 'wait­ForAtLeast­OneA­vail­ableCon­nec­tion()' han­dles this In­ter­rupt­edEx­cep­tion by in­vok­ing the In­terupt­edEx­cep­tionHelper. This in turn logs the ex­cep­tion and re-in­ter­rupts the thread. This is the cor­rect pat­tern to in­ter­rupt pos­si­ble fur­ther waits in the call stack.

But the method does not leave the while-loop. This caus­es a loop for the re­main­ing bor­rowCon­nec­tionTime­out, lead­ing to a very large amount of ex­cep­tion logs.

Changes im­pact­ing client API

None.

Bug210111
Miss­ing jar in eval down­load: trans­ac­tions-tom­cat-jakar­ta

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.x

De­scrip­tion

You can now use the Tom­cat Jakar­ta func­tion­al­i­ty in the free tri­al down­load.

Tech­ni­cal de­tails

The rel­e­vant jar file for this was miss­ing from the eval­u­a­tion zip file. It has now been added.

Is­sue202334
Mod­i­fy Tom­cat ex­am­ples to use Dock­er

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.110

De­scrip­tion

The Tom­cat ex­am­ples have been mod­i­fied to user Dock­er, but this does not work on all plat­forms yet.

Tech­ni­cal de­tails

The Dock­er im­age gen­er­at­ed to run the Tom­cat ex­am­ples con­tains a Java JDK that is not bi­na­ry com­pat­i­ble with all plat­forms yet.

ExtremeTransactions 6.0.111
Release notes for 6.0.111

02 October 2024 | Guy Pardon | Release notes

Bug208965
Fix race con­di­tion in new pool growth al­go­rithm

Sever­i­ty:2
Af­fect­ed ver­sion(s):6.0.110

De­scrip­tion

The im­prove­ment shipped as part of re­lease 6.0.110 con­tained a bug that cause race con­di­tions on con­cur­rent pool us­age. This is no longer the case;

Tech­ni­cal de­tails

The im­prove­ment that made grow­ing the pool fair­er for con­cur­rent wait­ing threads con­tained a bug that led to at­tempts to use the same con­nec­tion in two dif­fer­ent threads, lead­ing to ex­cep­tions like this one:

com.atomikos.datasource.ResourceException: XA resource '5684df3b-2192-4bd1-ba12-91cb2d55edac': resume for XID 'xid://61653731323262342D336561322D343761362D613461632D373861393064643062616539:31302E3130312E31332E392E746D31343035303633' raised -6: the XA resource did not expect this command in the current context
   at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:240)
   at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.<init>(BranchEnlistedStateHandler.java:42)
   at com.atomikos.datasource.xa.session.NotInBranchStateHandler.checkEnlistBeforeUse(NotInBranchStateHandler.java:46)
   at com.atomikos.datasource.xa.session.TransactionContext.checkEnlistBeforeUse(TransactionContext.java:58)
   at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:185)
   at com.atomikos.jdbc.internal.AtomikosJdbcConnectionProxy.enlist(AtomikosJdbcConnectionProxy.java:89)
   at com.atomikos.jdbc.internal.AtomikosJdbcConnectionProxy.updateTransactionContext(AtomikosJdbcConnectionProxy.java:62)
   at com.atomikos.jdbc.internal.AbstractJdbcConnectionProxy.prepareStatement(AbstractJdbcConnectionProxy.java:65)
   at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
   at java.base/java.lang.reflect.Method.invoke(Method.java:580)
   at com.atomikos.util.DynamicProxySupport.callProxiedMethod(DynamicProxySupport.java:167)
   at com.atomikos.util.DynamicProxySupport.invoke(DynamicProxySupport.java:121)
   at jdk.proxy3/jdk.proxy3.$Proxy235.prepareStatement(Unknown Source)
   at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
   at java.base/java.lang.reflect.Method.invoke(Method.java:580)
   at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:262)
   at jdk.proxy3/jdk.proxy3.$Proxy232.prepareStatement(Unknown Source)
   at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:153)
   at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:183)
   at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:155)
   at org.hibernate.sql.exec.spi.JdbcSelectExecutor.lambda$list$0(JdbcSelectExecutor.java:85)
   at org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess.executeQuery(DeferredResultSetAccess.java:231)
   at org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess.getResultSet(DeferredResultSetAccess.java:167)
   at org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl.advanceNext(JdbcValuesResultSetImpl.java:218)
   at org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl.processNext(JdbcValuesResultSetImpl.java:98)
   at org.hibernate.sql.results.jdbc.internal.AbstractJdbcValues.next(AbstractJdbcValues.java:19)
   at org.hibernate.sql.results.internal.RowProcessingStateStandardImpl.next(RowProcessingStateStandardImpl.java:66)
   at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:202)
   at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33)
   at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:209)
   at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:83)
   at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:76)
   at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:65)
   at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$2(ConcreteSqmSelectQueryPlan.java:137)
   at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:381)
   at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:303)
   at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:509)
   at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:427)
   at org.hibernate.query.Query.getResultList(Query.java:120)
   at org.springframework.data.jpa.repository.query.JpaQueryExecution$ExistsExecution.doExecute(JpaQueryExecution.java:315)
   at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92)
   at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:149)
   at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:137)
   at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
   at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
   at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:169)
   at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:148)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at datadog.trace.instrumentation.springdata.RepositoryInterceptor.invoke(RepositoryInterceptor.java:43)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
   at jdk.proxy3/jdk.proxy3.$Proxy395.existsByRetailTaxpayerIdIn(Unknown Source)
   at .portfolio_management.taxpayer.PendingSyncService.hasTaxpayerPendingSync(PendingSyncService.java:89)
   at .portfolio_management.executionaware.evaluation.EvaluationJob$Runner.washGroupCanBeEvaluated(EvaluationJob.java:145)
   at xxx.portfolio_management.executionaware.evaluation.EvaluationJob$Runner.shouldRunJob(EvaluationJob.java:137)
   at xxx.portfolio_management.executionaware.evaluation.EvaluationJob$Runner.run_aroundBody0(EvaluationJob.java:113)
   at xxx.portfolio_management.executionaware.evaluation.EvaluationJob$Runner$AjcClosure1.run(EvaluationJob.java:1)
   at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:67)
   at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:73)
   at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
   at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:71)
   at xxx.portfolio_management.executionaware.evaluation.EvaluationJob$Runner.run(EvaluationJob.java:112)
   at xxx.portfolio_management.executionaware.evaluation.EvaluationJob$Runner.run(EvaluationJob.java:61)
   at xxx.dj.DelayedJobWorker.lambda$process$0(DelayedJobWorker.java:90)
   at xxx.telemetry.metrics.Metric.lambda$delayedJobTimer$0(Metric.java:25)
   at io.micrometer.core.instrument.AbstractTimer.record(AbstractTimer.java:187)
   at xxx.telemetry.metrics.Metric.lambda$delayedJobTimer$1(Metric.java:33)
   at io.micrometer.core.instrument.AbstractTimer.record(AbstractTimer.java:187)
   at xxx.telemetry.metrics.Metric.delayedJobTimer(Metric.java:33)
   at xxx.telemetry.metrics.Metric.delayedJobTimer(Metric.java:29)
   at xxx.dj.DelayedJobWorker.lambda$process$5(DelayedJobWorker.java:86)
   at xxx.telemetry.metrics.Metric.lambda$delayedJobTimer$0(Metric.java:25)
   at io.micrometer.core.instrument.AbstractTimer.record(AbstractTimer.java:187)
   at xxx.telemetry.metrics.Metric.lambda$delayedJobTimer$1(Metric.java:33)
   at io.micrometer.core.instrument.AbstractTimer.record(AbstractTimer.java:187)
   at xxx.telemetry.metrics.Metric.delayedJobTimer(Metric.java:33)
   at xxx.telemetry.metrics.Metric.delayedJobTimer(Metric.java:29)
   at xxx.dj.DelayedJobWorker.process(DelayedJobWorker.java:51)
   at xxx.dj.DelayedJobProcessor.lambda$claimAndSubmitJobs$0(DelayedJobProcessor.java:148)
   at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
   at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
   at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
   at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
   at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: org.postgresql.xa.PGXAException: Connection is busy with another transaction
   at org.postgresql.xa.PGXAConnection.start(PGXAConnection.java:199)
   at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTransaction.java:234)
   ... 94 more

Changes im­pact­ing client API

None.

Is­sue202334
Mod­i­fy Tom­cat ex­am­ples to use Dock­er

Sever­i­ty:4
Af­fect­ed ver­sion(s):6.0.110

De­scrip­tion

The Tom­cat ex­am­ples have been mod­i­fied to user Dock­er, but this does not work on all plat­forms yet.

Tech­ni­cal de­tails

The Dock­er im­age gen­er­at­ed to run the Tom­cat ex­am­ples con­tains a Java JDK that is not bi­na­ry com­pat­i­ble with all plat­forms yet.

Corporate Information

Atomikos Corporate Headquarters
Hoveniersstraat, 39/1, 2800
Mechelen, Belgium

Contact Us

Copyright 2026 Atomikos BVBA | Our Privacy Policy
This page was cached on 23 May 2026 - 23:00.
By using this site you agree to our cookies. More info. That's Fine