1919import jakarta .servlet .ServletContext ;
2020import jakarta .servlet .ServletException ;
2121import org .apache .commons .collections4 .IteratorUtils ;
22- import org .apache .commons .lang3 .StringUtils ;
22+ import org .apache .commons .lang3 .Strings ;
2323import org .apache .logging .log4j .Level ;
2424import org .apache .logging .log4j .Logger ;
2525import org .jetbrains .annotations .NotNull ;
110110/**
111111 * Class that wraps a data source and is shared amongst that data source's DbSchemas. Allows "nested" transactions,
112112 * implemented via a reference-counting style approach. Each (potentially nested) set of code should call
113- * {@code ensureTransaction()}. This will either start a new transaction, or join an existing one. Once the outermost
113+ * {@code ensureTransaction()}. This will either start a new transaction or join an existing one. Once the outermost
114114 * caller calls commit(), the WHOLE transaction will be committed at once. The most common usage scenario looks
115115 * something like:
116116 * <pre>{@code
121121 * transaction.commit();
122122 * }
123123 *
124- * The DbScope.Transaction class implements AutoCloseable, so it will be cleaned up automatically by JDK 7's try {}
125- * resource handling.
124+ * }
125+ * </pre>
126+ * The DbScope.Transaction class implements AutoCloseable, so it will be cleaned up automatically via try-with-resources.
127+ * <p>
128+ * All return pathways inside the transaction must commit, or the transaction will be considered abandoned to be rolled
129+ * back. There should be no further database work prior to exiting the try block after the commit. Example:
130+ * <pre>{@code
131+ * DbScope scope = dbSchemaInstance.getScope();
132+ * try (DbScope.Transaction transaction = scope.ensureTransaction())
133+ * {
134+ * // Do some work
135+ * if (condition) {
136+ * transaction.commit();
137+ * return true;
138+ * }
139+ * // Do some other work
140+ * boolean result = determineResult();
141+ * transaction.commit();
142+ * return result;
143+ * }
144+ *
126145 * }
127146 * </pre>
128147 */
@@ -869,7 +888,7 @@ public Transaction beginTransaction(TransactionKind transactionKind, Lock... loc
869888 int stackDepth ;
870889 synchronized (_transaction )
871890 {
872- List <TransactionImpl > transactions = _transaction .computeIfAbsent (getEffectiveThread (), k -> new ArrayList <>());
891+ List <TransactionImpl > transactions = _transaction .computeIfAbsent (getEffectiveThread (), _ -> new ArrayList <>());
873892 transactions .add (result );
874893 stackDepth = transactions .size ();
875894 }
@@ -1093,7 +1112,7 @@ public boolean isTransactionActive()
10931112 synchronized (_transaction )
10941113 {
10951114 List <TransactionImpl > transactions = _transaction .get (thread );
1096- return transactions == null ? null : transactions .get ( transactions . size () - 1 );
1115+ return transactions == null ? null : transactions .getLast ( );
10971116 }
10981117 }
10991118
@@ -1242,7 +1261,7 @@ private ConnectionHolder getConnectionHolder()
12421261 // Synchronize just long enough to get a ConnectionHolder into the map
12431262 synchronized (_threadConnections )
12441263 {
1245- return _threadConnections .computeIfAbsent (thread , t -> new ConnectionHolder ());
1264+ return _threadConnections .computeIfAbsent (thread , _ -> new ConnectionHolder ());
12461265 }
12471266 }
12481267
@@ -1301,7 +1320,7 @@ private static void ensureDelegation(Connection conn)
13011320 try
13021321 {
13031322 // Test the method to make sure we can access it
1304- Connection test = (Connection ) methodGetInnermostDelegate .invoke (conn );
1323+ var _ = (Connection ) methodGetInnermostDelegate .invoke (conn );
13051324 isDelegating = true ;
13061325 return ;
13071326 }
@@ -2000,7 +2019,7 @@ private static void createDataBase(SqlDialect dialect, LabKeyDataSource ds) thro
20002019
20012020 LOG .info ("Attempting to create database \" {}\" " , dbName );
20022021
2003- String defaultUrl = StringUtils .replace (url , dbName , dialect .getDefaultDatabaseName ());
2022+ String defaultUrl = Strings . CS .replace (url , dbName , dialect .getDefaultDatabaseName ());
20042023 String createSql = "(undefined)" ;
20052024
20062025 try (Connection conn = getRawConnection (defaultUrl , ds ))
@@ -2415,8 +2434,8 @@ public <T extends Runnable> T add(TransactionImpl transaction, T task)
24152434
24162435 public interface Transaction extends AutoCloseable
24172436 {
2418- /*
2419- * @return the task that was inserted or the existing object (equal to the runnable passed in) that will be run instead
2437+ /**
2438+ * @return the task that was inserted or the existing object (equal to the runnable passed in) that will be run instead
24202439 */
24212440 @ NotNull
24222441 <T extends Runnable > T addCommitTask (@ NotNull T runnable , @ NotNull CommitTaskOption firstOption , CommitTaskOption ... additionalOptions );
@@ -2796,7 +2815,7 @@ private boolean isOutermostTransaction()
27962815 /** Remove current transaction nesting and unlock any locks */
27972816 private void decrement ()
27982817 {
2799- List <Lock > locks = _locks .remove ( _locks . size () - 1 );
2818+ List <Lock > locks = _locks .removeLast ( );
28002819 for (Lock lock : locks )
28012820 {
28022821 // Release all the locks
@@ -2853,7 +2872,7 @@ public void increment(boolean releaseOnFinalCommit, List<Lock> extraLocks)
28532872 if (!_locks .isEmpty () && releaseOnFinalCommit )
28542873 {
28552874 // Add the new locks to the outermost set of locks
2856- _locks .get ( 0 ).addAll (extraLocks );
2875+ _locks .getFirst ( ).addAll (extraLocks );
28572876 // Add an empty list to this layer of the transaction
28582877 _locks .add (new ArrayList <>());
28592878 }
@@ -3328,7 +3347,7 @@ public void testNestedMissingCommit()
33283347 //noinspection EmptyTryBlock
33293348 try (Transaction ignored = getLabKeyScope ().ensureTransaction ())
33303349 {
3331- // Intentionally don't call t2.commit();
3350+ // Intentionally, don't call t2.commit();
33323351 }
33333352 try
33343353 {
@@ -3359,14 +3378,8 @@ public void testMultipleTransactionKinds()
33593378 try (Transaction t2 = getLabKeyScope ().ensureTransaction ())
33603379 {
33613380 assertSame (connection , t2 .getConnection ());
3362- try (Transaction t3 = getLabKeyScope ().ensureTransaction (new TransactionKind ()
3363- {
3364- @ NotNull
3365- @ Override
3366- public String getKind ()
3367- {
3368- return "PIPELINESTATUS" ; // We can't really see PipelineStatus here, but just need something non-normal to test
3369- }
3381+ try (Transaction t3 = getLabKeyScope ().ensureTransaction (() -> {
3382+ return "PIPELINESTATUS" ; // We can't really see PipelineStatus here, but just need something non-normal to test
33703383 }))
33713384 {
33723385 assertTrue (getLabKeyScope ().isTransactionActive ());
@@ -3392,7 +3405,7 @@ public void testServerRowLock()
33923405 Lock lockUser = new ServerPrimaryKeyLock (true , CoreSchema .getInstance ().getTableInfoUsersData (), user .getUserId ());
33933406 Lock lockHome = new ServerPrimaryKeyLock (true , CoreSchema .getInstance ().getTableInfoContainers (), ContainerManager .getHomeContainer ().getId ());
33943407
3395- attemptToDeadlock (lockUser , lockHome , (x ) -> {}, PessimisticLockingFailureException .class );
3408+ attemptToDeadlock (lockUser , lockHome , (_ ) -> {}, PessimisticLockingFailureException .class );
33963409 }
33973410
33983411 private void attemptToDeadlock (Lock lock1 , Lock lock2 , @ NotNull Consumer <Transaction > transactionModifier , Class <? extends Throwable > expectedException )
0 commit comments