Skip to content

Commit 10c8956

Browse files
authored
Merge pull request #31433 from mswatosh/DataLock
Fix for Data deadlock with EJB in .war
2 parents 0e22424 + 8b6105e commit 10c8956

File tree

3 files changed

+40
-42
lines changed

3 files changed

+40
-42
lines changed

dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/DataProvider.java

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,13 @@ public class DataProvider implements //
212212
new ConcurrentHashMap<>();
213213

214214
/**
215-
* EntityManagerBuilder futures, grouped by application, for EJB modules
216-
* that are triggered to initialize on module starting rather than waiting
217-
* for application start.
215+
* EntityManagerBuilder futures, grouped by application, triggered to initialize
216+
* on module starting rather than waiting for application start.
218217
* The Set values in this map are subsets of the Set values in futureEMBuilders.
219218
* The entries are removed on application start, which uses the values to avoid
220219
* duplicated initalization attempts.
221220
*/
222-
private final ConcurrentHashMap<String, Set<FutureEMBuilder>> futureEMBuildersInEJB = //
221+
private final ConcurrentHashMap<String, Set<FutureEMBuilder>> processedFutureEMBuilders = //
223222
new ConcurrentHashMap<>();
224223

225224
/**
@@ -326,7 +325,7 @@ public void applicationStarted(ApplicationInfo appInfo) throws StateChangeExcept
326325
//Use deployment name but fall back to generated name
327326
String appName = appInfo.getDeploymentName() == null ? appInfo.getName() : appInfo.getDeploymentName();
328327
Set<FutureEMBuilder> futures = futureEMBuilders.get(appName);
329-
Set<FutureEMBuilder> skip = futureEMBuildersInEJB.remove(appName);
328+
Set<FutureEMBuilder> skip = processedFutureEMBuilders.remove(appName);
330329
if (futures != null) {
331330
for (FutureEMBuilder futureEMBuilder : futures) {
332331
if (skip == null || !skip.contains(futureEMBuilder))
@@ -410,6 +409,7 @@ public void componentMetaDataCreated(MetaDataEvent<ComponentMetaData> event) {
410409

411410
if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
412411
Tr.debug(this, tc, "componentMetaDataCreated " + jeeName, metadata);
412+
413413
}
414414

415415
@Override
@@ -880,50 +880,39 @@ public void moduleStarted(ModuleInfo moduleInfo) throws StateChangeException {
880880
public void moduleStarting(ModuleInfo moduleInfo) throws StateChangeException {
881881
final boolean trace = TraceComponent.isAnyTracingEnabled();
882882

883-
// TODO here and elsewhere: use whichever of getDeploymentName() or getName()
884-
// is guaranteed to match J2EEName
885-
String appName = moduleInfo.getApplicationInfo().getName();
883+
ApplicationInfo appInfo = moduleInfo.getApplicationInfo();
884+
//Use deployment name but fall back to generated name
885+
String appName = appInfo.getDeploymentName() == null ? appInfo.getName() : appInfo.getDeploymentName();
886886
String moduleName = moduleInfo.getName(); // does not include .jar at the end
887887

888888
if (trace && tc.isDebugEnabled())
889889
Tr.debug(this, tc, "moduleStarting " + moduleInfo, appName, moduleName);
890890

891-
Set<FutureEMBuilder> processed = futureEMBuildersInEJB.get(appName);
891+
Set<FutureEMBuilder> processed = processedFutureEMBuilders.get(appName);
892892

893893
// TODO it would be more direct to map from appName+moduleName -> FutureEMBuilder,
894894
// but we would need to take into account the difference in module names
895895
// including or not including .jar at the end.
896896
Set<FutureEMBuilder> futures = futureEMBuilders.get(appName);
897897
if (futures != null)
898898
for (FutureEMBuilder futureEMBuilder : futures) {
899-
// The JEE name includes .jar at the end of EJB modules
900-
String moduleNameWithDot = futureEMBuilder.jeeName.getModule();
901-
902-
if (!futureEMBuilder.inWebModule &&
903-
moduleNameWithDot != null &&
904-
moduleNameWithDot.length() == moduleName.length() + 4 &&
905-
moduleNameWithDot.startsWith(moduleName) &&
906-
moduleNameWithDot.endsWith(".jar")) {
907-
908-
if (trace && tc.isDebugEnabled())
909-
Tr.debug(this, tc, "matched with " + futureEMBuilder.jeeName);
910-
911-
// This delays createEMBuilder until restore.
912-
// While this works by avoiding all connections to the data source, it does make restore much slower.
913-
// TODO figure out how to do more work on restore without having to make a connection to the data source
914-
CheckpointPhase.onRestore(() -> futureEMBuilder.completeAsync(futureEMBuilder::createEMBuilder, executor));
899+
// This delays createEMBuilder until restore.
900+
// While this works by avoiding all connections to the data source, it does make restore much slower.
901+
// TODO figure out how to do more work on restore without having to make a connection to the data source
902+
CheckpointPhase.onRestore(() -> futureEMBuilder.completeAsync(futureEMBuilder::createEMBuilder, executor));
903+
904+
if (processed == null) {
905+
processed = new ConcurrentSkipListSet<>();
906+
Set<FutureEMBuilder> previous = processedFutureEMBuilders //
907+
.putIfAbsent(appName, processed);
908+
if (previous != null)
909+
processed = previous;
910+
}
915911

916-
if (processed == null) {
917-
processed = new ConcurrentSkipListSet<>();
918-
Set<FutureEMBuilder> previous = futureEMBuildersInEJB //
919-
.putIfAbsent(appName, processed);
920-
if (previous != null)
921-
processed = previous;
922-
}
912+
processed.add(futureEMBuilder);
923913

924-
processed.add(futureEMBuilder);
925-
}
926914
}
915+
927916
}
928917

929918
@Override

dev/io.openliberty.data.internal.persistence/src/io/openliberty/data/internal/persistence/cdi/FutureEMBuilder.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ public EntityManagerBuilder createEMBuilder() {
296296
final boolean trace = TraceComponent.isAnyTracingEnabled();
297297
try {
298298
String resourceName = dataStore;
299-
String metadataIdentifier = getMetadataIdentifier();
299+
String metadataIdentifier = getMetadataIdentifier(inWebModule);
300300

301301
// metadataIdentifier examples:
302302
// WEB#MyApp#MyWebModule.war
@@ -335,8 +335,13 @@ public EntityManagerBuilder createEMBuilder() {
335335
metadata = (ComponentMetaData) provider.metadataIdSvc //
336336
.getMetaData(metadataIdentifier);
337337
} catch (IllegalStateException x) {
338-
if (System.nanoTime() - start > TimeUnit.SECONDS.toNanos(30))
339-
throw x;
338+
try { //Check if this is an EJB in a Web Module
339+
metadata = (ComponentMetaData) provider.metadataIdSvc //
340+
.getMetaData(getMetadataIdentifier(false));
341+
} catch (IllegalStateException y) {
342+
if (System.nanoTime() - start > TimeUnit.SECONDS.toNanos(30))
343+
throw x; //Throw exception for non-EJB check
344+
}
340345
// else retry because the deferred metadata is not available yet
341346
}
342347
} while (metadata == null);
@@ -672,11 +677,14 @@ private J2EEName getArtifactName(Class<?> repositoryInterface,
672677
* Obtains the metadata identifier for the module that defines the repository
673678
* interface.
674679
*
680+
* @param isWebComponent true for a Web Module, false for an EJB Module
681+
*
675682
* @return metadata identifier as the key, and application/module/component
676683
* as the value. Module and component might be null or might not be
677684
* present at all.
678685
*/
679-
private String getMetadataIdentifier() {
686+
private String getMetadataIdentifier(boolean isWebComponent) {
687+
680688
String mdIdentifier;
681689

682690
if (jeeName.getModule() == null) {
@@ -685,7 +693,7 @@ private String getMetadataIdentifier() {
685693
null);
686694
} else {
687695
mdIdentifier = provider.metadataIdSvc //
688-
.getMetaDataIdentifier(inWebModule ? "WEB" : "EJB",
696+
.getMetaDataIdentifier(isWebComponent ? "WEB" : "EJB",
689697
jeeName.getApplication(),
690698
jeeName.getModule(),
691699
null);

dev/io.openliberty.data.internal_fat/test-applications/DataTestApp/src/test/jakarta/data/web/DataTestEJB.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import jakarta.annotation.PostConstruct;
1616
import jakarta.ejb.Singleton;
1717
import jakarta.ejb.Startup;
18+
import jakarta.inject.Inject;
1819

1920
/**
2021
* A singleton startup EJB that is included inside the war file.
@@ -24,11 +25,11 @@
2425
public class DataTestEJB {
2526

2627
//TODO renable after fixing deadlock in DataProvider
27-
// @Inject
28-
// Animals animals;
28+
@Inject
29+
Animals animals;
2930

3031
@PostConstruct
3132
public void init() {
32-
// animals.findAll();
33+
animals.findAll();
3334
}
3435
}

0 commit comments

Comments
 (0)