diff --git a/build/config/pom.xml b/build/config/pom.xml
index ba893e98e25..00e5e40298b 100644
--- a/build/config/pom.xml
+++ b/build/config/pom.xml
@@ -248,6 +248,9 @@
^org\.hibernate\.query\.spi\.QueryParameterBindingTypeResolver$
^org\.hibernate\.query\.sqm\.spi\.SqmCreationContext$
^org\.hibernate\.sql\.results\.graph\.Fetchable$
+
+ ^org\.hibernate\.engine\.extension\.spi\.[a-zA-Z]+$
+ ^org\.hibernate\.engine\.spi\.SharedSessionContractImplementor#getExtension.+$
- 7.2.0.CR2
+ 7.2.0-SNAPSHOT
https://docs.jboss.org/hibernate/orm/${parsed-version.org.hibernate.orm.majorVersion}.${parsed-version.org.hibernate.orm.minorVersion}/javadocs/
https://docs.jboss.org/hibernate/orm/${parsed-version.org.hibernate.orm.majorVersion}.${parsed-version.org.hibernate.orm.minorVersion}/userguide/html_single/Hibernate_User_Guide.html
diff --git a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringIT.java b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringIT.java
index 365e779de7f..d35a596ba22 100644
--- a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringIT.java
+++ b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringIT.java
@@ -13,11 +13,9 @@
import org.hibernate.search.integrationtest.spring.jta.dao.SnertDAO;
import org.hibernate.search.integrationtest.spring.jta.entity.Snert;
import org.hibernate.search.integrationtest.spring.testsupport.AbstractMapperOrmSpringIT;
-import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSearchSessionHolder;
import org.hibernate.search.util.impl.integrationtest.common.extension.BackendMock;
import org.hibernate.search.util.impl.test.annotation.PortedFromSearch5;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -50,11 +48,6 @@ void checkJta() {
.returns( true, TransactionCoordinatorBuilder::isJta );
}
- @AfterEach
- void checkNoMemoryLeak() {
- assertThat( HibernateOrmSearchSessionHolder.staticMapSize() ).isZero();
- }
-
@Test
void test() {
Snert snert = new Snert();
diff --git a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringMoreComplexIT.java b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringMoreComplexIT.java
index fb683b2222b..3f800e2bee4 100644
--- a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringMoreComplexIT.java
+++ b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringMoreComplexIT.java
@@ -15,11 +15,9 @@
import org.hibernate.search.integrationtest.spring.jta.entity.Doughnut;
import org.hibernate.search.integrationtest.spring.jta.entity.Muffin;
import org.hibernate.search.integrationtest.spring.testsupport.AbstractMapperOrmSpringIT;
-import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSearchSessionHolder;
import org.hibernate.search.util.impl.integrationtest.common.extension.BackendMock;
import org.hibernate.search.util.impl.test.annotation.PortedFromSearch5;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -52,11 +50,6 @@ void checkJta() {
.returns( true, TransactionCoordinatorBuilder::isJta );
}
- @AfterEach
- void checkNoMemoryLeak() {
- assertThat( HibernateOrmSearchSessionHolder.staticMapSize() ).isZero();
- }
-
@Test
void testMuffins() {
Box box = new Box();
diff --git a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringOutboxIT.java b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringOutboxIT.java
index 321dbab9d50..62df6de8b58 100644
--- a/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringOutboxIT.java
+++ b/integrationtest/mapper/orm-spring/src/test/java/org/hibernate/search/integrationtest/spring/jta/JtaAndSpringOutboxIT.java
@@ -13,10 +13,8 @@
import org.hibernate.search.integrationtest.spring.jta.dao.SnertDAO;
import org.hibernate.search.integrationtest.spring.jta.entity.Snert;
import org.hibernate.search.integrationtest.spring.testsupport.AbstractMapperOrmSpringIT;
-import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSearchSessionHolder;
import org.hibernate.search.util.impl.integrationtest.common.extension.BackendMock;
-import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -48,11 +46,6 @@ void checkJta() {
.returns( true, TransactionCoordinatorBuilder::isJta );
}
- @AfterEach
- void checkNoMemoryLeak() {
- assertThat( HibernateOrmSearchSessionHolder.staticMapSize() ).isZero();
- }
-
@Test
void test() {
Snert snert = new Snert();
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java
index e5ae46217b1..1fbe2de3f99 100644
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java
@@ -377,10 +377,9 @@ public PojoIndexingPlan currentIndexingPlanIfExisting(SessionImplementor session
@Override
public PojoTypeIndexingPlan currentIndexingPlanIfTypeIncluded(
- SharedSessionContractImplementor sessionImplementor,
+ SharedSessionContractImplementor session,
PojoRawTypeIdentifier> typeIdentifier) {
try {
- SessionImplementor session = sessionImplementor.unwrap( SessionImplementor.class );
HibernateOrmSearchSession searchSession = HibernateOrmSearchSession.get( this, session, false );
if ( searchSession != null ) {
// If the session exist, rely on the session-level filter
@@ -403,7 +402,7 @@ public PojoTypeIndexingPlan currentIndexingPlanIfTypeIncluded(
}
}
catch (PersistenceException e) {
- throw OrmMiscLog.INSTANCE.unsupportedSessionType( sessionImplementor.getClass() );
+ throw OrmMiscLog.INSTANCE.unsupportedSessionType( session.getClass() );
}
}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/AfterCommitIndexingPlanSynchronization.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/AfterCommitIndexingPlanSynchronization.java
index 1309380443c..d58303348e3 100644
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/AfterCommitIndexingPlanSynchronization.java
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/AfterCommitIndexingPlanSynchronization.java
@@ -18,15 +18,15 @@
class AfterCommitIndexingPlanSynchronization implements Synchronization {
private final PojoIndexingPlan indexingPlan;
- private final HibernateOrmSearchSessionHolder sessionHolder;
+ private final HibernateOrmSearchSessionExtension sessionExtension;
private final Transaction transactionIdentifier;
private final ConfiguredIndexingPlanSynchronizationStrategy synchronizationStrategy;
AfterCommitIndexingPlanSynchronization(PojoIndexingPlan indexingPlan,
- HibernateOrmSearchSessionHolder sessionHolder, Transaction transactionIdentifier,
+ HibernateOrmSearchSessionExtension sessionExtension, Transaction transactionIdentifier,
ConfiguredIndexingPlanSynchronizationStrategy synchronizationStrategy) {
this.indexingPlan = indexingPlan;
- this.sessionHolder = sessionHolder;
+ this.sessionExtension = sessionExtension;
this.transactionIdentifier = transactionIdentifier;
this.synchronizationStrategy = synchronizationStrategy;
}
@@ -51,7 +51,7 @@ public void afterCompletion(int i) {
}
finally {
//clean the Synchronization per Transaction
- sessionHolder.clear( transactionIdentifier );
+ sessionExtension.clear( transactionIdentifier );
}
}
}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/BeforeCommitIndexingPlanSynchronization.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/BeforeCommitIndexingPlanSynchronization.java
index b5a6f168400..3a27e781368 100644
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/BeforeCommitIndexingPlanSynchronization.java
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/BeforeCommitIndexingPlanSynchronization.java
@@ -18,15 +18,15 @@
class BeforeCommitIndexingPlanSynchronization implements Synchronization {
private final PojoIndexingPlan indexingPlan;
- private final HibernateOrmSearchSessionHolder sessionHolder;
+ private final HibernateOrmSearchSessionExtension sessionExtension;
private final Transaction transactionIdentifier;
private final ConfiguredIndexingPlanSynchronizationStrategy synchronizationStrategy;
BeforeCommitIndexingPlanSynchronization(PojoIndexingPlan indexingPlan,
- HibernateOrmSearchSessionHolder sessionHolder, Transaction transactionIdentifier,
+ HibernateOrmSearchSessionExtension sessionExtension, Transaction transactionIdentifier,
ConfiguredIndexingPlanSynchronizationStrategy synchronizationStrategy) {
this.indexingPlan = indexingPlan;
- this.sessionHolder = sessionHolder;
+ this.sessionExtension = sessionExtension;
this.transactionIdentifier = transactionIdentifier;
this.synchronizationStrategy = synchronizationStrategy;
}
@@ -47,7 +47,7 @@ public void afterCompletion(int i) {
}
finally {
//clean the Synchronization per Transaction
- sessionHolder.clear( transactionIdentifier );
+ sessionExtension.clear( transactionIdentifier );
}
}
}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/ConfiguredAutomaticIndexingStrategy.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/ConfiguredAutomaticIndexingStrategy.java
index 42753b89165..7eb3a60144a 100644
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/ConfiguredAutomaticIndexingStrategy.java
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/ConfiguredAutomaticIndexingStrategy.java
@@ -238,15 +238,15 @@ public PojoIndexingPlan createIndexingPlan(HibernateOrmSearchSession context,
}
public Synchronization createTransactionWorkQueueSynchronization(PojoIndexingPlan indexingPlan,
- HibernateOrmSearchSessionHolder sessionProperties,
+ HibernateOrmSearchSessionExtension sessionExtension,
Transaction transactionIdentifier,
ConfiguredIndexingPlanSynchronizationStrategy synchronizationStrategy) {
if ( enlistsInTransaction ) {
- return new BeforeCommitIndexingPlanSynchronization( indexingPlan, sessionProperties, transactionIdentifier,
+ return new BeforeCommitIndexingPlanSynchronization( indexingPlan, sessionExtension, transactionIdentifier,
synchronizationStrategy );
}
else {
- return new AfterCommitIndexingPlanSynchronization( indexingPlan, sessionProperties, transactionIdentifier,
+ return new AfterCommitIndexingPlanSynchronization( indexingPlan, sessionExtension, transactionIdentifier,
synchronizationStrategy );
}
}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java
index 2d158bd1020..6a96d0002e8 100644
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java
@@ -17,6 +17,7 @@
import org.hibernate.action.spi.BeforeTransactionCompletionProcess;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.search.engine.backend.common.spi.EntityReferenceFactory;
import org.hibernate.search.engine.search.common.NonStaticMetamodelScope;
import org.hibernate.search.engine.search.query.dsl.SearchQuerySelectStep;
@@ -66,7 +67,7 @@ public class HibernateOrmSearchSession extends AbstractPojoSearchSession
* @return The {@link HibernateOrmSearchSession} to use within the context of the given session.
*/
public static HibernateOrmSearchSession get(HibernateOrmSearchSessionMappingContext context,
- SessionImplementor sessionImplementor) {
+ SharedSessionContractImplementor sessionImplementor) {
return get( context, sessionImplementor, true );
}
@@ -75,14 +76,9 @@ public static HibernateOrmSearchSession get(HibernateOrmSearchSessionMappingCont
* @return The {@link HibernateOrmSearchSession} to use within the context of the given session.
*/
public static HibernateOrmSearchSession get(HibernateOrmSearchSessionMappingContext context,
- SessionImplementor sessionImplementor, boolean createIfDoesNotExist) {
- HibernateOrmSearchSessionHolder holder =
- HibernateOrmSearchSessionHolder.get( sessionImplementor, createIfDoesNotExist );
- if ( holder == null ) {
- // Can only happen if createIfDoesNotExist is false
- return null;
- }
- HibernateOrmSearchSession searchSession = holder.searchSession();
+ SharedSessionContractImplementor sessionImplementor, boolean createIfDoesNotExist) {
+ HibernateOrmSearchSessionExtension extension = HibernateOrmSearchSessionExtension.get( sessionImplementor );
+ HibernateOrmSearchSession searchSession = extension.searchSession();
if ( searchSession != null ) {
return searchSession;
}
@@ -91,9 +87,16 @@ public static HibernateOrmSearchSession get(HibernateOrmSearchSessionMappingCont
return null;
}
- searchSession = context.createSessionBuilder( sessionImplementor ).build();
- holder.searchSession( searchSession );
- return searchSession;
+ if ( sessionImplementor instanceof SessionImplementor implementor ) {
+ searchSession = context.createSessionBuilder( implementor ).build();
+ extension.searchSession( searchSession );
+ return searchSession;
+ }
+ else {
+ // TODO: For a stateless session need a different impl of the search session
+ throw new UnsupportedOperationException(
+ "Cannot create Search Session using a non stateful ORM session: " + sessionImplementor.getClass() );
+ }
}
private final HibernateOrmSearchSessionMappingContext mappingContext;
@@ -203,6 +206,10 @@ public TypedSearchScope typedScope(Class rootScope, Collectio
return mappingContext.createScope( rootScope, classes );
}
+ // TODO: won't be able to use these (toEntityManager / toOrmSession / session) in a stateless session case...
+ // options ?
+ // = deprecate and introduce some shared session interface instead ?
+ // = keep two search session interfaces one for stateless one for stateful ?
@Override
public EntityManager toEntityManager() {
return sessionImplementor;
@@ -213,6 +220,11 @@ public Session toOrmSession() {
return sessionImplementor;
}
+ @Override
+ public SessionImplementor session() {
+ return sessionImplementor;
+ }
+
@Override
public SearchIndexingPlan indexingPlan() {
if ( indexingPlan == null ) {
@@ -254,11 +266,6 @@ public ConfiguredSearchIndexingPlanFilter configuredIndexingPlanFilter() {
return configuredIndexingPlanFilter;
}
- @Override
- public SessionImplementor session() {
- return sessionImplementor;
- }
-
@Override
public EntityReferenceFactory entityReferenceFactory() {
return mappingContext.entityReferenceFactory();
@@ -276,9 +283,9 @@ public PojoRuntimeIntrospector runtimeIntrospector() {
@Override
public PojoIndexingPlan currentIndexingPlan(boolean createIfDoesNotExist) {
- HibernateOrmSearchSessionHolder holder =
- HibernateOrmSearchSessionHolder.get( sessionImplementor, createIfDoesNotExist );
- if ( holder == null ) {
+ HibernateOrmSearchSessionExtension extension =
+ HibernateOrmSearchSessionExtension.get( sessionImplementor );
+ if ( extension.searchSession() == null ) {
// Can only happen if createIfDoesNotExist is false
return null;
}
@@ -291,7 +298,7 @@ public PojoIndexingPlan currentIndexingPlan(boolean createIfDoesNotExist) {
transactionIdentifier = null;
}
- PojoIndexingPlan plan = holder.pojoIndexingPlan( transactionIdentifier );
+ PojoIndexingPlan plan = extension.pojoIndexingPlan( transactionIdentifier );
if ( plan != null ) {
return plan;
}
@@ -303,11 +310,11 @@ public PojoIndexingPlan currentIndexingPlan(boolean createIfDoesNotExist) {
ConfiguredIndexingPlanSynchronizationStrategy currentSynchronizationStrategy =
indexingPlanSynchronizationStrategy;
plan = automaticIndexingStrategy.createIndexingPlan( this, currentSynchronizationStrategy );
- holder.pojoIndexingPlan( transactionIdentifier, plan );
+ extension.pojoIndexingPlan( transactionIdentifier, plan );
if ( sessionImplementor.isTransactionInProgress() ) {
Synchronization txSync = automaticIndexingStrategy.createTransactionWorkQueueSynchronization(
- plan, holder, transactionIdentifier,
+ plan, extension, transactionIdentifier,
currentSynchronizationStrategy
);
registerSynchronization( sessionImplementor, txSync );
@@ -347,6 +354,10 @@ private void registerSynchronization(SessionImplementor sessionImplementor, Sync
* In a JTA env, the before transaction completion is called before the flush, so not all changes are yet
* written. However, Synchronization-s do propagate exceptions, so they can be safely used.
*/
+
+ // TODO: There's no action queue with stateless session ...
+ // Hence it would be great if we could just have an SPI in ORM to deal with this instead?
+ // TODO: Have a closer look at this part to figure the best way to deal with stateless sessions..
final ActionQueue actionQueue = sessionImplementor.getActionQueue();
SynchronizationAdapter adapter = new SynchronizationAdapter( synchronization );
@@ -372,7 +383,7 @@ private boolean isLocalTransaction(SessionImplementor sessionImplementor) {
.isJta();
}
- private static void checkOpen(SessionImplementor session) {
+ private static void checkOpen(SharedSessionContractImplementor session) {
try {
session.checkOpen();
}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionExtension.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionExtension.java
new file mode 100644
index 00000000000..9a582eedc00
--- /dev/null
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionExtension.java
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.search.mapper.orm.session.impl;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.hibernate.Transaction;
+import org.hibernate.engine.extension.spi.Extension;
+import org.hibernate.engine.spi.SharedSessionContractImplementor;
+import org.hibernate.search.mapper.pojo.work.spi.PojoIndexingPlan;
+
+public class HibernateOrmSearchSessionExtension implements Serializable, Extension {
+
+ public static HibernateOrmSearchSessionExtension get(SharedSessionContractImplementor session) {
+ return session.getExtension( HibernateOrmSearchSessionExtension.class );
+ }
+
+ // Everything here should be transient because the holder might get serialized along with a Hibernate ORM session.
+ // The Hibernate Search data (indexing plans in particular) will be lost in the process,
+ // but that's the best we can do.
+ private transient HibernateOrmSearchSession searchSession;
+ private transient Map planPerTransaction;
+
+ public static HibernateOrmSearchSessionExtension init() {
+ return new HibernateOrmSearchSessionExtension();
+ }
+
+ public HibernateOrmSearchSession searchSession() {
+ return searchSession;
+ }
+
+ public void searchSession(HibernateOrmSearchSession searchSession) {
+ this.searchSession = searchSession;
+ }
+
+ public PojoIndexingPlan pojoIndexingPlan(Transaction transaction) {
+ return planPerTransaction == null ? null : planPerTransaction.get( transaction );
+ }
+
+ public void pojoIndexingPlan(Transaction transaction, PojoIndexingPlan plan) {
+ if ( planPerTransaction == null ) {
+ planPerTransaction = new HashMap<>();
+ }
+ planPerTransaction.put( transaction, plan );
+ }
+
+ public void clear(Transaction transactionIdentifier) {
+ if ( planPerTransaction == null ) {
+ return;
+ }
+ planPerTransaction.remove( transactionIdentifier );
+ }
+}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionHolder.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionHolder.java
deleted file mode 100644
index 42b770c713c..00000000000
--- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionHolder.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * Copyright Red Hat Inc. and Hibernate Authors
- */
-package org.hibernate.search.mapper.orm.session.impl;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import jakarta.transaction.Synchronization;
-
-import org.hibernate.Transaction;
-import org.hibernate.engine.spi.SessionImplementor;
-import org.hibernate.search.mapper.pojo.work.spi.PojoIndexingPlan;
-
-public class HibernateOrmSearchSessionHolder implements Serializable {
-
- private static final String SESSION_PROPERTY_KEY = "hibernate.search.session";
-
- private static final Map holderPerClosedSessionTransaction =
- new ConcurrentHashMap<>();
-
- // Public for tests only
- public static int staticMapSize() {
- return holderPerClosedSessionTransaction.size();
- }
-
- public static HibernateOrmSearchSessionHolder get(SessionImplementor session, boolean createIfMissing) {
- HibernateOrmSearchSessionHolder holder =
- (HibernateOrmSearchSessionHolder) session.getProperties().get( SESSION_PROPERTY_KEY );
- if ( holder != null ) {
- return holder;
- }
- boolean closedSessionAndTransaction = session.isClosed() && session.isTransactionInProgress();
- if ( closedSessionAndTransaction ) {
- // This can happen when using JTA.
- // Only do this as a fallback: if somehow the session holder was added to the session properties
- // before the session was closed, we definitely want to use it and avoid the static map.
- holder = holderPerClosedSessionTransaction.get( session.accessTransaction() );
- }
- if ( holder != null ) {
- return holder;
- }
- if ( !createIfMissing ) {
- return null;
- }
- holder = new HibernateOrmSearchSessionHolder();
- if ( closedSessionAndTransaction ) {
- // This can happen when using JTA.
- Transaction transaction = session.accessTransaction();
- transaction.registerSynchronization( new HolderPerClosedSessionTransactionCleanup( transaction ) );
- holderPerClosedSessionTransaction.put( transaction, holder );
- }
- else {
- session.setProperty( SESSION_PROPERTY_KEY, holder );
- }
- return holder;
- }
-
- // Everything here should be transient because the holder might get serialized along with a Hibernate ORM session.
- // The Hibernate Search data (indexing plans in particular) will be lost in the process,
- // but that's the best we can do.
- private transient HibernateOrmSearchSession searchSession;
- private transient Map planPerTransaction;
-
- public HibernateOrmSearchSession searchSession() {
- return searchSession;
- }
-
- public void searchSession(HibernateOrmSearchSession searchSession) {
- this.searchSession = searchSession;
- }
-
- public PojoIndexingPlan pojoIndexingPlan(Transaction transaction) {
- return planPerTransaction == null ? null : planPerTransaction.get( transaction );
- }
-
- public void pojoIndexingPlan(Transaction transaction, PojoIndexingPlan plan) {
- if ( planPerTransaction == null ) {
- planPerTransaction = new HashMap<>();
- }
- planPerTransaction.put( transaction, plan );
- }
-
- public void clear(Transaction transactionIdentifier) {
- if ( planPerTransaction == null ) {
- return;
- }
- planPerTransaction.remove( transactionIdentifier );
- }
-
- private static class HolderPerClosedSessionTransactionCleanup implements Synchronization {
- private final Transaction transaction;
-
- public HolderPerClosedSessionTransactionCleanup(Transaction transaction) {
- this.transaction = transaction;
- }
-
- @Override
- public void beforeCompletion() {
- // Nothing to do
- }
-
- @Override
- public void afterCompletion(int i) {
- holderPerClosedSessionTransaction.remove( transaction );
- }
- }
-}
diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateSearchSessionExtensionIntegration.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateSearchSessionExtensionIntegration.java
new file mode 100644
index 00000000000..fa59cdc9a4a
--- /dev/null
+++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateSearchSessionExtensionIntegration.java
@@ -0,0 +1,20 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.search.mapper.orm.session.impl;
+
+import org.hibernate.engine.extension.spi.ExtensionIntegration;
+import org.hibernate.engine.extension.spi.ExtensionIntegrationContext;
+
+public class HibernateSearchSessionExtensionIntegration implements ExtensionIntegration {
+ @Override
+ public Class getExtensionType() {
+ return HibernateOrmSearchSessionExtension.class;
+ }
+
+ @Override
+ public HibernateOrmSearchSessionExtension createExtension(ExtensionIntegrationContext extensionIntegrationContext) {
+ return HibernateOrmSearchSessionExtension.init();
+ }
+}
diff --git a/mapper/orm/src/main/resources/META-INF/services/org.hibernate.engine.extension.spi.ExtensionIntegration b/mapper/orm/src/main/resources/META-INF/services/org.hibernate.engine.extension.spi.ExtensionIntegration
new file mode 100644
index 00000000000..8fa058c7029
--- /dev/null
+++ b/mapper/orm/src/main/resources/META-INF/services/org.hibernate.engine.extension.spi.ExtensionIntegration
@@ -0,0 +1 @@
+org.hibernate.search.mapper.orm.session.impl.HibernateSearchSessionExtensionIntegration