This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch 3.8.x in repository https://gitbox.apache.org/repos/asf/james-project.git
commit e0e6f24bd0563d9a556c7ed8cd60dd984d0cb556 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Tue May 30 08:56:18 2023 +0700 [FIX] Correctly close JPA EntityManager in a couple of places (#1574) --- .../mailbox/jpa/quota/JPAPerUserMaxQuotaDAO.java | 73 +++++++++++++++------- .../mailbox/jpa/quota/JpaCurrentQuotaManager.java | 10 ++- .../james/jpa/healthcheck/JPAHealthCheck.java | 17 ++--- 3 files changed, 65 insertions(+), 35 deletions(-) diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JPAPerUserMaxQuotaDAO.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JPAPerUserMaxQuotaDAO.java index dcd23bae35..fa1fcffaca 100644 --- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JPAPerUserMaxQuotaDAO.java +++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JPAPerUserMaxQuotaDAO.java @@ -26,6 +26,7 @@ import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import org.apache.james.backends.jpa.EntityManagerUtils; import org.apache.james.backends.jpa.TransactionRunner; import org.apache.james.core.Domain; import org.apache.james.core.quota.QuotaCountLimit; @@ -163,56 +164,80 @@ public class JPAPerUserMaxQuotaDAO { public Optional<QuotaSizeLimit> getGlobalMaxStorage() { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxGlobalStorage storedValue = entityManager.find(MaxGlobalStorage.class, MaxGlobalStorage.DEFAULT_KEY); - if (storedValue == null) { - return Optional.empty(); + try { + MaxGlobalStorage storedValue = entityManager.find(MaxGlobalStorage.class, MaxGlobalStorage.DEFAULT_KEY); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaSize(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaSize(storedValue.getValue()); } public Optional<QuotaCountLimit> getGlobalMaxMessage() { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxGlobalMessageCount storedValue = entityManager.find(MaxGlobalMessageCount.class, MaxGlobalMessageCount.DEFAULT_KEY); - if (storedValue == null) { - return Optional.empty(); + try { + MaxGlobalMessageCount storedValue = entityManager.find(MaxGlobalMessageCount.class, MaxGlobalMessageCount.DEFAULT_KEY); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaCount(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaCount(storedValue.getValue()); } public Optional<QuotaSizeLimit> getMaxStorage(QuotaRoot quotaRoot) { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxUserStorage storedValue = entityManager.find(MaxUserStorage.class, quotaRoot.getValue()); - if (storedValue == null) { - return Optional.empty(); + try { + MaxUserStorage storedValue = entityManager.find(MaxUserStorage.class, quotaRoot.getValue()); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaSize(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaSize(storedValue.getValue()); } public Optional<QuotaCountLimit> getMaxMessage(QuotaRoot quotaRoot) { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxUserMessageCount storedValue = entityManager.find(MaxUserMessageCount.class, quotaRoot.getValue()); - if (storedValue == null) { - return Optional.empty(); + try { + MaxUserMessageCount storedValue = entityManager.find(MaxUserMessageCount.class, quotaRoot.getValue()); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaCount(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaCount(storedValue.getValue()); } public Optional<QuotaCountLimit> getDomainMaxMessage(Domain domain) { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxDomainMessageCount storedValue = entityManager.find(MaxDomainMessageCount.class, domain.asString()); - if (storedValue == null) { - return Optional.empty(); + try { + MaxDomainMessageCount storedValue = entityManager.find(MaxDomainMessageCount.class, domain.asString()); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaCount(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaCount(storedValue.getValue()); } public Optional<QuotaSizeLimit> getDomainMaxStorage(Domain domain) { EntityManager entityManager = entityManagerFactory.createEntityManager(); - MaxDomainStorage storedValue = entityManager.find(MaxDomainStorage.class, domain.asString()); - if (storedValue == null) { - return Optional.empty(); + try { + MaxDomainStorage storedValue = entityManager.find(MaxDomainStorage.class, domain.asString()); + if (storedValue == null) { + return Optional.empty(); + } + return longToQuotaSize(storedValue.getValue()); + } finally { + EntityManagerUtils.safelyClose(entityManager); } - return longToQuotaSize(storedValue.getValue()); } diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java index 3e4c6d161a..2f5c5a980d 100644 --- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java +++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/quota/JpaCurrentQuotaManager.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import org.apache.james.backends.jpa.EntityManagerUtils; import org.apache.james.backends.jpa.TransactionRunner; import org.apache.james.core.quota.QuotaCountUsage; import org.apache.james.core.quota.QuotaSizeUsage; @@ -56,7 +57,8 @@ public class JpaCurrentQuotaManager implements CurrentQuotaManager { return Mono.fromCallable(() -> Optional.ofNullable(retrieveUserQuota(entityManager, quotaRoot)) .map(JpaCurrentQuota::getMessageCount) - .orElse(QuotaCountUsage.count(NO_STORED_BYTES))); + .orElse(QuotaCountUsage.count(NO_STORED_BYTES))) + .doFinally(any -> EntityManagerUtils.safelyClose(entityManager)); } @Override @@ -65,14 +67,16 @@ public class JpaCurrentQuotaManager implements CurrentQuotaManager { return Mono.fromCallable(() -> Optional.ofNullable(retrieveUserQuota(entityManager, quotaRoot)) .map(JpaCurrentQuota::getSize) - .orElse(QuotaSizeUsage.size(NO_STORED_BYTES))); + .orElse(QuotaSizeUsage.size(NO_STORED_BYTES))) + .doFinally(any -> EntityManagerUtils.safelyClose(entityManager)); } public Mono<CurrentQuotas> getCurrentQuotas(QuotaRoot quotaRoot) { EntityManager entityManager = entityManagerFactory.createEntityManager(); return Mono.fromCallable(() -> Optional.ofNullable(retrieveUserQuota(entityManager, quotaRoot)) .map(jpaCurrentQuota -> new CurrentQuotas(jpaCurrentQuota.getMessageCount(), jpaCurrentQuota.getSize())) - .orElse(CurrentQuotas.emptyQuotas())); + .orElse(CurrentQuotas.emptyQuotas())) + .doFinally(any -> EntityManagerUtils.safelyClose(entityManager)); } @Override diff --git a/server/data/data-jpa/src/main/java/org/apache/james/jpa/healthcheck/JPAHealthCheck.java b/server/data/data-jpa/src/main/java/org/apache/james/jpa/healthcheck/JPAHealthCheck.java index a97461223a..7dbea33e7f 100644 --- a/server/data/data-jpa/src/main/java/org/apache/james/jpa/healthcheck/JPAHealthCheck.java +++ b/server/data/data-jpa/src/main/java/org/apache/james/jpa/healthcheck/JPAHealthCheck.java @@ -22,14 +22,15 @@ import static org.apache.james.core.healthcheck.Result.healthy; import static org.apache.james.core.healthcheck.Result.unhealthy; import javax.inject.Inject; -import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import org.apache.james.backends.jpa.EntityManagerUtils; import org.apache.james.core.healthcheck.ComponentName; import org.apache.james.core.healthcheck.HealthCheck; import org.apache.james.core.healthcheck.Result; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; public class JPAHealthCheck implements HealthCheck { @@ -47,15 +48,15 @@ public class JPAHealthCheck implements HealthCheck { @Override public Mono<Result> check() { - return Mono.fromCallable(entityManagerFactory::createEntityManager) - .map(EntityManager::isOpen) - .map(open -> { - if (open) { - return healthy(componentName()); + return Mono.usingWhen(Mono.fromCallable(entityManagerFactory::createEntityManager).subscribeOn(Schedulers.boundedElastic()), + entityManager -> { + if (entityManager.isOpen()) { + return Mono.just(healthy(componentName())); } else { - return unhealthy(componentName(), "entityManager is not open"); + return Mono.just(unhealthy(componentName(), "entityManager is not open")); } - }) + }, + entityManager -> Mono.fromRunnable(() -> EntityManagerUtils.safelyClose(entityManager)).subscribeOn(Schedulers.boundedElastic())) .onErrorResume(IllegalStateException.class, e -> Mono.just(unhealthy(componentName(), "EntityManagerFactory or EntityManager thrown an IllegalStateException, the connection is unhealthy", e))) .onErrorResume(e -> Mono.just(unhealthy(componentName(), "Unexpected exception upon checking JPA driver", e))); --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org