[FIX] Correctly close JPA EntityManager in a couple of places (#1574)

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 dcd23ba..fa1fcff 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.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 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 3e4c6d1..2f5c5a9 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.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 @@
 
         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 @@
 
         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 a974612..7dbea33 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.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 @@
 
     @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)));