Skip to content

Commit 1602eec

Browse files
committed
Merge remote-tracking branch 'origin/develop' into fb_workflowStorageActions
2 parents 9d0cbe8 + 234e97e commit 1602eec

3 files changed

Lines changed: 45 additions & 25 deletions

File tree

api/src/org/labkey/api/audit/AbstractAuditTypeProvider.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.labkey.api.data.DbSchema;
3030
import org.labkey.api.data.DbSchemaType;
3131
import org.labkey.api.data.DbScope;
32+
import org.labkey.api.data.MultiChoice;
3233
import org.labkey.api.data.MutableColumnInfo;
3334
import org.labkey.api.data.Table;
3435
import org.labkey.api.data.TableInfo;
@@ -377,6 +378,12 @@ else if (value instanceof Date date)
377378
String formatted = DateUtil.toISO(date);
378379
stringMap.put(entry.getKey(), formatted);
379380
}
381+
else if (value instanceof java.sql.Array arr)
382+
{
383+
// GitHub Issue 1073: Updating a List MVTC field shows array in audit for values with quotes
384+
var arrayVal = MultiChoice.Converter.getInstance().convert(MultiChoice.Array.class, arr);
385+
stringMap.put(entry.getKey(), PageFlowUtil.joinValuesToStringForExport(arrayVal));
386+
}
380387
else
381388
stringMap.put(entry.getKey(), value == null ? null : value.toString());
382389
}

api/src/org/labkey/api/data/DbScope.java

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import jakarta.servlet.ServletContext;
2020
import jakarta.servlet.ServletException;
2121
import org.apache.commons.collections4.IteratorUtils;
22-
import org.apache.commons.lang3.StringUtils;
22+
import org.apache.commons.lang3.Strings;
2323
import org.apache.logging.log4j.Level;
2424
import org.apache.logging.log4j.Logger;
2525
import org.jetbrains.annotations.NotNull;
@@ -110,7 +110,7 @@
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
@@ -121,8 +121,27 @@
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)

list/src/org/labkey/list/model/ListManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ String formatAuditItem(ListDefinitionImpl list, User user, Map<String, Object> p
12191219

12201220
if (null != ti)
12211221
{
1222-
Map<String, String> recordChangedMap = new CaseInsensitiveHashMap<>();
1222+
Map<String, Object> recordChangedMap = new CaseInsensitiveHashMap<>();
12231223
Set<String> reserved = list.getDomain().getDomainKind().getReservedPropertyNames(list.getDomain(), user);
12241224

12251225
// Match props to columns
@@ -1241,7 +1241,7 @@ String formatAuditItem(ListDefinitionImpl list, User user, Map<String, Object> p
12411241
continue;
12421242

12431243
ColumnInfo col = ti.getColumn(FieldKey.fromParts(baseKey));
1244-
String value = Objects.toString(entry.getValue(), "");
1244+
Object value = entry.getValue();
12451245
String key = null;
12461246

12471247
if (null != col)

0 commit comments

Comments
 (0)