You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2019/12/18 11:23:15 UTC

[james-project] branch master updated (4bfb763 -> 9638ef4)

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.


    from 4bfb763  JAMES-2993 201 does only mean task generation success
     new 9f3ed02  JAMES-3008 Reactive BlobPutter
     new 207ad0a  JAMES-3008 Remove unused parameter in AWS blobPutter
     new 9fdbcd8  [Refactoring] Replacing NoopMetricFactory by RecordingMetricFactory
     new 2e9ce57  [Refactoring] use DropWizardMetric in Spring
     new a36539e  [Refactoring] Spring: Replacing NoopMetricFactory by RecordingMetricFactory
     new 6e98527  [Refactoring] PreDeleletionHook: Optional MetricFactory
     new c650863  [Refactoring] Remove unused constructors in LMTPProtocolHandlerChain
     new 4361d3c  [Refactoring] Move LMTPProtocolHandlerChain to test and use RecordingMetric
     new b448717  [Refactoring] Drop NoopMetricFactory
     new c282daa  JAMES-2991 Bind ComputeMessageFastViewProjectionListener in JMAP products
     new cd3f608  JAMES-2993 Create a Preview.Factory
     new ffc5eb9  JAMES-2991 Full content is required for preview computation
     new 9638ef4  JAMES-2919 MessageFastView projection changelog entry

The 13 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGELOG.md                                       |   1 +
 examples/custom-listeners/pom.xml                  |   5 +
 mailbox/api/pom.xml                                |   5 +
 mailbox/backup/pom.xml                             |   5 +
 mailbox/cassandra/pom.xml                          |   5 +
 .../cassandra/CassandraCombinationManagerTest.java |   4 +-
 .../cassandra/CassandraMailboxManagerProvider.java |   4 +-
 .../cassandra/CassandraMailboxManagerTest.java     |   4 +-
 .../CassandraMessageIdManagerStorageTest.java      |   4 +-
 .../CassandraMessageIdManagerTestSystem.java       |   4 +-
 .../cassandra/CassandraTestSystemFixture.java      |   4 +-
 .../CassandraMailboxManagerAttachmentTest.java     |   4 +-
 mailbox/elasticsearch/pom.xml                      |   5 +
 .../ElasticSearchIntegrationTest.java              |   4 +-
 .../elasticsearch/json/IndexableMessageTest.java   |   4 +-
 .../json/MessageToElasticSearchJsonTest.java       |   4 +-
 mailbox/event/event-memory/pom.xml                 |   5 +
 .../james/mailbox/events/InVMEventBusTest.java     |   4 +-
 .../events/delivery/InVmEventDeliveryTest.java     |   4 +-
 mailbox/event/event-rabbitmq/pom.xml               |   5 +
 .../james/mailbox/events/RabbitMQEventBusTest.java |   4 +-
 mailbox/jpa/pom.xml                                |   5 +
 .../mailbox/jpa/JpaMailboxManagerProvider.java     |   4 +-
 mailbox/lucene/pom.xml                             |   5 +
 mailbox/maildir/pom.xml                            |   5 +
 .../maildir/MaildirMailboxManagerProvider.java     |   4 +-
 mailbox/memory/pom.xml                             |   5 +
 .../manager/InMemoryIntegrationResources.java      |   6 +-
 .../james/vault/DeletedMessageVaultHookTest.java   |   4 +-
 mailbox/plugin/quota-mailing-cassandra/pom.xml     |   5 +
 mailbox/plugin/quota-mailing-memory/pom.xml        |   5 +
 mailbox/plugin/quota-mailing/pom.xml               |   5 +
 .../QuotaThresholdListenersTestSystem.java         |   4 +-
 mailbox/plugin/quota-search-elasticsearch/pom.xml  |   5 +
 mailbox/plugin/quota-search-scanning/pom.xml       |   5 +
 mailbox/plugin/spamassassin/pom.xml                |   5 +
 mailbox/scanning-search/pom.xml                    |   5 +
 mailbox/spring/pom.xml                             |   5 +
 .../src/test/resources/META-INF/spring/metrics.xml |   2 +-
 .../james/mailbox/store/PreDeletionHooks.java      |  21 ++-
 .../AbstractMessageIdManagerSideEffectTest.java    |   4 +-
 .../mailbox/store/StoreMailboxManagerTest.java     |   4 +-
 mailbox/tika/pom.xml                               |   5 +
 .../mailbox/tika/CachingTextExtractorTest.java     |   4 +-
 .../james/mailbox/tika/TikaTextExtractorTest.java  |  10 +-
 mailbox/tools/copier/pom.xml                       |   5 +
 mailbox/tools/indexer/pom.xml                      |   5 +
 .../james/metrics/api/NoopMetricFactory.java       |  66 ----------
 mpt/impl/imap-mailbox/cassandra/pom.xml            |   5 +
 .../cassandra/host/CassandraHostSystem.java        |   4 +-
 mpt/impl/imap-mailbox/elasticsearch/pom.xml        |   5 +
 mpt/impl/imap-mailbox/inmemory/pom.xml             |   5 +
 mpt/impl/imap-mailbox/jpa/pom.xml                  |   5 +
 .../mpt/imapmailbox/jpa/host/JPAHostSystem.java    |   4 +-
 mpt/impl/imap-mailbox/lucenesearch/pom.xml         |   5 +
 mpt/impl/imap-mailbox/maildir/pom.xml              |   5 +
 .../maildir/host/MaildirHostSystem.java            |   4 +-
 mpt/impl/imap-mailbox/rabbitmq/pom.xml             |   5 +
 .../rabbitmq/host/RabbitMQEventBusHostSystem.java  |   4 +-
 protocols/imap/pom.xml                             |   5 +
 .../james/imap/processor/CopyProcessorTest.java    |   4 +-
 .../imap/processor/DeleteACLProcessorTest.java     |   4 +-
 .../james/imap/processor/GetACLProcessorTest.java  |   4 +-
 .../imap/processor/GetAnnotationProcessorTest.java |   4 +-
 .../imap/processor/GetQuotaProcessorTest.java      |   4 +-
 .../imap/processor/GetQuotaRootProcessorTest.java  |   4 +-
 .../james/imap/processor/LSubProcessorTest.java    |   4 +-
 .../imap/processor/ListRightsProcessorTest.java    |   4 +-
 .../james/imap/processor/MoveProcessorTest.java    |   6 +-
 .../imap/processor/NamespaceProcessorTest.java     |   4 +-
 .../james/imap/processor/SearchProcessorTest.java  |   4 +-
 .../james/imap/processor/SetACLProcessorTest.java  |   4 +-
 .../imap/processor/SetAnnotationProcessorTest.java |   4 +-
 .../imap/processor/SetQuotaProcessorTest.java      |   4 +-
 .../processor/base/MailboxEventAnalyserTest.java   |   4 +-
 protocols/lmtp/pom.xml                             |   5 +
 .../protocols/lmtp/LMTPProtocolHandlerChain.java   |  26 ++--
 protocols/smtp/pom.xml                             |   5 +
 .../protocols/smtp/AbstractSMTPServerTest.java     |   4 +-
 .../smtp/netty/NettyStartTlsSMTPServerTest.java    |   4 +-
 .../james/blob/objectstorage/BlobPutter.java       |   6 +-
 .../blob/objectstorage/ObjectStorageBlobStore.java |  38 +++---
 .../objectstorage/StreamCompatibleBlobPutter.java  |  20 +--
 .../blob/objectstorage/aws/AwsS3ObjectStorage.java |  42 +++---
 server/container/guice/mailbox/pom.xml             |   5 +
 .../mailbox/MailboxListenersLoaderImplTest.java    |   5 +-
 .../apache/james/jmap/draft/JMAPCommonModule.java  |   6 +
 server/container/mailbox-jmx/pom.xml               |   5 +
 .../org/apache/james/jmap/api/model/Preview.java   |  50 +++++++
 .../MessageFastViewPrecomputedProperties.java      |  28 ++++
 server/dns-service/dnsservice-dnsjava/pom.xml      |   5 +
 .../dnsservice/dnsjava/DNSJavaServiceTest.java     |   4 +-
 server/mailet/mailetcontainer-camel/pom.xml        |   5 +
 .../impl/camel/CamelCompositeProcessorTest.java    |   4 +-
 .../impl/camel/CamelMailetProcessorTest.java       |   4 +-
 server/mailet/mailets/pom.xml                      |  10 +-
 .../james/transport/mailets/SpamAssassinTest.java  |   4 +-
 .../mailets/delivery/LocalDeliveryTest.java        |   4 +-
 .../mailets/delivery/ToRecipientFolderTest.java    |   4 +-
 .../remote/delivery/RemoteDeliveryTest.java        |   4 +-
 server/protocols/jmap-draft/pom.xml                |   5 +
 .../ComputeMessageFastViewProjectionListener.java  |  19 +--
 .../MessageFastViewProjectionItemFactoryTest.java  | 144 +++++++++++++++++++++
 .../org/apache/james/jmap/PreviewFactoryTest.java  |  73 +++++++++++
 .../james/jmap/draft/AuthenticationFilterTest.java |  10 +-
 .../DefaultMailboxesProvisioningFilterTest.java    |   5 +-
 ...faultMailboxesProvisioningFilterThreadTest.java |   5 +-
 .../james/jmap/draft/DownloadServletTest.java      |   5 +-
 .../apache/james/jmap/draft/JMAPServletTest.java   |   7 +-
 .../jmap/draft/UserProvisioningFilterTest.java     |   8 +-
 .../draft/UserProvisioningFilterThreadTest.java    |   4 +-
 .../jmap/draft/methods/GetMessagesMethodTest.java  |   6 +-
 .../jmap/draft/methods/MessageSenderTest.java      |   4 +-
 .../methods/SetMailboxesCreationProcessorTest.java |   4 +-
 .../methods/SetMailboxesUpdateProcessorTest.java   |   4 +-
 .../methods/SetMessagesCreationProcessorTest.java  |  10 +-
 .../methods/SetMessagesUpdateProcessorTest.java    |   6 +-
 .../message/view/MessageFastViewFactoryTest.java   |   6 +-
 .../message/view/MessageFullViewFactoryTest.java   |   4 +-
 ...mputeMessageFastViewProjectionListenerTest.java |   9 +-
 .../src/test/resources/inlineAttachment.eml        |   1 +
 .../src/test/resources/oneAttachment.eml           |   0
 server/protocols/protocols-pop3/pom.xml            |   5 +
 server/protocols/protocols-smtp/pom.xml            |   5 +
 .../apache/james/smtpserver/SMTPServerTest.java    |   4 +-
 .../james/smtpserver/SpamAssassinHandlerTest.java  |   8 +-
 .../webadmin/webadmin-cassandra-data/pom.xml       |   5 +
 .../protocols/webadmin/webadmin-cassandra/pom.xml  |   5 +
 server/protocols/webadmin/webadmin-core/pom.xml    |   5 +
 .../org/apache/james/webadmin/WebAdminUtils.java   |   5 +-
 server/protocols/webadmin/webadmin-data/pom.xml    |  10 +-
 .../webadmin-mailbox-deleted-message-vault/pom.xml |   5 +
 .../routes/DeletedMessagesVaultRoutesTest.java     |   4 +-
 server/protocols/webadmin/webadmin-mailbox/pom.xml |   5 +
 .../routes/EventDeadLettersRoutesTest.java         |   4 +-
 .../protocols/webadmin/webadmin-mailqueue/pom.xml  |   5 +
 .../webadmin/webadmin-mailrepository/pom.xml       |   5 +
 .../activemq/ActiveMQMailQueueFactoryTest.java     |   6 +-
 .../james/queue/jms/JMSMailQueueFactoryTest.java   |   4 +-
 .../RabbitMQMailQueueConfigurationChangeTest.java  |   4 +-
 .../rabbitmq/RabbitMqMailQueueFactoryTest.java     |   4 +-
 third-party/spamassassin/pom.xml                   |   5 +
 .../spamassassin/SpamAssassinInvokerTest.java      |   4 +-
 143 files changed, 809 insertions(+), 348 deletions(-)
 delete mode 100644 metrics/metrics-api/src/main/java/org/apache/james/metrics/api/NoopMetricFactory.java
 rename protocols/lmtp/src/{main => test}/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java (80%)
 create mode 100644 server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/MessageFastViewProjectionItemFactoryTest.java
 create mode 100644 server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/PreviewFactoryTest.java
 copy mailbox/store/src/test/resources/eml/noContentDispositionWithCID.eml => server/protocols/jmap-draft/src/test/resources/inlineAttachment.eml (95%)
 copy mailbox/store/src/test/resources/eml/emailWithOnlyAttachment.eml => server/protocols/jmap-draft/src/test/resources/oneAttachment.eml (100%)


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 01/13: JAMES-3008 Reactive BlobPutter

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 9f3ed027972034b7823ce0ba15783cf388d39ba0
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 12 15:37:12 2019 +0700

    JAMES-3008 Reactive BlobPutter
    
    Avoids two threads waiting for the same Blob operation
---
 .../james/blob/objectstorage/BlobPutter.java       |  6 ++--
 .../blob/objectstorage/ObjectStorageBlobStore.java | 38 +++++++++++---------
 .../objectstorage/StreamCompatibleBlobPutter.java  | 20 +++++------
 .../blob/objectstorage/aws/AwsS3ObjectStorage.java | 40 ++++++++++------------
 4 files changed, 53 insertions(+), 51 deletions(-)

diff --git a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/BlobPutter.java b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/BlobPutter.java
index 4a229bf..8fe1a2b 100644
--- a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/BlobPutter.java
+++ b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/BlobPutter.java
@@ -24,6 +24,8 @@ import java.util.function.Supplier;
 import org.apache.james.blob.api.BlobId;
 import org.jclouds.blobstore.domain.Blob;
 
+import reactor.core.publisher.Mono;
+
 /**
  * Implementations may have specific behaviour when uploading a blob,
  * such cases are not well handled by jClouds.
@@ -36,7 +38,7 @@ import org.jclouds.blobstore.domain.Blob;
 
 public interface BlobPutter {
 
-    void putDirectly(ObjectStorageBucketName bucketName, Blob blob);
+    Mono<Void> putDirectly(ObjectStorageBucketName bucketName, Blob blob);
 
-    BlobId putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier);
+    Mono<BlobId> putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier);
 }
diff --git a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobStore.java b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobStore.java
index 8a0628e..fbe82ed 100644
--- a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobStore.java
+++ b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/ObjectStorageBlobStore.java
@@ -100,16 +100,18 @@ public class ObjectStorageBlobStore implements BlobStore {
         Preconditions.checkNotNull(data);
         ObjectStorageBucketName resolvedBucketName = bucketNameResolver.resolve(bucketName);
 
-        BlobId blobId = blobIdFactory.forPayload(data);
-        Payload payload = payloadCodec.write(data);
+        return Mono.fromCallable(() -> blobIdFactory.forPayload(data))
+            .flatMap(blobId -> {
+                Payload payload = payloadCodec.write(data);
 
-        Blob blob = blobStore.blobBuilder(blobId.asString())
-            .payload(payload.getPayload())
-            .contentLength(payload.getLength().orElse(Long.valueOf(data.length)))
-            .build();
+                Blob blob = blobStore.blobBuilder(blobId.asString())
+                    .payload(payload.getPayload())
+                    .contentLength(payload.getLength().orElse(Long.valueOf(data.length)))
+                    .build();
 
-        return Mono.fromRunnable(() -> blobPutter.putDirectly(resolvedBucketName, blob))
-            .thenReturn(blobId);
+                return blobPutter.putDirectly(resolvedBucketName, blob)
+                    .thenReturn(blobId);
+            });
     }
 
     @Override
@@ -143,15 +145,17 @@ public class ObjectStorageBlobStore implements BlobStore {
     private Mono<BlobId> saveBigStream(BucketName bucketName, InputStream data) {
         ObjectStorageBucketName resolvedBucketName = bucketNameResolver.resolve(bucketName);
 
-        BlobId tmpId = blobIdFactory.randomId();
-        HashingInputStream hashingInputStream = new HashingInputStream(Hashing.sha256(), data);
-        Payload payload = payloadCodec.write(hashingInputStream);
-        Blob blob = blobStore.blobBuilder(tmpId.asString())
-                            .payload(payload.getPayload())
-                            .build();
-
-        Supplier<BlobId> blobIdSupplier = () -> blobIdFactory.from(hashingInputStream.hash().toString());
-        return Mono.fromRunnable(() -> blobPutter.putAndComputeId(resolvedBucketName, blob, blobIdSupplier));
+        return Mono.fromCallable(blobIdFactory::randomId)
+            .flatMap(tmpId -> {
+                HashingInputStream hashingInputStream = new HashingInputStream(Hashing.sha256(), data);
+                Payload payload = payloadCodec.write(hashingInputStream);
+                Blob blob = blobStore.blobBuilder(tmpId.asString())
+                    .payload(payload.getPayload())
+                    .build();
+
+                Supplier<BlobId> blobIdSupplier = () -> blobIdFactory.from(hashingInputStream.hash().toString());
+                return blobPutter.putAndComputeId(resolvedBucketName, blob, blobIdSupplier);
+            });
     }
 
     @Override
diff --git a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/StreamCompatibleBlobPutter.java b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/StreamCompatibleBlobPutter.java
index 30ad89c..269a8a4 100644
--- a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/StreamCompatibleBlobPutter.java
+++ b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/StreamCompatibleBlobPutter.java
@@ -50,8 +50,8 @@ public class StreamCompatibleBlobPutter implements BlobPutter {
     }
 
     @Override
-    public void putDirectly(ObjectStorageBucketName bucketName, Blob blob) {
-        Mono.fromRunnable(() -> blobStore.putBlob(bucketName.asString(), blob))
+    public Mono<Void> putDirectly(ObjectStorageBucketName bucketName, Blob blob) {
+        return Mono.fromRunnable(() -> blobStore.putBlob(bucketName.asString(), blob))
             .publishOn(Schedulers.elastic())
             .retryWhen(Retry.onlyIf(retryContext -> needToCreateBucket(retryContext.exception(), bucketName))
                 .exponentialBackoff(FIRST_BACK_OFF, FOREVER)
@@ -62,21 +62,21 @@ public class StreamCompatibleBlobPutter implements BlobPutter {
                 .withBackoffScheduler(Schedulers.elastic())
                 .exponentialBackoff(FIRST_BACK_OFF, FOREVER)
                 .retryMax(RETRY_ONE_LAST_TIME_ON_CONCURRENT_SAVING))
-            .block();
+            .then();
     }
 
     @Override
-    public BlobId putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier) {
-        putDirectly(bucketName, initialBlob);
-        BlobId finalId = blobIdSupplier.get();
-        updateBlobId(bucketName, initialBlob.getMetadata().getName(), finalId.asString());
-        return finalId;
+    public Mono<BlobId> putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier) {
+        return putDirectly(bucketName, initialBlob)
+            .then(Mono.fromCallable(blobIdSupplier::get))
+            .map(blobId -> updateBlobId(bucketName, initialBlob.getMetadata().getName(), blobId));
     }
 
-    private void updateBlobId(ObjectStorageBucketName bucketName, String from, String to) {
+    private BlobId updateBlobId(ObjectStorageBucketName bucketName, String from, BlobId to) {
         String bucketNameAsString = bucketName.asString();
-        blobStore.copyBlob(bucketNameAsString, from, bucketNameAsString, to, CopyOptions.NONE);
+        blobStore.copyBlob(bucketNameAsString, from, bucketNameAsString, to.asString(), CopyOptions.NONE);
         blobStore.removeBlob(bucketNameAsString, from);
+        return to;
     }
 
     private boolean needToCreateBucket(Throwable throwable, ObjectStorageBucketName bucketName) {
diff --git a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
index db7cd67..e02577a 100644
--- a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
+++ b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
@@ -20,14 +20,13 @@
 package org.apache.james.blob.objectstorage.aws;
 
 import java.io.File;
-import java.io.IOException;
 import java.time.Duration;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.UUID;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 import javax.annotation.PreDestroy;
@@ -146,33 +145,30 @@ public class AwsS3ObjectStorage {
         }
 
         @Override
-        public void putDirectly(ObjectStorageBucketName bucketName, Blob blob) {
-            writeFileAndAct(blob, (file) -> putWithRetry(bucketName, configuration, blob, file, FIRST_TRY).block());
+        public Mono<Void> putDirectly(ObjectStorageBucketName bucketName, Blob blob) {
+            return writeFileAndAct(blob, file -> putWithRetry(bucketName, configuration, blob, file, FIRST_TRY));
         }
 
         @Override
-        public BlobId putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier) {
-            Consumer<File> putChangedBlob = (file) -> {
+        public Mono<BlobId> putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier) {
+            Function<File, Mono<Void>> putChangedBlob = file -> {
                 initialBlob.getMetadata().setName(blobIdSupplier.get().asString());
-                putWithRetry(bucketName, configuration, initialBlob, file, FIRST_TRY).block();
+                return putWithRetry(bucketName, configuration, initialBlob, file, FIRST_TRY);
             };
-            writeFileAndAct(initialBlob, putChangedBlob);
-            return blobIdSupplier.get();
+            return writeFileAndAct(initialBlob, putChangedBlob)
+                .then(Mono.fromCallable(blobIdSupplier::get));
         }
 
-        private void writeFileAndAct(Blob blob, Consumer<File> putFile) {
-            File file = null;
-            try {
-                file = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
-                FileUtils.copyToFile(blob.getPayload().openStream(), file);
-                putFile.accept(file);
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            } finally {
-                if (file != null) {
-                    FileUtils.deleteQuietly(file);
-                }
-            }
+        private Mono<Void> writeFileAndAct(Blob blob, Function<File, Mono<Void>> putFile) {
+            return Mono.using(
+                () -> {
+                    File file = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
+                    FileUtils.copyToFile(blob.getPayload().openStream(), file);
+                    return file;
+                },
+                putFile::apply,
+                FileUtils::deleteQuietly
+            );
         }
 
         private Mono<Void> putWithRetry(ObjectStorageBucketName bucketName, AwsS3AuthConfiguration configuration, Blob blob, File file, int tried) {


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 08/13: [Refactoring] Move LMTPProtocolHandlerChain to test and use RecordingMetric

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 4361d3cd2a3fd88a7448528e882611fb7a6f46be
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Dec 16 10:36:54 2019 +0700

    [Refactoring] Move LMTPProtocolHandlerChain to test and use RecordingMetric
---
 protocols/lmtp/pom.xml                                   |  5 +++++
 .../james/protocols/lmtp/LMTPProtocolHandlerChain.java   | 16 ++++++++--------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/protocols/lmtp/pom.xml b/protocols/lmtp/pom.xml
index 3f4881b..da1abfb 100644
--- a/protocols/lmtp/pom.xml
+++ b/protocols/lmtp/pom.xml
@@ -34,6 +34,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>${james.protocols.groupId}</groupId>
             <artifactId>protocols-api</artifactId>
         </dependency>
diff --git a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java b/protocols/lmtp/src/test/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
similarity index 86%
rename from protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
rename to protocols/lmtp/src/test/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
index 86332d2..2f0b02c 100644
--- a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
+++ b/protocols/lmtp/src/test/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
@@ -21,7 +21,7 @@ package org.apache.james.protocols.lmtp;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.protocols.api.handler.CommandDispatcher;
 import org.apache.james.protocols.api.handler.CommandHandlerResultLogger;
 import org.apache.james.protocols.api.handler.ProtocolHandler;
@@ -50,7 +50,7 @@ import org.apache.james.protocols.smtp.core.esmtp.StartTlsCmdHandler;
 public class LMTPProtocolHandlerChain extends SMTPProtocolHandlerChain {
 
     public LMTPProtocolHandlerChain() {
-        super(new NoopMetricFactory());
+        super(new RecordingMetricFactory());
     }
 
     @Override
@@ -58,21 +58,21 @@ public class LMTPProtocolHandlerChain extends SMTPProtocolHandlerChain {
         List<ProtocolHandler> defaultHandlers = new ArrayList<>();
         defaultHandlers.add(new CommandDispatcher<SMTPSession>());
         defaultHandlers.add(new ExpnCmdHandler());
-        defaultHandlers.add(new LhloCmdHandler(new NoopMetricFactory()));
+        defaultHandlers.add(new LhloCmdHandler(new RecordingMetricFactory()));
         defaultHandlers.add(new HelpCmdHandler());
-        defaultHandlers.add(new MailCmdHandler(new NoopMetricFactory()));
+        defaultHandlers.add(new MailCmdHandler(new RecordingMetricFactory()));
         defaultHandlers.add(new NoopCmdHandler());
-        defaultHandlers.add(new QuitCmdHandler(new NoopMetricFactory()));
-        defaultHandlers.add(new RcptCmdHandler(new NoopMetricFactory()));
+        defaultHandlers.add(new QuitCmdHandler(new RecordingMetricFactory()));
+        defaultHandlers.add(new RcptCmdHandler(new RecordingMetricFactory()));
         defaultHandlers.add(new RsetCmdHandler());
         defaultHandlers.add(new VrfyCmdHandler());
-        defaultHandlers.add(new DataCmdHandler(new NoopMetricFactory()));
+        defaultHandlers.add(new DataCmdHandler(new RecordingMetricFactory()));
         defaultHandlers.add(new MailSizeEsmtpExtension());
         defaultHandlers.add(new WelcomeMessageHandler());
         defaultHandlers.add(new ReceivedDataLineFilter());
         defaultHandlers.add(new DataLineMessageHookHandler());
         defaultHandlers.add(new StartTlsCmdHandler());
-        defaultHandlers.add(new UnknownCmdHandler(new NoopMetricFactory()));
+        defaultHandlers.add(new UnknownCmdHandler(new RecordingMetricFactory()));
         defaultHandlers.add(new CommandHandlerResultLogger());
 
         return defaultHandlers;


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 10/13: JAMES-2991 Bind ComputeMessageFastViewProjectionListener in JMAP products

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit c282daad07dc26f847c1600c767b6406a56e882a
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Dec 17 09:14:32 2019 +0700

    JAMES-2991 Bind ComputeMessageFastViewProjectionListener in JMAP products
---
 .../src/main/java/org/apache/james/jmap/draft/JMAPCommonModule.java | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/JMAPCommonModule.java b/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/JMAPCommonModule.java
index 067893a..34184a7 100644
--- a/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/JMAPCommonModule.java
+++ b/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/JMAPCommonModule.java
@@ -40,7 +40,9 @@ import org.apache.james.jmap.draft.model.message.view.MessageHeaderViewFactory;
 import org.apache.james.jmap.draft.model.message.view.MessageMetadataViewFactory;
 import org.apache.james.jmap.draft.send.MailSpool;
 import org.apache.james.jmap.draft.utils.HeadersAuthenticationExtractor;
+import org.apache.james.jmap.event.ComputeMessageFastViewProjectionListener;
 import org.apache.james.lifecycle.api.StartUpCheck;
+import org.apache.james.mailbox.events.MailboxListener;
 import org.apache.james.util.date.DefaultZonedDateTimeProvider;
 import org.apache.james.util.date.ZonedDateTimeProvider;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -89,6 +91,10 @@ public class JMAPCommonModule extends AbstractModule {
         bindConstant().annotatedWith(Names.named(AccessTokenRepository.TOKEN_EXPIRATION_IN_MS)).to(DEFAULT_TOKEN_EXPIRATION_IN_MS);
         bind(AccessTokenManager.class).to(AccessTokenManagerImpl.class);
 
+        Multibinder.newSetBinder(binder(), MailboxListener.GroupMailboxListener.class)
+            .addBinding()
+            .to(ComputeMessageFastViewProjectionListener.class);
+
         Multibinder.newSetBinder(binder(), StartUpCheck.class)
             .addBinding().to(JMAPConfigurationStartUpCheck.class);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 02/13: JAMES-3008 Remove unused parameter in AWS blobPutter

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 207ad0a9690080468eebc97bac10b68b9ee7b6e9
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Dec 12 15:38:25 2019 +0700

    JAMES-3008 Remove unused parameter in AWS blobPutter
---
 .../org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
index e02577a..f1e8f77 100644
--- a/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
+++ b/server/blob/blob-objectstorage/src/main/java/org/apache/james/blob/objectstorage/aws/AwsS3ObjectStorage.java
@@ -146,14 +146,14 @@ public class AwsS3ObjectStorage {
 
         @Override
         public Mono<Void> putDirectly(ObjectStorageBucketName bucketName, Blob blob) {
-            return writeFileAndAct(blob, file -> putWithRetry(bucketName, configuration, blob, file, FIRST_TRY));
+            return writeFileAndAct(blob, file -> putWithRetry(bucketName, configuration, blob, file));
         }
 
         @Override
         public Mono<BlobId> putAndComputeId(ObjectStorageBucketName bucketName, Blob initialBlob, Supplier<BlobId> blobIdSupplier) {
             Function<File, Mono<Void>> putChangedBlob = file -> {
                 initialBlob.getMetadata().setName(blobIdSupplier.get().asString());
-                return putWithRetry(bucketName, configuration, initialBlob, file, FIRST_TRY);
+                return putWithRetry(bucketName, configuration, initialBlob, file);
             };
             return writeFileAndAct(initialBlob, putChangedBlob)
                 .then(Mono.fromCallable(blobIdSupplier::get));
@@ -171,7 +171,7 @@ public class AwsS3ObjectStorage {
             );
         }
 
-        private Mono<Void> putWithRetry(ObjectStorageBucketName bucketName, AwsS3AuthConfiguration configuration, Blob blob, File file, int tried) {
+        private Mono<Void> putWithRetry(ObjectStorageBucketName bucketName, AwsS3AuthConfiguration configuration, Blob blob, File file) {
             return Mono.<Void>fromRunnable(Throwing.runnable(() -> put(bucketName, configuration, blob, file)).sneakyThrow())
                 .publishOn(Schedulers.elastic())
                 .retryWhen(Retry


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 07/13: [Refactoring] Remove unused constructors in LMTPProtocolHandlerChain

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit c65086336bb0975c2115616c037a0a9c186536b2
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Dec 16 10:33:28 2019 +0700

    [Refactoring] Remove unused constructors in LMTPProtocolHandlerChain
---
 .../apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java  | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java b/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
index 7a21cca..86332d2 100644
--- a/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
+++ b/protocols/lmtp/src/main/java/org/apache/james/protocols/lmtp/LMTPProtocolHandlerChain.java
@@ -25,7 +25,6 @@ import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.protocols.api.handler.CommandDispatcher;
 import org.apache.james.protocols.api.handler.CommandHandlerResultLogger;
 import org.apache.james.protocols.api.handler.ProtocolHandler;
-import org.apache.james.protocols.api.handler.WiringException;
 import org.apache.james.protocols.lmtp.core.DataLineMessageHookHandler;
 import org.apache.james.protocols.lmtp.core.LhloCmdHandler;
 import org.apache.james.protocols.lmtp.core.ReceivedDataLineFilter;
@@ -44,7 +43,6 @@ import org.apache.james.protocols.smtp.core.UnknownCmdHandler;
 import org.apache.james.protocols.smtp.core.VrfyCmdHandler;
 import org.apache.james.protocols.smtp.core.esmtp.MailSizeEsmtpExtension;
 import org.apache.james.protocols.smtp.core.esmtp.StartTlsCmdHandler;
-import org.apache.james.protocols.smtp.hook.Hook;
 
 /**
  * Special {@link SMTPProtocolHandlerChain} sub-class which should be used to build the chain for LMTP.
@@ -55,14 +53,6 @@ public class LMTPProtocolHandlerChain extends SMTPProtocolHandlerChain {
         super(new NoopMetricFactory());
     }
 
-    public LMTPProtocolHandlerChain(boolean addDefault) {
-        super(new NoopMetricFactory(), addDefault);
-    }
-
-    public LMTPProtocolHandlerChain(Hook... hooks) throws WiringException {
-        super(new NoopMetricFactory(), hooks);
-    }
-
     @Override
     protected List<ProtocolHandler> initDefaultHandlers() {
         List<ProtocolHandler> defaultHandlers = new ArrayList<>();


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 03/13: [Refactoring] Replacing NoopMetricFactory by RecordingMetricFactory

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 9fdbcd89ac9dd740ac8bb6a711d1bd3c6214d595
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Dec 13 16:25:43 2019 +0700

    [Refactoring] Replacing NoopMetricFactory by RecordingMetricFactory
    
    Recently, there is a MetricContract provided in
    https://github.com/linagora/james-project/pull/2993
    
    Started from the discussion in https://github.com/linagora/james-project/pull/2993#discussion_r357054044
    
    We came to a conclusion that the NoopMetric should follow the contract
    while its purpose is only to satisfy the compiler in tests but not a
    working Metric. Thus it will break almost tests in the contract because
    of fake behaviors. This issue can by addressed by several ways:
    
     - Make NoopMetric really works, but it conflicts with the RecordingMetric
     - Throw exceptions in NoopMetric methods => could breaks a lot of tests
     - Having a ReadingMetricFactory implement Metric, and leave NoopMetric
     - Replace NoopMetric by RecordingMetric if possible.
    
    I decided to take the 4th solution
---
 examples/custom-listeners/pom.xml                              |  5 +++++
 mailbox/api/pom.xml                                            |  5 +++++
 mailbox/backup/pom.xml                                         |  5 +++++
 mailbox/cassandra/pom.xml                                      |  5 +++++
 .../mailbox/cassandra/CassandraCombinationManagerTest.java     |  4 ++--
 .../mailbox/cassandra/CassandraMailboxManagerProvider.java     |  4 ++--
 .../james/mailbox/cassandra/CassandraMailboxManagerTest.java   |  4 ++--
 .../cassandra/CassandraMessageIdManagerStorageTest.java        |  4 ++--
 .../mailbox/cassandra/CassandraMessageIdManagerTestSystem.java |  4 ++--
 .../james/mailbox/cassandra/CassandraTestSystemFixture.java    |  4 ++--
 .../cassandra/mail/CassandraMailboxManagerAttachmentTest.java  |  4 ++--
 mailbox/elasticsearch/pom.xml                                  |  5 +++++
 .../mailbox/elasticsearch/ElasticSearchIntegrationTest.java    |  4 ++--
 .../james/mailbox/elasticsearch/json/IndexableMessageTest.java |  4 ++--
 .../elasticsearch/json/MessageToElasticSearchJsonTest.java     |  4 ++--
 mailbox/event/event-memory/pom.xml                             |  5 +++++
 .../java/org/apache/james/mailbox/events/InVMEventBusTest.java |  4 ++--
 .../james/mailbox/events/delivery/InVmEventDeliveryTest.java   |  4 ++--
 mailbox/event/event-rabbitmq/pom.xml                           |  5 +++++
 .../org/apache/james/mailbox/events/RabbitMQEventBusTest.java  |  4 ++--
 mailbox/jpa/pom.xml                                            |  5 +++++
 .../apache/james/mailbox/jpa/JpaMailboxManagerProvider.java    |  4 ++--
 mailbox/lucene/pom.xml                                         |  5 +++++
 mailbox/maildir/pom.xml                                        |  5 +++++
 .../james/mailbox/maildir/MaildirMailboxManagerProvider.java   |  4 ++--
 mailbox/memory/pom.xml                                         |  5 +++++
 .../mailbox/inmemory/manager/InMemoryIntegrationResources.java |  6 +++---
 .../org/apache/james/vault/DeletedMessageVaultHookTest.java    |  4 ++--
 mailbox/plugin/quota-mailing-cassandra/pom.xml                 |  5 +++++
 mailbox/plugin/quota-mailing-memory/pom.xml                    |  5 +++++
 mailbox/plugin/quota-mailing/pom.xml                           |  5 +++++
 .../mailing/listeners/QuotaThresholdListenersTestSystem.java   |  4 ++--
 mailbox/plugin/quota-search-elasticsearch/pom.xml              |  5 +++++
 mailbox/plugin/quota-search-scanning/pom.xml                   |  5 +++++
 mailbox/plugin/spamassassin/pom.xml                            |  5 +++++
 mailbox/scanning-search/pom.xml                                |  5 +++++
 .../mailbox/store/AbstractMessageIdManagerSideEffectTest.java  |  4 ++--
 .../apache/james/mailbox/store/StoreMailboxManagerTest.java    |  4 ++--
 mailbox/tika/pom.xml                                           |  5 +++++
 .../apache/james/mailbox/tika/CachingTextExtractorTest.java    |  4 ++--
 .../org/apache/james/mailbox/tika/TikaTextExtractorTest.java   | 10 +++++-----
 mailbox/tools/copier/pom.xml                                   |  5 +++++
 mailbox/tools/indexer/pom.xml                                  |  5 +++++
 mpt/impl/imap-mailbox/cassandra/pom.xml                        |  5 +++++
 .../mpt/imapmailbox/cassandra/host/CassandraHostSystem.java    |  4 ++--
 mpt/impl/imap-mailbox/elasticsearch/pom.xml                    |  5 +++++
 mpt/impl/imap-mailbox/inmemory/pom.xml                         |  5 +++++
 mpt/impl/imap-mailbox/jpa/pom.xml                              |  5 +++++
 .../apache/james/mpt/imapmailbox/jpa/host/JPAHostSystem.java   |  4 ++--
 mpt/impl/imap-mailbox/lucenesearch/pom.xml                     |  5 +++++
 mpt/impl/imap-mailbox/maildir/pom.xml                          |  5 +++++
 .../james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java  |  4 ++--
 mpt/impl/imap-mailbox/rabbitmq/pom.xml                         |  5 +++++
 .../imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java  |  4 ++--
 protocols/imap/pom.xml                                         |  5 +++++
 .../org/apache/james/imap/processor/CopyProcessorTest.java     |  4 ++--
 .../apache/james/imap/processor/DeleteACLProcessorTest.java    |  4 ++--
 .../org/apache/james/imap/processor/GetACLProcessorTest.java   |  4 ++--
 .../james/imap/processor/GetAnnotationProcessorTest.java       |  4 ++--
 .../org/apache/james/imap/processor/GetQuotaProcessorTest.java |  4 ++--
 .../apache/james/imap/processor/GetQuotaRootProcessorTest.java |  4 ++--
 .../org/apache/james/imap/processor/LSubProcessorTest.java     |  4 ++--
 .../apache/james/imap/processor/ListRightsProcessorTest.java   |  4 ++--
 .../org/apache/james/imap/processor/MoveProcessorTest.java     |  6 +++---
 .../apache/james/imap/processor/NamespaceProcessorTest.java    |  4 ++--
 .../org/apache/james/imap/processor/SearchProcessorTest.java   |  4 ++--
 .../org/apache/james/imap/processor/SetACLProcessorTest.java   |  4 ++--
 .../james/imap/processor/SetAnnotationProcessorTest.java       |  4 ++--
 .../org/apache/james/imap/processor/SetQuotaProcessorTest.java |  4 ++--
 .../james/imap/processor/base/MailboxEventAnalyserTest.java    |  4 ++--
 protocols/smtp/pom.xml                                         |  5 +++++
 .../apache/james/protocols/smtp/AbstractSMTPServerTest.java    |  4 ++--
 .../protocols/smtp/netty/NettyStartTlsSMTPServerTest.java      |  4 ++--
 server/container/guice/mailbox/pom.xml                         |  5 +++++
 .../james/modules/mailbox/MailboxListenersLoaderImplTest.java  |  5 ++---
 server/container/mailbox-jmx/pom.xml                           |  5 +++++
 server/dns-service/dnsservice-dnsjava/pom.xml                  |  5 +++++
 .../apache/james/dnsservice/dnsjava/DNSJavaServiceTest.java    |  4 ++--
 server/mailet/mailetcontainer-camel/pom.xml                    |  5 +++++
 .../impl/camel/CamelCompositeProcessorTest.java                |  4 ++--
 .../mailetcontainer/impl/camel/CamelMailetProcessorTest.java   |  4 ++--
 server/mailet/mailets/pom.xml                                  | 10 +++++-----
 .../org/apache/james/transport/mailets/SpamAssassinTest.java   |  4 ++--
 .../james/transport/mailets/delivery/LocalDeliveryTest.java    |  4 ++--
 .../transport/mailets/delivery/ToRecipientFolderTest.java      |  4 ++--
 .../transport/mailets/remote/delivery/RemoteDeliveryTest.java  |  4 ++--
 server/protocols/jmap-draft/pom.xml                            |  5 +++++
 .../org/apache/james/jmap/draft/AuthenticationFilterTest.java  | 10 +++++-----
 .../jmap/draft/DefaultMailboxesProvisioningFilterTest.java     |  5 ++---
 .../draft/DefaultMailboxesProvisioningFilterThreadTest.java    |  5 ++---
 .../java/org/apache/james/jmap/draft/DownloadServletTest.java  |  5 ++---
 .../test/java/org/apache/james/jmap/draft/JMAPServletTest.java |  7 +++----
 .../apache/james/jmap/draft/UserProvisioningFilterTest.java    |  8 ++++----
 .../james/jmap/draft/UserProvisioningFilterThreadTest.java     |  4 ++--
 .../apache/james/jmap/draft/methods/GetMessagesMethodTest.java |  6 +++---
 .../org/apache/james/jmap/draft/methods/MessageSenderTest.java |  4 ++--
 .../jmap/draft/methods/SetMailboxesCreationProcessorTest.java  |  4 ++--
 .../jmap/draft/methods/SetMailboxesUpdateProcessorTest.java    |  4 ++--
 .../jmap/draft/methods/SetMessagesCreationProcessorTest.java   | 10 +++++-----
 .../jmap/draft/methods/SetMessagesUpdateProcessorTest.java     |  6 +++---
 .../draft/model/message/view/MessageFastViewFactoryTest.java   |  6 +++---
 .../draft/model/message/view/MessageFullViewFactoryTest.java   |  4 ++--
 .../event/ComputeMessageFastViewProjectionListenerTest.java    |  6 +++---
 server/protocols/protocols-pop3/pom.xml                        |  5 +++++
 server/protocols/protocols-smtp/pom.xml                        |  5 +++++
 .../test/java/org/apache/james/smtpserver/SMTPServerTest.java  |  4 ++--
 .../org/apache/james/smtpserver/SpamAssassinHandlerTest.java   |  8 ++++----
 server/protocols/webadmin/webadmin-cassandra-data/pom.xml      |  5 +++++
 server/protocols/webadmin/webadmin-cassandra/pom.xml           |  5 +++++
 server/protocols/webadmin/webadmin-core/pom.xml                |  5 +++++
 .../src/test/java/org/apache/james/webadmin/WebAdminUtils.java |  5 ++---
 server/protocols/webadmin/webadmin-data/pom.xml                | 10 +++++-----
 .../webadmin/webadmin-mailbox-deleted-message-vault/pom.xml    |  5 +++++
 .../webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java  |  4 ++--
 server/protocols/webadmin/webadmin-mailbox/pom.xml             |  5 +++++
 .../james/webadmin/routes/EventDeadLettersRoutesTest.java      |  4 ++--
 server/protocols/webadmin/webadmin-mailqueue/pom.xml           |  5 +++++
 server/protocols/webadmin/webadmin-mailrepository/pom.xml      |  5 +++++
 .../james/queue/activemq/ActiveMQMailQueueFactoryTest.java     |  6 +++---
 .../org/apache/james/queue/jms/JMSMailQueueFactoryTest.java    |  4 ++--
 .../rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java     |  4 ++--
 .../james/queue/rabbitmq/RabbitMqMailQueueFactoryTest.java     |  4 ++--
 third-party/spamassassin/pom.xml                               |  5 +++++
 .../org/apache/james/spamassassin/SpamAssassinInvokerTest.java |  4 ++--
 124 files changed, 410 insertions(+), 191 deletions(-)

diff --git a/examples/custom-listeners/pom.xml b/examples/custom-listeners/pom.xml
index fe13eec..c09ae2f 100644
--- a/examples/custom-listeners/pom.xml
+++ b/examples/custom-listeners/pom.xml
@@ -33,6 +33,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/api/pom.xml b/mailbox/api/pom.xml
index 616dc68..f117ac6 100644
--- a/mailbox/api/pom.xml
+++ b/mailbox/api/pom.xml
@@ -55,6 +55,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/backup/pom.xml b/mailbox/backup/pom.xml
index 634141b..172fa3b 100644
--- a/mailbox/backup/pom.xml
+++ b/mailbox/backup/pom.xml
@@ -60,6 +60,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/cassandra/pom.xml b/mailbox/cassandra/pom.xml
index 5edd48d..f245713 100644
--- a/mailbox/cassandra/pom.xml
+++ b/mailbox/cassandra/pom.xml
@@ -95,6 +95,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
index c63377c..63871af 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraCombinationManagerTest.java
@@ -26,7 +26,7 @@ import org.apache.james.mailbox.events.delivery.InVmEventDelivery;
 import org.apache.james.mailbox.store.AbstractCombinationManagerTest;
 import org.apache.james.mailbox.store.CombinationManagerTestSystem;
 import org.apache.james.mailbox.store.quota.NoQuotaManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraCombinationManagerTest extends AbstractCombinationManagerTest {
@@ -35,7 +35,7 @@ class CassandraCombinationManagerTest extends AbstractCombinationManagerTest {
     
     @Override
     public CombinationManagerTestSystem createTestingData() {
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         return CassandraCombinationManagerTestSystem.createTestingData(cassandraCluster.getCassandraCluster(), new NoQuotaManager(), eventBus);
     }
     
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
index f28d275..11d9588 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerProvider.java
@@ -50,7 +50,7 @@ import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.quota.StoreQuotaManager;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 import com.datastax.driver.core.Session;
 
@@ -70,7 +70,7 @@ public class CassandraMailboxManagerProvider {
         MailboxACLResolver aclResolver = new UnionMailboxACLResolver();
         GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
         MessageParser messageParser = new MessageParser();
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mapperFactory, aclResolver, groupMembershipResolver, eventBus);
 
         Authenticator noAuthenticator = null;
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
index eb0394c..130cd7f 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMailboxManagerTest.java
@@ -23,7 +23,7 @@ import org.apache.james.mailbox.MailboxManagerTest;
 import org.apache.james.mailbox.cassandra.mail.MailboxAggregateModule;
 import org.apache.james.mailbox.events.EventBus;
 import org.apache.james.mailbox.store.PreDeletionHooks;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMailboxManager> {
@@ -35,7 +35,7 @@ public class CassandraMailboxManagerTest extends MailboxManagerTest<CassandraMai
         return CassandraMailboxManagerProvider.provideMailboxManager(
             cassandra.getCassandraCluster().getConf(),
             cassandra.getCassandraCluster().getTypesProvider(),
-            new PreDeletionHooks(preDeletionHooks(), new NoopMetricFactory()));
+            new PreDeletionHooks(preDeletionHooks(), new RecordingMetricFactory()));
     }
 
     @Override
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
index 3cb6776..ce54298 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerStorageTest.java
@@ -27,7 +27,7 @@ import org.apache.james.mailbox.extension.PreDeletionHook;
 import org.apache.james.mailbox.store.AbstractMessageIdManagerStorageTest;
 import org.apache.james.mailbox.store.MessageIdManagerTestSystem;
 import org.apache.james.mailbox.store.quota.NoQuotaManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
 class CassandraMessageIdManagerStorageTest extends AbstractMessageIdManagerStorageTest {
@@ -36,7 +36,7 @@ class CassandraMessageIdManagerStorageTest extends AbstractMessageIdManagerStora
     
     @Override
     protected MessageIdManagerTestSystem createTestingData() {
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         return CassandraMessageIdManagerTestSystem.createTestingData(cassandraCluster.getCassandraCluster(), new NoQuotaManager(), eventBus, PreDeletionHook.NO_PRE_DELETION_HOOK);
     }
 }
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java
index cbd640d..0ea0093 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraMessageIdManagerTestSystem.java
@@ -31,7 +31,7 @@ import org.apache.james.mailbox.store.MessageIdManagerTestSystem;
 import org.apache.james.mailbox.store.PreDeletionHooks;
 import org.apache.james.mailbox.store.quota.ListeningCurrentQuotaUpdater;
 import org.apache.james.mailbox.store.quota.StoreCurrentQuotaManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 class CassandraMessageIdManagerTestSystem {
 
@@ -39,7 +39,7 @@ class CassandraMessageIdManagerTestSystem {
                                                         Set<PreDeletionHook> preDeletionHooks) {
         CassandraMailboxSessionMapperFactory mapperFactory = CassandraTestSystemFixture.createMapperFactory(cassandra);
 
-        return new MessageIdManagerTestSystem(CassandraTestSystemFixture.createMessageIdManager(mapperFactory, quotaManager, eventBus, new PreDeletionHooks(preDeletionHooks, new NoopMetricFactory())),
+        return new MessageIdManagerTestSystem(CassandraTestSystemFixture.createMessageIdManager(mapperFactory, quotaManager, eventBus, new PreDeletionHooks(preDeletionHooks, new RecordingMetricFactory())),
             new CassandraMessageId.Factory(),
             mapperFactory,
             CassandraTestSystemFixture.createMailboxManager(mapperFactory)) {
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
index b42d708..c3aed62 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/CassandraTestSystemFixture.java
@@ -52,7 +52,7 @@ import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 class CassandraTestSystemFixture {
 
@@ -66,7 +66,7 @@ class CassandraTestSystemFixture {
     }
 
     static CassandraMailboxManager createMailboxManager(CassandraMailboxSessionMapperFactory mapperFactory) {
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mapperFactory, new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver(), eventBus);
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mapperFactory, storeRightManager);
 
diff --git a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
index efd2323..1775767 100644
--- a/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
+++ b/mailbox/cassandra/src/test/java/org/apache/james/mailbox/cassandra/mail/CassandraMailboxManagerAttachmentTest.java
@@ -48,7 +48,7 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
@@ -76,7 +76,7 @@ class CassandraMailboxManagerAttachmentTest extends AbstractMailboxManagerAttach
             messageIdFactory);
         Authenticator noAuthenticator = null;
         Authorizator noAuthorizator = null;
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mailboxSessionMapperFactory, new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver(), eventBus);
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mailboxSessionMapperFactory, storeRightManager);
 
diff --git a/mailbox/elasticsearch/pom.xml b/mailbox/elasticsearch/pom.xml
index c69e00e..41159ef 100644
--- a/mailbox/elasticsearch/pom.xml
+++ b/mailbox/elasticsearch/pom.xml
@@ -102,6 +102,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java
index 468f21d..04bc2d6 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java
@@ -46,7 +46,7 @@ import org.apache.james.mailbox.tika.TikaConfiguration;
 import org.apache.james.mailbox.tika.TikaExtension;
 import org.apache.james.mailbox.tika.TikaHttpClientImpl;
 import org.apache.james.mailbox.tika.TikaTextExtractor;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mime4j.dom.Message;
 import org.elasticsearch.client.RestHighLevelClient;
 import org.junit.jupiter.api.AfterEach;
@@ -81,7 +81,7 @@ class ElasticSearchIntegrationTest extends AbstractMessageSearchIndexTest {
 
     @Override
     protected void initializeMailboxManager() throws Exception {
-        textExtractor = new TikaTextExtractor(new NoopMetricFactory(),
+        textExtractor = new TikaTextExtractor(new RecordingMetricFactory(),
             new TikaHttpClientImpl(TikaConfiguration.builder()
                 .host(tika.getIp())
                 .port(tika.getPort())
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/IndexableMessageTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/IndexableMessageTest.java
index fecf8c6..2526f14 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/IndexableMessageTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/IndexableMessageTest.java
@@ -47,7 +47,7 @@ import org.apache.james.mailbox.tika.TikaConfiguration;
 import org.apache.james.mailbox.tika.TikaExtension;
 import org.apache.james.mailbox.tika.TikaHttpClientImpl;
 import org.apache.james.mailbox.tika.TikaTextExtractor;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.assertj.core.api.iterable.Extractor;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -66,7 +66,7 @@ class IndexableMessageTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        textExtractor = new TikaTextExtractor(new NoopMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
+        textExtractor = new TikaTextExtractor(new RecordingMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
                 .host(tika.getIp())
                 .port(tika.getPort())
                 .timeoutInMillis(tika.getTimeoutInMillis())
diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
index ed214bf..8586c1a 100644
--- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
+++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/MessageToElasticSearchJsonTest.java
@@ -49,7 +49,7 @@ import org.apache.james.mailbox.tika.TikaConfiguration;
 import org.apache.james.mailbox.tika.TikaExtension;
 import org.apache.james.mailbox.tika.TikaHttpClientImpl;
 import org.apache.james.mailbox.tika.TikaTextExtractor;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.ClassLoaderUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -75,7 +75,7 @@ class MessageToElasticSearchJsonTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        textExtractor = new TikaTextExtractor(new NoopMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
+        textExtractor = new TikaTextExtractor(new RecordingMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
                 .host(tika.getIp())
                 .port(tika.getPort())
                 .timeoutInMillis(tika.getTimeoutInMillis())
diff --git a/mailbox/event/event-memory/pom.xml b/mailbox/event/event-memory/pom.xml
index 62d3c4e..72d32d0 100644
--- a/mailbox/event/event-memory/pom.xml
+++ b/mailbox/event/event-memory/pom.xml
@@ -48,6 +48,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/InVMEventBusTest.java b/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/InVMEventBusTest.java
index 862fc82..18e0a19 100644
--- a/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/InVMEventBusTest.java
+++ b/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/InVMEventBusTest.java
@@ -20,7 +20,7 @@
 package org.apache.james.mailbox.events;
 
 import org.apache.james.mailbox.events.delivery.InVmEventDelivery;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.BeforeEach;
 
 public class InVMEventBusTest implements KeyContract.SingleEventBusKeyContract, GroupContract.SingleEventBusGroupContract,
@@ -33,7 +33,7 @@ public class InVMEventBusTest implements KeyContract.SingleEventBusKeyContract,
     void setUp() {
         deadLetters = new MemoryEventDeadLetters();
         eventBus = new InVMEventBus(
-            new InVmEventDelivery(new NoopMetricFactory()), RetryBackoffConfiguration.DEFAULT, deadLetters);
+            new InVmEventDelivery(new RecordingMetricFactory()), RetryBackoffConfiguration.DEFAULT, deadLetters);
     }
 
     @Override
diff --git a/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/delivery/InVmEventDeliveryTest.java b/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/delivery/InVmEventDeliveryTest.java
index dfea972..6212178 100644
--- a/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/delivery/InVmEventDeliveryTest.java
+++ b/mailbox/event/event-memory/src/test/java/org/apache/james/mailbox/events/delivery/InVmEventDeliveryTest.java
@@ -36,7 +36,7 @@ import org.apache.james.mailbox.events.RetryBackoffConfiguration;
 import org.apache.james.mailbox.events.delivery.EventDelivery.DeliveryOption;
 import org.apache.james.mailbox.events.delivery.EventDelivery.PermanentFailureHandler;
 import org.apache.james.mailbox.events.delivery.EventDelivery.Retryer.BackoffRetryer;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
@@ -49,7 +49,7 @@ class InVmEventDeliveryTest {
     @BeforeEach
     void setUp() {
         listener = newListener();
-        inVmEventDelivery = new InVmEventDelivery(new NoopMetricFactory());
+        inVmEventDelivery = new InVmEventDelivery(new RecordingMetricFactory());
     }
 
     MailboxListenerCountingSuccessfulExecution newListener() {
diff --git a/mailbox/event/event-rabbitmq/pom.xml b/mailbox/event/event-rabbitmq/pom.xml
index 8a17955..d6cbf3d 100644
--- a/mailbox/event/event-rabbitmq/pom.xml
+++ b/mailbox/event/event-rabbitmq/pom.xml
@@ -81,6 +81,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
index ed97aec..3656e35 100644
--- a/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
+++ b/mailbox/event/event-rabbitmq/src/test/java/org/apache/james/mailbox/events/RabbitMQEventBusTest.java
@@ -64,7 +64,7 @@ import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.mailbox.util.EventCollector;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.assertj.core.data.Percentage;
 import org.junit.jupiter.api.AfterEach;
@@ -131,7 +131,7 @@ class RabbitMQEventBusTest implements GroupContract.SingleEventBusGroupContract,
     }
 
     private RabbitMQEventBus newEventBus(ReactorRabbitMQChannelPool rabbitMQChannelPool) {
-        return new RabbitMQEventBus(rabbitMQChannelPool, eventSerializer, RetryBackoffConfiguration.DEFAULT, routingKeyConverter, memoryEventDeadLetters, new NoopMetricFactory());
+        return new RabbitMQEventBus(rabbitMQChannelPool, eventSerializer, RetryBackoffConfiguration.DEFAULT, routingKeyConverter, memoryEventDeadLetters, new RecordingMetricFactory());
     }
 
     @Override
diff --git a/mailbox/jpa/pom.xml b/mailbox/jpa/pom.xml
index 7f7f759..1db474b 100644
--- a/mailbox/jpa/pom.xml
+++ b/mailbox/jpa/pom.xml
@@ -73,6 +73,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JpaMailboxManagerProvider.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JpaMailboxManagerProvider.java
index 7dfcf74..5c11441 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JpaMailboxManagerProvider.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/JpaMailboxManagerProvider.java
@@ -42,7 +42,7 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 public class JpaMailboxManagerProvider {
 
@@ -60,7 +60,7 @@ public class JpaMailboxManagerProvider {
         Authenticator noAuthenticator = null;
         Authorizator noAuthorizator = null;
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mf, aclResolver, groupMembershipResolver, eventBus);
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mf, storeRightManager,
             LIMIT_ANNOTATIONS, LIMIT_ANNOTATION_SIZE);
diff --git a/mailbox/lucene/pom.xml b/mailbox/lucene/pom.xml
index b4e2d53..bf76738 100644
--- a/mailbox/lucene/pom.xml
+++ b/mailbox/lucene/pom.xml
@@ -78,6 +78,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/maildir/pom.xml b/mailbox/maildir/pom.xml
index 3ea306b..f04e477 100644
--- a/mailbox/maildir/pom.xml
+++ b/mailbox/maildir/pom.xml
@@ -66,6 +66,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java
index b7abdd0..2b67512 100644
--- a/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java
+++ b/mailbox/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerProvider.java
@@ -42,7 +42,7 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 public class MaildirMailboxManagerProvider {
 
@@ -54,7 +54,7 @@ public class MaildirMailboxManagerProvider {
         GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
         MessageParser messageParser = new MessageParser();
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mf, aclResolver, groupMembershipResolver, eventBus);
 
         Authenticator noAuthenticator = null;
diff --git a/mailbox/memory/pom.xml b/mailbox/memory/pom.xml
index 1cc8527..d5077a0 100644
--- a/mailbox/memory/pom.xml
+++ b/mailbox/memory/pom.xml
@@ -58,6 +58,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java
index e229849..f80a239 100644
--- a/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java
+++ b/mailbox/memory/src/test/java/org/apache/james/mailbox/inmemory/manager/InMemoryIntegrationResources.java
@@ -67,7 +67,7 @@ import org.apache.james.mailbox.store.quota.StoreQuotaManager;
 import org.apache.james.mailbox.store.search.ListeningMessageSearchIndex;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 
 import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Preconditions;
@@ -101,7 +101,7 @@ public class InMemoryIntegrationResources implements IntegrationResources<StoreM
             RequireAnnotationLimits eventBus(EventBus eventBus);
 
             default RequireAnnotationLimits inVmEventBus() {
-                return eventBus(new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory())));
+                return eventBus(new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory())));
             }
         }
 
@@ -336,7 +336,7 @@ public class InMemoryIntegrationResources implements IntegrationResources<StoreM
                 .stream()
                 .map(biFunction -> biFunction.apply(preInstanciationStage))
                 .collect(Guavate.toImmutableSet());
-            return new PreDeletionHooks(preDeletionHooksSet, new NoopMetricFactory());
+            return new PreDeletionHooks(preDeletionHooksSet, new RecordingMetricFactory());
         }
     }
 
diff --git a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
index f3f9b15..852a3cb 100644
--- a/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
+++ b/mailbox/plugin/deleted-messages-vault/src/test/java/org/apache/james/vault/DeletedMessageVaultHookTest.java
@@ -48,7 +48,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.SearchQuery;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.vault.blob.BlobStoreDeletedMessageVault;
 import org.apache.james.vault.blob.BucketNameGenerator;
@@ -107,7 +107,7 @@ class DeletedMessageVaultHookTest {
     @BeforeEach
     void setUp() throws Exception {
         clock = Clock.fixed(DELETION_DATE.toInstant(), ZoneOffset.UTC);
-        messageVault = new BlobStoreDeletedMessageVault(new NoopMetricFactory(), new MemoryDeletedMessageMetadataVault(),
+        messageVault = new BlobStoreDeletedMessageVault(new RecordingMetricFactory(), new MemoryDeletedMessageMetadataVault(),
             new MemoryBlobStore(new HashBlobId.Factory()), new BucketNameGenerator(clock), clock,
             RetentionConfiguration.DEFAULT);
 
diff --git a/mailbox/plugin/quota-mailing-cassandra/pom.xml b/mailbox/plugin/quota-mailing-cassandra/pom.xml
index 86f67d9..656f066 100644
--- a/mailbox/plugin/quota-mailing-cassandra/pom.xml
+++ b/mailbox/plugin/quota-mailing-cassandra/pom.xml
@@ -101,6 +101,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/plugin/quota-mailing-memory/pom.xml b/mailbox/plugin/quota-mailing-memory/pom.xml
index 24ef821..6c73c25 100644
--- a/mailbox/plugin/quota-mailing-memory/pom.xml
+++ b/mailbox/plugin/quota-mailing-memory/pom.xml
@@ -97,6 +97,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/plugin/quota-mailing/pom.xml b/mailbox/plugin/quota-mailing/pom.xml
index 432fc55..800b5a7 100644
--- a/mailbox/plugin/quota-mailing/pom.xml
+++ b/mailbox/plugin/quota-mailing/pom.xml
@@ -93,6 +93,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
index 2ba6e93..129bf22 100644
--- a/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
+++ b/mailbox/plugin/quota-mailing/src/test/java/org/apache/james/mailbox/quota/mailing/listeners/QuotaThresholdListenersTestSystem.java
@@ -29,7 +29,7 @@ import org.apache.james.mailbox.events.RegistrationKey;
 import org.apache.james.mailbox.events.delivery.InVmEventDelivery;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.quota.mailing.QuotaMailingListenerConfiguration;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.server.core.JamesServerResourceLoader;
 import org.apache.james.server.core.filesystem.FileSystemImpl;
 import org.apache.james.user.memory.MemoryUsersRepository;
@@ -44,7 +44,7 @@ class QuotaThresholdListenersTestSystem {
     private final EventBus eventBus;
 
     QuotaThresholdListenersTestSystem(MailetContext mailetContext, EventStore eventStore, QuotaMailingListenerConfiguration configuration) throws MailboxException {
-        eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
 
         FileSystem fileSystem = new FileSystemImpl(new JamesServerResourceLoader("."));
 
diff --git a/mailbox/plugin/quota-search-elasticsearch/pom.xml b/mailbox/plugin/quota-search-elasticsearch/pom.xml
index 62bfe31..db5c31c 100644
--- a/mailbox/plugin/quota-search-elasticsearch/pom.xml
+++ b/mailbox/plugin/quota-search-elasticsearch/pom.xml
@@ -95,6 +95,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/plugin/quota-search-scanning/pom.xml b/mailbox/plugin/quota-search-scanning/pom.xml
index 7656359..276381e 100644
--- a/mailbox/plugin/quota-search-scanning/pom.xml
+++ b/mailbox/plugin/quota-search-scanning/pom.xml
@@ -76,6 +76,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/plugin/spamassassin/pom.xml b/mailbox/plugin/spamassassin/pom.xml
index 475d32c..9e0ca23 100644
--- a/mailbox/plugin/spamassassin/pom.xml
+++ b/mailbox/plugin/spamassassin/pom.xml
@@ -69,6 +69,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/scanning-search/pom.xml b/mailbox/scanning-search/pom.xml
index 9d1710e..fb936ad 100644
--- a/mailbox/scanning-search/pom.xml
+++ b/mailbox/scanning-search/pom.xml
@@ -65,6 +65,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
index b579036..a06bf95 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerSideEffectTest.java
@@ -65,7 +65,7 @@ import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.util.EventCollector;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.assertj.core.api.AbstractListAssert;
 import org.assertj.core.api.ObjectAssert;
 import org.assertj.core.api.SoftAssertions;
@@ -105,7 +105,7 @@ public abstract class AbstractMessageIdManagerSideEffectTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         eventCollector = new EventCollector();
         quotaManager = mock(QuotaManager.class);
 
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
index 34efd21..334ebf5 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/StoreMailboxManagerTest.java
@@ -54,7 +54,7 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -84,7 +84,7 @@ class StoreMailboxManagerTest {
         authenticator.addUser(CURRENT_USER, CURRENT_USER_PASSWORD);
         authenticator.addUser(ADMIN, ADMIN_PASSWORD);
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
 
         StoreRightManager storeRightManager = new StoreRightManager(mockedMapperFactory, new UnionMailboxACLResolver(),
                                                                     new SimpleGroupMembershipResolver(), eventBus);
diff --git a/mailbox/tika/pom.xml b/mailbox/tika/pom.xml
index 085eea1..104c577 100644
--- a/mailbox/tika/pom.xml
+++ b/mailbox/tika/pom.xml
@@ -51,6 +51,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/CachingTextExtractorTest.java b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/CachingTextExtractorTest.java
index e7ee6d6..791a7ed 100644
--- a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/CachingTextExtractorTest.java
+++ b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/CachingTextExtractorTest.java
@@ -43,7 +43,7 @@ import java.util.stream.IntStream;
 import org.apache.james.mailbox.extractor.ParsedContent;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.RepeatedTest;
@@ -73,7 +73,7 @@ public class CachingTextExtractorTest {
         textExtractor = new CachingTextExtractor(wrappedTextExtractor,
             TikaConfiguration.DEFAULT_CACHE_EVICTION_PERIOD,
             CACHE_LIMIT_10_MiB,
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             new NoopGaugeRegistry());
 
         when(wrappedTextExtractor.extractContent(any(), any()))
diff --git a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaTextExtractorTest.java b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaTextExtractorTest.java
index 2b0d126..4ecde3d 100644
--- a/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaTextExtractorTest.java
+++ b/mailbox/tika/src/test/java/org/apache/james/mailbox/tika/TikaTextExtractorTest.java
@@ -32,7 +32,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.james.mailbox.extractor.ParsedContent;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.tika.TikaTextExtractor.ContentAndMetadataDeserializer;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
@@ -50,7 +50,7 @@ class TikaTextExtractorTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        textExtractor = new TikaTextExtractor(new NoopMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
+        textExtractor = new TikaTextExtractor(new RecordingMetricFactory(), new TikaHttpClientImpl(TikaConfiguration.builder()
                 .host(tika.getIp())
                 .port(tika.getPort())
                 .timeoutInMillis(tika.getTimeoutInMillis())
@@ -159,7 +159,7 @@ class TikaTextExtractorTest {
     @Test
     void deserializerShouldNotThrowWhenMoreThanOneNode() throws Exception {
         TikaTextExtractor textExtractor = new TikaTextExtractor(
-            new NoopMetricFactory(), 
+            new RecordingMetricFactory(),
             (inputStream, contentType) -> Optional.of(new ByteArrayInputStream(("[{\"X-TIKA:content\": \"This is an awesome LibreOffice document !\"}, " +
                                                             "{\"Chroma BlackIsZero\": \"true\"}]")
                                                         .getBytes(StandardCharsets.UTF_8))));
@@ -172,7 +172,7 @@ class TikaTextExtractorTest {
     void deserializerShouldTakeFirstNodeWhenSeveral() throws Exception {
         String expectedExtractedContent = "content A";
         TikaTextExtractor textExtractor = new TikaTextExtractor(
-            new NoopMetricFactory(), 
+            new RecordingMetricFactory(),
             (inputStream, contentType) -> Optional.of(new ByteArrayInputStream(("[{\"X-TIKA:content\": \"" + expectedExtractedContent + "\"}, " +
                                                             "{\"X-TIKA:content\": \"content B\"}]")
                                                         .getBytes(StandardCharsets.UTF_8))));
@@ -186,7 +186,7 @@ class TikaTextExtractorTest {
     @Test
     void deserializerShouldThrowWhenNodeIsNotAnObject() {
         TikaTextExtractor textExtractor = new TikaTextExtractor(
-            new NoopMetricFactory(), 
+            new RecordingMetricFactory(),
             (inputStream, contentType) -> Optional.of(new ByteArrayInputStream("[\"value1\"]"
                                                         .getBytes(StandardCharsets.UTF_8))));
 
diff --git a/mailbox/tools/copier/pom.xml b/mailbox/tools/copier/pom.xml
index 4f453f1..5c63b97 100644
--- a/mailbox/tools/copier/pom.xml
+++ b/mailbox/tools/copier/pom.xml
@@ -58,6 +58,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/tools/indexer/pom.xml b/mailbox/tools/indexer/pom.xml
index 1551ef3..a0de783 100644
--- a/mailbox/tools/indexer/pom.xml
+++ b/mailbox/tools/indexer/pom.xml
@@ -90,6 +90,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/cassandra/pom.xml b/mpt/impl/imap-mailbox/cassandra/pom.xml
index c88c883..f180712 100644
--- a/mpt/impl/imap-mailbox/cassandra/pom.xml
+++ b/mpt/impl/imap-mailbox/cassandra/pom.xml
@@ -66,6 +66,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
index ff27ab1..ba3d4a0 100644
--- a/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
+++ b/mpt/impl/imap-mailbox/cassandra/src/test/java/org/apache/james/mpt/imapmailbox/cassandra/host/CassandraHostSystem.java
@@ -56,8 +56,8 @@ import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.quota.StoreQuotaManager;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mpt.api.ImapFeatures;
 import org.apache.james.mpt.api.ImapFeatures.Feature;
 import org.apache.james.mpt.host.JamesImapHostSystem;
@@ -93,7 +93,7 @@ public class CassandraHostSystem extends JamesImapHostSystem {
             messageIdFactory);
 
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mapperFactory, new UnionMailboxACLResolver(), new SimpleGroupMembershipResolver(), eventBus);
 
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mapperFactory, storeRightManager);
diff --git a/mpt/impl/imap-mailbox/elasticsearch/pom.xml b/mpt/impl/imap-mailbox/elasticsearch/pom.xml
index bf85051..bcc3fe1 100644
--- a/mpt/impl/imap-mailbox/elasticsearch/pom.xml
+++ b/mpt/impl/imap-mailbox/elasticsearch/pom.xml
@@ -83,6 +83,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/inmemory/pom.xml b/mpt/impl/imap-mailbox/inmemory/pom.xml
index 28cc73f..8a71713 100644
--- a/mpt/impl/imap-mailbox/inmemory/pom.xml
+++ b/mpt/impl/imap-mailbox/inmemory/pom.xml
@@ -54,6 +54,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/jpa/pom.xml b/mpt/impl/imap-mailbox/jpa/pom.xml
index c568323..feff9f3 100644
--- a/mpt/impl/imap-mailbox/jpa/pom.xml
+++ b/mpt/impl/imap-mailbox/jpa/pom.xml
@@ -64,6 +64,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/jpa/src/test/java/org/apache/james/mpt/imapmailbox/jpa/host/JPAHostSystem.java b/mpt/impl/imap-mailbox/jpa/src/test/java/org/apache/james/mpt/imapmailbox/jpa/host/JPAHostSystem.java
index c48356d..d4be1ce 100644
--- a/mpt/impl/imap-mailbox/jpa/src/test/java/org/apache/james/mpt/imapmailbox/jpa/host/JPAHostSystem.java
+++ b/mpt/impl/imap-mailbox/jpa/src/test/java/org/apache/james/mpt/imapmailbox/jpa/host/JPAHostSystem.java
@@ -58,8 +58,8 @@ import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.quota.StoreQuotaManager;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mpt.api.ImapFeatures;
 import org.apache.james.mpt.api.ImapFeatures.Feature;
 import org.apache.james.mpt.host.JamesImapHostSystem;
@@ -101,7 +101,7 @@ public class JPAHostSystem extends JamesImapHostSystem {
         MessageParser messageParser = new MessageParser();
 
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mapperFactory, aclResolver, groupMembershipResolver, eventBus);
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mapperFactory, storeRightManager);
         SessionProviderImpl sessionProvider = new SessionProviderImpl(authenticator, authorizator);
diff --git a/mpt/impl/imap-mailbox/lucenesearch/pom.xml b/mpt/impl/imap-mailbox/lucenesearch/pom.xml
index 69cfe03..e95d969 100644
--- a/mpt/impl/imap-mailbox/lucenesearch/pom.xml
+++ b/mpt/impl/imap-mailbox/lucenesearch/pom.xml
@@ -72,6 +72,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/maildir/pom.xml b/mpt/impl/imap-mailbox/maildir/pom.xml
index fa5fcaa..23051f1 100644
--- a/mpt/impl/imap-mailbox/maildir/pom.xml
+++ b/mpt/impl/imap-mailbox/maildir/pom.xml
@@ -47,6 +47,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java b/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java
index 65b8f07..86472c1 100644
--- a/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java
+++ b/mpt/impl/imap-mailbox/maildir/src/test/java/org/apache/james/mpt/imapmailbox/maildir/host/MaildirHostSystem.java
@@ -51,8 +51,8 @@ import org.apache.james.mailbox.store.mail.model.impl.MessageParser;
 import org.apache.james.mailbox.store.quota.QuotaComponents;
 import org.apache.james.mailbox.store.search.MessageSearchIndex;
 import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mpt.api.ImapFeatures;
 import org.apache.james.mpt.api.ImapFeatures.Feature;
 import org.apache.james.mpt.host.JamesImapHostSystem;
@@ -77,7 +77,7 @@ public class MaildirHostSystem extends JamesImapHostSystem {
         GroupMembershipResolver groupMembershipResolver = new SimpleGroupMembershipResolver();
         MessageParser messageParser = new MessageParser();
 
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         StoreRightManager storeRightManager = new StoreRightManager(mailboxSessionMapperFactory, aclResolver, groupMembershipResolver, eventBus);
         StoreMailboxAnnotationManager annotationManager = new StoreMailboxAnnotationManager(mailboxSessionMapperFactory, storeRightManager);
         SessionProviderImpl sessionProvider = new SessionProviderImpl(authenticator, authorizator);
diff --git a/mpt/impl/imap-mailbox/rabbitmq/pom.xml b/mpt/impl/imap-mailbox/rabbitmq/pom.xml
index a12ad81..8f6afc9 100644
--- a/mpt/impl/imap-mailbox/rabbitmq/pom.xml
+++ b/mpt/impl/imap-mailbox/rabbitmq/pom.xml
@@ -79,6 +79,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java b/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
index 3c72917..c34510c 100644
--- a/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
+++ b/mpt/impl/imap-mailbox/rabbitmq/src/test/java/org/apache/james/mpt/imapmailbox/rabbitmq/host/RabbitMQEventBusHostSystem.java
@@ -43,8 +43,8 @@ import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.store.StoreSubscriptionManager;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mpt.api.ImapFeatures;
 import org.apache.james.mpt.api.ImapFeatures.Feature;
 import org.apache.james.mpt.host.JamesImapHostSystem;
@@ -110,7 +110,7 @@ public class RabbitMQEventBusHostSystem extends JamesImapHostSystem {
         EventSerializer eventSerializer = new EventSerializer(mailboxIdFactory, messageIdFactory, new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
         RoutingKeyConverter routingKeyConverter = new RoutingKeyConverter(ImmutableSet.of(new MailboxIdRegistrationKey.Factory(mailboxIdFactory)));
         return new RabbitMQEventBus(reactorRabbitMQChannelPool, eventSerializer, RetryBackoffConfiguration.DEFAULT,
-            routingKeyConverter, new MemoryEventDeadLetters(), new NoopMetricFactory());
+            routingKeyConverter, new MemoryEventDeadLetters(), new RecordingMetricFactory());
     }
 
     @Override
diff --git a/protocols/imap/pom.xml b/protocols/imap/pom.xml
index bf957e0..961bc7f 100644
--- a/protocols/imap/pom.xml
+++ b/protocols/imap/pom.xml
@@ -65,6 +65,11 @@
             <artifactId>metrics-api</artifactId>
         </dependency>
         <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>${james.protocols.groupId}</groupId>
             <artifactId>protocols-api</artifactId>
         </dependency>
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
index dcca0de..3af65df 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/CopyProcessorTest.java
@@ -50,7 +50,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -77,7 +77,7 @@ public class CopyProcessorTest {
         imapSession = new FakeImapSession();
         mailboxSession = MailboxSessionUtil.create(USERNAME);
 
-        testee = new CopyProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new NoopMetricFactory());
+        testee = new CopyProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new RecordingMetricFactory());
 
         imapSession.authenticated();
         imapSession.setMailboxSession(mailboxSession);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/DeleteACLProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/DeleteACLProcessorTest.java
index 97241da..69a1ada 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/DeleteACLProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/DeleteACLProcessorTest.java
@@ -48,7 +48,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -77,7 +77,7 @@ public class DeleteACLProcessorTest {
         path = MailboxPath.forUser(USER_1, MAILBOX_NAME);
         UnpooledStatusResponseFactory statusResponseFactory = new UnpooledStatusResponseFactory();
         mailboxManager = mock(MailboxManager.class);
-        subject = new DeleteACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new NoopMetricFactory());
+        subject = new DeleteACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new RecordingMetricFactory());
         imapSession = new FakeImapSession();
         mailboxSession = MailboxSessionUtil.create(USER_1);
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetACLProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetACLProcessorTest.java
index d25f37c..45a889b 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetACLProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetACLProcessorTest.java
@@ -47,7 +47,7 @@ import org.apache.james.mailbox.MessageManager.MetaData.FetchGroup;
 import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -76,7 +76,7 @@ public class GetACLProcessorTest {
         path = MailboxPath.forUser(USER_1, MAILBOX_NAME);
         UnpooledStatusResponseFactory statusResponseFactory = new UnpooledStatusResponseFactory();
         mailboxManager = mock(MailboxManager.class);
-        subject = new GetACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new NoopMetricFactory());
+        subject = new GetACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new RecordingMetricFactory());
         imapSession = new FakeImapSession();
         mailboxSession = MailboxSessionUtil.create(USER_1);
         MessageManager messageManager = mock(MessageManager.class);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
index 27a2433..0795c5c 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
@@ -54,7 +54,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxAnnotation;
 import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -122,7 +122,7 @@ public class GetAnnotationProcessorTest {
         MockitoAnnotations.initMocks(this);
         initAndMockData();
 
-        processor = new GetAnnotationProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new NoopMetricFactory());
+        processor = new GetAnnotationProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
index dd60e61..bcb35dc 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaProcessorTest.java
@@ -53,7 +53,7 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -90,7 +90,7 @@ public class GetQuotaProcessorTest {
         mockedResponder = mock(ImapProcessor.Responder.class);
         mockedMailboxManager = mock(MailboxManager.class);
         testee = new GetQuotaProcessor(mock(ImapProcessor.class), mockedMailboxManager,
-            statusResponseFactory, mockedQuotaManager, mockedQuotaRootResolver, new NoopMetricFactory());
+            statusResponseFactory, mockedQuotaManager, mockedQuotaRootResolver, new RecordingMetricFactory());
         mailbox = mock(Mailbox.class);
         when(mailbox.generateAssociatedPath()).thenReturn(MAILBOX_PATH);
         imapSession.authenticated();
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
index 1eb5820..440e5b5 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetQuotaRootProcessorTest.java
@@ -54,7 +54,7 @@ import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
 import org.apache.james.mailbox.quota.QuotaManager;
 import org.apache.james.mailbox.quota.QuotaRootResolver;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -87,7 +87,7 @@ public class GetQuotaRootProcessorTest {
         mockedResponder = mock(ImapProcessor.Responder.class);
         mockedMailboxManager = mock(MailboxManager.class);
         testee = new GetQuotaRootProcessor(mock(ImapProcessor.class), mockedMailboxManager,
-            statusResponseFactory, mockedQuotaRootResolver, mockedQuotaManager, new NoopMetricFactory());
+            statusResponseFactory, mockedQuotaRootResolver, mockedQuotaManager, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/LSubProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/LSubProcessorTest.java
index 80fcc4f..fc92529 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/LSubProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/LSubProcessorTest.java
@@ -44,7 +44,7 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.SubscriptionManager;
 import org.apache.james.mailbox.model.MailboxMetaData;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -95,7 +95,7 @@ public class LSubProcessorTest {
         responderImpl = responder;
         manager =  mock(SubscriptionManager.class);
         mailboxSession = MailboxSessionUtil.create(USER);
-        processor = new LSubProcessor(next, mock(MailboxManager.class), manager, serverResponseFactory, new NoopMetricFactory());
+        processor = new LSubProcessor(next, mock(MailboxManager.class), manager, serverResponseFactory, new RecordingMetricFactory());
         session.setMailboxSession(mailboxSession);
     }
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/ListRightsProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/ListRightsProcessorTest.java
index 5b57277..6bbbd04 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/ListRightsProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/ListRightsProcessorTest.java
@@ -49,7 +49,7 @@ import org.apache.james.mailbox.model.MailboxACL;
 import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -79,7 +79,7 @@ public class ListRightsProcessorTest {
         path = MailboxPath.forUser(USER_1, MAILBOX_NAME);
         UnpooledStatusResponseFactory statusResponseFactory = new UnpooledStatusResponseFactory();
         mailboxManager = mock(MailboxManager.class);
-        subject = new ListRightsProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new NoopMetricFactory());
+        subject = new ListRightsProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new RecordingMetricFactory());
         imapSession = new FakeImapSession();
         mailboxSession = MailboxSessionUtil.create(USER_1);
         MessageManager messageManager = mock(MessageManager.class);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
index eeb3e08..20515cb 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/MoveProcessorTest.java
@@ -53,7 +53,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Mailbox;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -81,7 +81,7 @@ public class MoveProcessorTest {
         mailboxSession = MailboxSessionUtil.create(USERNAME);
 
         when(mockMailboxManager.hasCapability(eq(MailboxCapabilities.Move))).thenReturn(true);
-        testee = new MoveProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new NoopMetricFactory());
+        testee = new MoveProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new RecordingMetricFactory());
         verify(mockMailboxManager).hasCapability(MailboxCapabilities.Move);
 
         imapSession.authenticated();
@@ -96,7 +96,7 @@ public class MoveProcessorTest {
     @Test
     public void getImplementedCapabilitiesShouldNotContainMoveWhenUnSupportedByMailboxManager() {
         when(mockMailboxManager.hasCapability(eq(MailboxCapabilities.Move))).thenReturn(false);
-        assertThat(new MoveProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new NoopMetricFactory())
+        assertThat(new MoveProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new RecordingMetricFactory())
                 .getImplementedCapabilities(null)).isEmpty();
     }
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/NamespaceProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/NamespaceProcessorTest.java
index 4c17a5d..ac91c4d 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/NamespaceProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/NamespaceProcessorTest.java
@@ -47,7 +47,7 @@ import org.apache.james.imap.message.response.NamespaceResponse;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.model.MailboxConstants;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -71,7 +71,7 @@ public class NamespaceProcessorTest {
         sharedSpaces = new ArrayList<>();
         statusResponseStub = mock(StatusResponseFactory.class);
         mailboxManagerStub = mock(MailboxManager.class);
-        subject = new NamespaceProcessor(mock(ImapProcessor.class), mailboxManagerStub, statusResponseStub, new NoopMetricFactory());
+        subject = new NamespaceProcessor(mock(ImapProcessor.class), mailboxManagerStub, statusResponseStub, new RecordingMetricFactory());
         imapSession = spy(new FakeImapSession());
         mailboxSession = mock(MailboxSession.class);
      
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
index b6f7bfb..3ee524a 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SearchProcessorTest.java
@@ -66,7 +66,7 @@ import org.apache.james.mailbox.model.SearchQuery.AddressType;
 import org.apache.james.mailbox.model.SearchQuery.Criterion;
 import org.apache.james.mailbox.model.SearchQuery.DateResolution;
 import org.apache.james.mailbox.model.TestId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -128,7 +128,7 @@ public class SearchProcessorTest {
         selectedMailbox = mock(SelectedMailbox.class);
         when(selectedMailbox.getMailboxId()).thenReturn(mailboxId);
         
-        processor = new SearchProcessor(next,  mailboxManager, serverResponseFactory, new NoopMetricFactory());
+        processor = new SearchProcessor(next,  mailboxManager, serverResponseFactory, new RecordingMetricFactory());
         expectOk();
     }
 
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
index 44b66c9..8aa91f1 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetACLProcessorTest.java
@@ -50,7 +50,7 @@ import org.apache.james.mailbox.model.MailboxACL.EditMode;
 import org.apache.james.mailbox.model.MailboxACL.EntryKey;
 import org.apache.james.mailbox.model.MailboxACL.Rfc4314Rights;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -81,7 +81,7 @@ public class SetACLProcessorTest {
         path = MailboxPath.forUser(USER_1, MAILBOX_NAME);
         UnpooledStatusResponseFactory statusResponseFactory = new UnpooledStatusResponseFactory();
         mailboxManager = mock(MailboxManager.class);
-        subject = new SetACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new NoopMetricFactory());
+        subject = new SetACLProcessor(mock(ImapProcessor.class), mailboxManager, statusResponseFactory, new RecordingMetricFactory());
         imapSession = new FakeImapSession();
         mailboxSession = MailboxSessionUtil.create(USER_1);
         MessageManager messageManager = mock(MessageManager.class);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetAnnotationProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetAnnotationProcessorTest.java
index 010fa3f..7cc60c9 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetAnnotationProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetAnnotationProcessorTest.java
@@ -50,7 +50,7 @@ import org.apache.james.mailbox.exception.MailboxNotFoundException;
 import org.apache.james.mailbox.model.MailboxAnnotation;
 import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -104,7 +104,7 @@ public class SetAnnotationProcessorTest {
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         initAndMockData();
-        processor = new SetAnnotationProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new NoopMetricFactory());
+        processor = new SetAnnotationProcessor(mockNextProcessor, mockMailboxManager, mockStatusResponseFactory, new RecordingMetricFactory());
     }
     
     @After
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetQuotaProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetQuotaProcessorTest.java
index 30791b8..229c5ea 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetQuotaProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetQuotaProcessorTest.java
@@ -34,7 +34,7 @@ import org.apache.james.imap.message.response.UnpooledStatusResponseFactory;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -51,7 +51,7 @@ public class SetQuotaProcessorTest {
         imapSession = new FakeImapSession();
         mockedResponder = mock(ImapProcessor.Responder.class);
         testee = new SetQuotaProcessor(mock(ImapProcessor.class), mock(MailboxManager.class),
-            statusResponseFactory, new NoopMetricFactory());
+            statusResponseFactory, new RecordingMetricFactory());
         imapSession.authenticated();
         imapSession.setMailboxSession(mailboxSession);
     }
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
index d45c82a..4c885ba 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/MailboxEventAnalyserTest.java
@@ -53,7 +53,7 @@ import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.store.event.EventFactory;
 import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -130,7 +130,7 @@ public class MailboxEventAnalyserTest {
     @Before
     public void setUp() throws MailboxException {
         FakeImapSession imapSession = new FakeImapSession();
-        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        InVMEventBus eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
         imapSession.setMailboxSession(MAILBOX_SESSION);
         imapSession.authenticated();
 
diff --git a/protocols/smtp/pom.xml b/protocols/smtp/pom.xml
index a72f278..cbd1f99 100644
--- a/protocols/smtp/pom.xml
+++ b/protocols/smtp/pom.xml
@@ -46,6 +46,11 @@
             <artifactId>metrics-api</artifactId>
         </dependency>
         <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>${james.protocols.groupId}</groupId>
             <artifactId>protocols-api</artifactId>
         </dependency>
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
index 1fb15da..19d084f 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/AbstractSMTPServerTest.java
@@ -36,7 +36,7 @@ import org.apache.commons.net.smtp.SMTPClient;
 import org.apache.commons.net.smtp.SMTPReply;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.MaybeSender;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.protocols.api.Protocol;
 import org.apache.james.protocols.api.ProtocolServer;
 import org.apache.james.protocols.api.handler.ConnectHandler;
@@ -945,7 +945,7 @@ public abstract class AbstractSMTPServerTest {
 
     
     protected Protocol createProtocol(ProtocolHandler... handlers) throws WiringException {
-        SMTPProtocolHandlerChain chain = new SMTPProtocolHandlerChain(new NoopMetricFactory());
+        SMTPProtocolHandlerChain chain = new SMTPProtocolHandlerChain(new RecordingMetricFactory());
         chain.addAll(0, Arrays.asList(handlers));
         chain.wireExtensibleHandlers();
         return new SMTPProtocol(chain, new SMTPConfigurationImpl());
diff --git a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
index 8ef21c1..b5edd0d 100644
--- a/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
+++ b/protocols/smtp/src/test/java/org/apache/james/protocols/smtp/netty/NettyStartTlsSMTPServerTest.java
@@ -34,7 +34,7 @@ import javax.mail.internet.MimeMessage;
 
 import org.apache.commons.net.smtp.SMTPReply;
 import org.apache.commons.net.smtp.SMTPSClient;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.protocols.api.Encryption;
 import org.apache.james.protocols.api.Protocol;
 import org.apache.james.protocols.api.ProtocolServer;
@@ -101,7 +101,7 @@ public class NettyStartTlsSMTPServerTest {
     }
 
     private Protocol createProtocol(Optional<ProtocolHandler> handler) throws WiringException {
-        SMTPProtocolHandlerChain chain = new SMTPProtocolHandlerChain(new NoopMetricFactory());
+        SMTPProtocolHandlerChain chain = new SMTPProtocolHandlerChain(new RecordingMetricFactory());
         if (handler.isPresent()) {
             chain.add(handler.get());
         }
diff --git a/server/container/guice/mailbox/pom.xml b/server/container/guice/mailbox/pom.xml
index 7db97a0..1360545 100644
--- a/server/container/guice/mailbox/pom.xml
+++ b/server/container/guice/mailbox/pom.xml
@@ -54,6 +54,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
index bc921fb..5ae23b0 100644
--- a/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
+++ b/server/container/guice/mailbox/src/test/java/org/apache/james/modules/mailbox/MailboxListenersLoaderImplTest.java
@@ -38,7 +38,7 @@ import org.apache.james.mailbox.events.Group;
 import org.apache.james.mailbox.events.InVMEventBus;
 import org.apache.james.mailbox.events.MailboxListener;
 import org.apache.james.mailbox.events.delivery.InVmEventDelivery;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.server.core.configuration.FileConfigurationProvider;
 import org.apache.james.utils.ExtendedClassLoader;
 import org.apache.james.utils.GuiceGenericLoader;
@@ -46,7 +46,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.inject.Guice;
 
 class MailboxListenersLoaderImplTest {
 
@@ -59,7 +58,7 @@ class MailboxListenersLoaderImplTest {
         when(fileSystem.getFile(anyString()))
             .thenThrow(new FileNotFoundException());
 
-        eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()));
+        eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()));
 
         GuiceGenericLoader genericLoader = GuiceGenericLoader.forTesting(new ExtendedClassLoader(fileSystem));
         testee = new MailboxListenersLoaderImpl(new MailboxListenerFactory(genericLoader), eventBus, ImmutableSet.of());
diff --git a/server/container/mailbox-jmx/pom.xml b/server/container/mailbox-jmx/pom.xml
index c09b251..72fceba 100644
--- a/server/container/mailbox-jmx/pom.xml
+++ b/server/container/mailbox-jmx/pom.xml
@@ -65,6 +65,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/dns-service/dnsservice-dnsjava/pom.xml b/server/dns-service/dnsservice-dnsjava/pom.xml
index ca432a5..e3b9a39 100644
--- a/server/dns-service/dnsservice-dnsjava/pom.xml
+++ b/server/dns-service/dnsservice-dnsjava/pom.xml
@@ -52,6 +52,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/dns-service/dnsservice-dnsjava/src/test/java/org/apache/james/dnsservice/dnsjava/DNSJavaServiceTest.java b/server/dns-service/dnsservice-dnsjava/src/test/java/org/apache/james/dnsservice/dnsjava/DNSJavaServiceTest.java
index f95426c..e7d1a22 100644
--- a/server/dns-service/dnsservice-dnsjava/src/test/java/org/apache/james/dnsservice/dnsjava/DNSJavaServiceTest.java
+++ b/server/dns-service/dnsservice-dnsjava/src/test/java/org/apache/james/dnsservice/dnsjava/DNSJavaServiceTest.java
@@ -31,7 +31,7 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.server.core.configuration.FileConfigurationProvider;
 import org.junit.After;
 import org.junit.Before;
@@ -226,7 +226,7 @@ public class DNSJavaServiceTest {
     private final class TestableDNSServer extends DNSJavaService {
 
         public TestableDNSServer() {
-            super(new NoopMetricFactory());
+            super(new RecordingMetricFactory());
         }
 
         public void setResolver(Resolver r) {
diff --git a/server/mailet/mailetcontainer-camel/pom.xml b/server/mailet/mailetcontainer-camel/pom.xml
index 6fd3b23..6369b32 100644
--- a/server/mailet/mailetcontainer-camel/pom.xml
+++ b/server/mailet/mailetcontainer-camel/pom.xml
@@ -91,6 +91,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelCompositeProcessorTest.java b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelCompositeProcessorTest.java
index 95d03ae..494dceb 100644
--- a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelCompositeProcessorTest.java
+++ b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelCompositeProcessorTest.java
@@ -25,14 +25,14 @@ import org.apache.james.mailetcontainer.api.mock.MockMailetLoader;
 import org.apache.james.mailetcontainer.api.mock.MockMatcherLoader;
 import org.apache.james.mailetcontainer.lib.AbstractStateCompositeProcessor;
 import org.apache.james.mailetcontainer.lib.AbstractStateCompositeProcessorTest;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.mailet.base.test.FakeMailContext;
 
 public class CamelCompositeProcessorTest extends AbstractStateCompositeProcessorTest {
 
     @Override
     protected AbstractStateCompositeProcessor createProcessor(HierarchicalConfiguration<ImmutableNode> config) throws Exception {
-        CamelCompositeProcessor processor = new CamelCompositeProcessor(new NoopMetricFactory(),
+        CamelCompositeProcessor processor = new CamelCompositeProcessor(new RecordingMetricFactory(),
             FakeMailContext.defaultContext(),
             new MockMatcherLoader(),
             new MockMailetLoader());
diff --git a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessorTest.java b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessorTest.java
index 1146951..a962dfd 100644
--- a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessorTest.java
+++ b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/camel/CamelMailetProcessorTest.java
@@ -29,7 +29,7 @@ import org.apache.james.mailetcontainer.api.mock.MockMailetLoader;
 import org.apache.james.mailetcontainer.api.mock.MockMatcherLoader;
 import org.apache.james.mailetcontainer.lib.AbstractStateMailetProcessor;
 import org.apache.james.mailetcontainer.lib.AbstractStateMailetProcessorTest;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.mailet.base.test.FakeMailContext;
 
 public class CamelMailetProcessorTest extends AbstractStateMailetProcessorTest {
@@ -38,7 +38,7 @@ public class CamelMailetProcessorTest extends AbstractStateMailetProcessorTest {
     protected AbstractStateMailetProcessor createProcessor(HierarchicalConfiguration<ImmutableNode> configuration) throws Exception {
         CamelMailetProcessor processor = null;
         try {
-            processor = new CamelMailetProcessor(new NoopMetricFactory());
+            processor = new CamelMailetProcessor(new RecordingMetricFactory());
             processor.setCamelContext(new DefaultCamelContext());
             processor.setMailetContext(FakeMailContext.defaultContext());
             processor.setMailetLoader(new MockMailetLoader());
diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml
index b1c30bf..7f17e11 100644
--- a/server/mailet/mailets/pom.xml
+++ b/server/mailet/mailets/pom.xml
@@ -94,11 +94,6 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
-            <artifactId>metrics-tests</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
             <artifactId>james-mdn</artifactId>
         </dependency>
         <dependency>
@@ -181,6 +176,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
index ba840fc..5e8dc59 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
@@ -27,7 +27,7 @@ import javax.mail.MessagingException;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.domainlist.api.DomainList;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.james.spamassassin.mock.MockSpamd;
 import org.apache.james.spamassassin.mock.MockSpamdTestRule;
@@ -48,7 +48,7 @@ public class SpamAssassinTest {
     @Rule
     public MockSpamdTestRule spamd = new MockSpamdTestRule();
 
-    private SpamAssassin mailet = new SpamAssassin(new NoopMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST));
+    private SpamAssassin mailet = new SpamAssassin(new RecordingMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST));
 
     @Test
     public void initShouldSetDefaultSpamdHostWhenNone() throws Exception {
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/LocalDeliveryTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/LocalDeliveryTest.java
index aa3d4b6..ccbb2d2 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/LocalDeliveryTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/LocalDeliveryTest.java
@@ -38,7 +38,7 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.transport.mailets.LocalDelivery;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.mailet.Mail;
@@ -63,7 +63,7 @@ public class LocalDeliveryTest {
         usersRepository = mock(UsersRepository.class);
         mailboxManager = mock(MailboxManager.class);
 
-        MetricFactory metricFactory = new NoopMetricFactory();
+        MetricFactory metricFactory = new RecordingMetricFactory();
         testee = new LocalDelivery(usersRepository, mailboxManager, metricFactory);
 
         session = mock(MailboxSession.class);
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/ToRecipientFolderTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/ToRecipientFolderTest.java
index 35f59bc..6b3b249 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/ToRecipientFolderTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/delivery/ToRecipientFolderTest.java
@@ -39,7 +39,7 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageManager;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.transport.mailets.ToRecipientFolder;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.mailet.Mail;
@@ -77,7 +77,7 @@ public class ToRecipientFolderTest {
         mailboxManager = mock(MailboxManager.class);
 
 
-        MetricFactory metricFactory = new NoopMetricFactory();
+        MetricFactory metricFactory = new RecordingMetricFactory();
         testee = new ToRecipientFolder(mailboxManager, usersRepository, metricFactory);
 
         session = mock(MailboxSession.class);
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
index 5690778..4c7a87e 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/remote/delivery/RemoteDeliveryTest.java
@@ -34,7 +34,7 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.domainlist.lib.DomainListConfiguration;
 import org.apache.james.domainlist.memory.MemoryDomainList;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.queue.api.MailPrioritySupport;
 import org.apache.james.queue.api.MailQueueFactory;
 import org.apache.james.queue.api.ManageableMailQueue;
@@ -105,7 +105,7 @@ public class RemoteDeliveryTest {
         MemoryDomainList domainList = new MemoryDomainList(dnsService);
         domainList.configure(DomainListConfiguration.builder().defaultDomain(JAMES_APACHE_ORG_DOMAIN));
         remoteDelivery = new RemoteDelivery(dnsService, domainList,
-            queueFactory, new NoopMetricFactory(), RemoteDelivery.ThreadState.DO_NOT_START_THREADS);
+            queueFactory, new RecordingMetricFactory(), RemoteDelivery.ThreadState.DO_NOT_START_THREADS);
     }
 
     @Test
diff --git a/server/protocols/jmap-draft/pom.xml b/server/protocols/jmap-draft/pom.xml
index c5734e8..63da871 100644
--- a/server/protocols/jmap-draft/pom.xml
+++ b/server/protocols/jmap-draft/pom.xml
@@ -145,6 +145,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/AuthenticationFilterTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/AuthenticationFilterTest.java
index fa0762a..adfe5ad 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/AuthenticationFilterTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/AuthenticationFilterTest.java
@@ -38,7 +38,7 @@ import org.apache.james.jmap.api.access.AccessTokenRepository;
 import org.apache.james.jmap.draft.exceptions.MailboxSessionCreationException;
 import org.apache.james.jmap.memory.access.MemoryAccessTokenRepository;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -64,7 +64,7 @@ public class AuthenticationFilterTest {
         when(mockedRequest.getMethod()).thenReturn("POST");
         List<AuthenticationStrategy> fakeAuthenticationStrategies = ImmutableList.of(new FakeAuthenticationStrategy(false));
 
-        testee = new AuthenticationFilter(fakeAuthenticationStrategies, new NoopMetricFactory());
+        testee = new AuthenticationFilter(fakeAuthenticationStrategies, new RecordingMetricFactory());
         filterChain = mock(FilterChain.class);
     }
 
@@ -96,7 +96,7 @@ public class AuthenticationFilterTest {
 
         accessTokenRepository.addToken(USERNAME, token).block();
 
-        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(new FakeAuthenticationStrategy(true)), new NoopMetricFactory());
+        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(new FakeAuthenticationStrategy(true)), new RecordingMetricFactory());
         sut.doFilter(mockedRequest, mockedResponse, filterChain);
 
         verify(filterChain).doFilter(any(ServletRequest.class), eq(mockedResponse));
@@ -110,7 +110,7 @@ public class AuthenticationFilterTest {
 
         accessTokenRepository.addToken(USERNAME, token).block();
 
-        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(new FakeAuthenticationStrategy(false), new FakeAuthenticationStrategy(true)), new NoopMetricFactory());
+        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(new FakeAuthenticationStrategy(false), new FakeAuthenticationStrategy(true)), new RecordingMetricFactory());
         sut.doFilter(mockedRequest, mockedResponse, filterChain);
 
         verify(filterChain).doFilter(any(ServletRequest.class), eq(mockedResponse));
@@ -131,7 +131,7 @@ public class AuthenticationFilterTest {
         when(mockedRequest.getHeader("Authorization"))
                 .thenReturn(TOKEN);
 
-        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(), new NoopMetricFactory());
+        AuthenticationFilter sut = new AuthenticationFilter(ImmutableList.of(), new RecordingMetricFactory());
         sut.doFilter(mockedRequest, mockedResponse, filterChain);
 
         verify(mockedResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterTest.java
index 481e829..218eeac 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterTest.java
@@ -23,7 +23,6 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.time.Duration;
 
 import org.apache.james.core.Username;
-import org.apache.james.jmap.draft.DefaultMailboxesProvisioningFilter;
 import org.apache.james.mailbox.DefaultMailboxes;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
@@ -31,7 +30,7 @@ import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.store.StoreSubscriptionManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.Before;
 import org.junit.Test;
@@ -53,7 +52,7 @@ public class DefaultMailboxesProvisioningFilterTest {
 
         mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
         subscriptionManager = new StoreSubscriptionManager(mailboxManager.getMapperFactory());
-        testee = new DefaultMailboxesProvisioningFilter(mailboxManager, subscriptionManager, new NoopMetricFactory());
+        testee = new DefaultMailboxesProvisioningFilter(mailboxManager, subscriptionManager, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterThreadTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterThreadTest.java
index 5981e9a..5e349aa 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterThreadTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DefaultMailboxesProvisioningFilterThreadTest.java
@@ -29,14 +29,13 @@ import java.time.Duration;
 import java.util.Optional;
 
 import org.apache.james.core.Username;
-import org.apache.james.jmap.draft.DefaultMailboxesProvisioningFilter;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.SubscriptionManager;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.TestId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.Before;
 import org.junit.Test;
@@ -55,7 +54,7 @@ public class DefaultMailboxesProvisioningFilterThreadTest {
         session = MailboxSessionUtil.create(USERNAME);
         mailboxManager = mock(MailboxManager.class);
         subscriptionManager = mock(SubscriptionManager.class);
-        sut = new DefaultMailboxesProvisioningFilter(mailboxManager, subscriptionManager, new NoopMetricFactory());
+        sut = new DefaultMailboxesProvisioningFilter(mailboxManager, subscriptionManager, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DownloadServletTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DownloadServletTest.java
index f6fe23b..e52c47e 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DownloadServletTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/DownloadServletTest.java
@@ -28,14 +28,13 @@ import static org.mockito.Mockito.when;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.james.core.Username;
-import org.apache.james.jmap.draft.DownloadServlet;
 import org.apache.james.jmap.draft.api.SimpleTokenFactory;
 import org.apache.james.jmap.draft.utils.DownloadPath;
 import org.apache.james.mailbox.BlobManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
 import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Test;
 
 public class DownloadServletTest {
@@ -48,7 +47,7 @@ public class DownloadServletTest {
             .thenThrow(new MailboxException());
         SimpleTokenFactory nullSimpleTokenFactory = null;
 
-        DownloadServlet testee = new DownloadServlet(mockedBlobManager, nullSimpleTokenFactory, new NoopMetricFactory());
+        DownloadServlet testee = new DownloadServlet(mockedBlobManager, nullSimpleTokenFactory, new RecordingMetricFactory());
 
         HttpServletResponse resp = mock(HttpServletResponse.class);
         testee.download(mailboxSession, DownloadPath.from("/blobId"), resp);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/JMAPServletTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/JMAPServletTest.java
index 692c216..de1a3dd 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/JMAPServletTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/JMAPServletTest.java
@@ -31,13 +31,12 @@ import java.util.stream.Stream;
 
 import org.apache.james.http.jetty.Configuration;
 import org.apache.james.http.jetty.JettyHttpServer;
-import org.apache.james.jmap.draft.JMAPServlet;
 import org.apache.james.jmap.draft.methods.ErrorResponse;
 import org.apache.james.jmap.draft.methods.Method;
 import org.apache.james.jmap.draft.methods.RequestHandler;
-import org.apache.james.jmap.draft.model.MethodCallId;
 import org.apache.james.jmap.draft.model.InvocationResponse;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.jmap.draft.model.MethodCallId;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -58,7 +57,7 @@ public class JMAPServletTest {
     @Before
     public void setup() throws Exception {
         requestHandler = mock(RequestHandler.class);
-        JMAPServlet jmapServlet = new JMAPServlet(requestHandler, new NoopMetricFactory());
+        JMAPServlet jmapServlet = new JMAPServlet(requestHandler, new RecordingMetricFactory());
 
         server = JettyHttpServer.create(
                 Configuration.builder()
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterTest.java
index 3fec2ca..23a2f81 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterTest.java
@@ -38,7 +38,7 @@ import org.apache.james.core.Username;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.user.memory.MemoryUsersRepository;
@@ -59,7 +59,7 @@ public class UserProvisioningFilterTest {
     @Before
     public void setup() throws Exception {
         usersRepository = MemoryUsersRepository.withoutVirtualHosting(NO_DOMAIN_LIST);
-        sut = new UserProvisioningFilter(usersRepository, new NoopMetricFactory());
+        sut = new UserProvisioningFilter(usersRepository, new RecordingMetricFactory());
         request = mock(HttpServletRequest.class);
         response = mock(HttpServletResponse.class);
         chain = mock(FilterChain.class);
@@ -103,7 +103,7 @@ public class UserProvisioningFilterTest {
     public void filterShouldNotTryToAddUserWhenReadOnlyUsersRepository() throws Exception {
         UsersRepository usersRepository = mock(UsersRepository.class);
         when(usersRepository.isReadOnly()).thenReturn(true);
-        sut = new UserProvisioningFilter(usersRepository, new NoopMetricFactory());
+        sut = new UserProvisioningFilter(usersRepository, new RecordingMetricFactory());
 
         MailboxSession mailboxSession = MailboxSessionUtil.create(USERNAME_WITH_DOMAIN);
         when(request.getAttribute(AuthenticationFilter.MAILBOX_SESSION))
@@ -119,7 +119,7 @@ public class UserProvisioningFilterTest {
     public void filterShouldChainCallsWhenReadOnlyUsersRepository() throws Exception {
         UsersRepository usersRepository = mock(UsersRepository.class);
         when(usersRepository.isReadOnly()).thenReturn(true);
-        sut = new UserProvisioningFilter(usersRepository, new NoopMetricFactory());
+        sut = new UserProvisioningFilter(usersRepository, new RecordingMetricFactory());
 
         MailboxSession mailboxSession = MailboxSessionUtil.create(USERNAME_WITH_DOMAIN);
         when(request.getAttribute(AuthenticationFilter.MAILBOX_SESSION))
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterThreadTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterThreadTest.java
index 43b3984..8ee5474 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterThreadTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/UserProvisioningFilterThreadTest.java
@@ -25,7 +25,7 @@ import org.apache.james.core.Username;
 import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MailboxSessionUtil;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.junit.Before;
@@ -42,7 +42,7 @@ public class UserProvisioningFilterThreadTest {
     public void before() {
         usersRepository = MemoryUsersRepository.withoutVirtualHosting(NO_DOMAIN_LIST);
         session = MailboxSessionUtil.create(Username.of("username"));
-        sut = new UserProvisioningFilter(usersRepository, new NoopMetricFactory());
+        sut = new UserProvisioningFilter(usersRepository, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
index d8539b6..35c2bcc 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/GetMessagesMethodTest.java
@@ -66,8 +66,8 @@ import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.store.StoreMailboxManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
 import org.apache.james.metrics.logger.DefaultMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mime4j.message.BodyPartBuilder;
 import org.apache.james.mime4j.message.MultipartBuilder;
 import org.apache.james.mime4j.stream.RawField;
@@ -125,9 +125,9 @@ public class GetMessagesMethodTest {
         messageMetadataViewFactory = spy(new MessageMetadataViewFactory(blobManager, messageIdManager));
         MessageFullViewFactory messageFullViewFactory = new MessageFullViewFactory(blobManager, messageContentExtractor,
             htmlTextExtractor, messageIdManager,
-            new MemoryMessageFastViewProjection(new NoopMetricFactory()));
+            new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
         MessageFastViewFactory messageFastViewFactory = new MessageFastViewFactory(blobManager, messageIdManager,
-            new MemoryMessageFastViewProjection(new NoopMetricFactory()), messageFullViewFactory);
+            new MemoryMessageFastViewProjection(new RecordingMetricFactory()), messageFullViewFactory);
 
         MetaMessageViewFactory metaMessageViewFactory = new MetaMessageViewFactory(
             messageFullViewFactory,
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/MessageSenderTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/MessageSenderTest.java
index bffb867..fdd95e3 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/MessageSenderTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/MessageSenderTest.java
@@ -48,7 +48,7 @@ import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.model.BlobId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestMessageId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.server.core.Envelope;
 import org.apache.james.util.html.HtmlTextExtractor;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -93,7 +93,7 @@ class MessageSenderTest {
         when(blobManager.toBlobId(any(MessageId.class))).thenReturn(BlobId.fromString("fake"));
         MessageIdManager messageIdManager = mock(MessageIdManager.class);
         MessageFullViewFactory messageFullViewFactory = new MessageFullViewFactory(blobManager, messageContentExtractor, htmlTextExtractor, messageIdManager,
-            new MemoryMessageFastViewProjection(new NoopMetricFactory()));
+            new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
         jmapMessage = messageFullViewFactory.fromMetaDataWithContent(message);
         envelope = EnvelopeUtils.fromMessage(jmapMessage);
     }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessorTest.java
index 3cf69da..844e631 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesCreationProcessorTest.java
@@ -36,7 +36,7 @@ import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.mailbox.inmemory.InMemoryId.Factory;
 import org.apache.james.mailbox.model.MailboxId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -52,7 +52,7 @@ public class SetMailboxesCreationProcessorTest {
     public void setup() {
         mailboxManager = mock(MailboxManager.class);
         mailboxIdFactory = new InMemoryId.Factory();
-        sut = new SetMailboxesCreationProcessor(mailboxManager, subscriptionManager, mailboxFactory, mailboxIdFactory, new NoopMetricFactory());
+        sut = new SetMailboxesCreationProcessor(mailboxManager, subscriptionManager, mailboxFactory, mailboxIdFactory, new RecordingMetricFactory());
     }
 
     @Test
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
index 00a962b..34cc705 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMailboxesUpdateProcessorTest.java
@@ -41,7 +41,7 @@ import org.apache.james.mailbox.SubscriptionManager;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.inmemory.InMemoryId;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -62,7 +62,7 @@ public class SetMailboxesUpdateProcessorTest {
         mockedMailboxUtils = mock(MailboxUtils.class);
         mockedMailboxFactory = mock(MailboxFactory.class);
         mockedMailboxSession = mock(MailboxSession.class);
-        MetricFactory metricFactory = new NoopMetricFactory();
+        MetricFactory metricFactory = new RecordingMetricFactory();
         sut = new SetMailboxesUpdateProcessor(mockedMailboxUtils, mockedMailboxManager, mockSubscriptionManager, mockedMailboxFactory, metricFactory);
     }
 
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessorTest.java
index f5b8ebb..e554199 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessorTest.java
@@ -63,7 +63,7 @@ import org.apache.james.mailbox.model.MailboxId.Factory;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestMessageId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.OptionalUtils;
 import org.apache.james.util.html.HtmlTextExtractor;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -129,7 +129,7 @@ public class SetMessagesCreationProcessorTest {
         MessageIdManager messageIdManager = mock(MessageIdManager.class);
         messageFullViewFactory = new MessageFullViewFactory(blobManager, messageContentExtractor, htmlTextExtractor,
             messageIdManager,
-            new MemoryMessageFastViewProjection(new NoopMetricFactory()));
+            new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
         mockedMailSpool = mock(MailSpool.class);
         mockedAttachmentManager = mock(AttachmentManager.class);
         mockedMailboxManager = mock(MailboxManager.class);
@@ -145,7 +145,7 @@ public class SetMessagesCreationProcessorTest {
         sut = new SetMessagesCreationProcessor(messageFullViewFactory,
             fakeSystemMailboxesProvider,
             new AttachmentChecker(mockedAttachmentManager),
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             mockedMailboxManager,
             mockedMailboxIdFactory,
             messageAppender,
@@ -234,7 +234,7 @@ public class SetMessagesCreationProcessorTest {
     @Test
     public void processShouldReturnNonEmptyCreatedWhenRequestHasNonEmptyCreate() throws MailboxException {
         // Given
-        sut = new SetMessagesCreationProcessor(messageFullViewFactory, fakeSystemMailboxesProvider, new AttachmentChecker(mockedAttachmentManager), new NoopMetricFactory(), mockedMailboxManager, mockedMailboxIdFactory, messageAppender, messageSender, referenceUpdater);
+        sut = new SetMessagesCreationProcessor(messageFullViewFactory, fakeSystemMailboxesProvider, new AttachmentChecker(mockedAttachmentManager), new RecordingMetricFactory(), mockedMailboxManager, mockedMailboxIdFactory, messageAppender, messageSender, referenceUpdater);
 
         // When
         SetMessagesResponse result = sut.process(createMessageInOutbox, session);
@@ -250,7 +250,7 @@ public class SetMessagesCreationProcessorTest {
         // Given
         TestSystemMailboxesProvider doNotProvideOutbox = new TestSystemMailboxesProvider(Optional::empty, () -> optionalDrafts);
         SetMessagesCreationProcessor sut = new SetMessagesCreationProcessor(messageFullViewFactory, doNotProvideOutbox,
-            new AttachmentChecker(mockedAttachmentManager), new NoopMetricFactory(), mockedMailboxManager, mockedMailboxIdFactory,
+            new AttachmentChecker(mockedAttachmentManager), new RecordingMetricFactory(), mockedMailboxManager, mockedMailboxIdFactory,
             messageAppender,
             messageSender,
             referenceUpdater);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessorTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessorTest.java
index 990198a..9a60e03 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessorTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessorTest.java
@@ -33,7 +33,7 @@ import org.apache.james.mailbox.SystemMailboxesProvider;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestMessageId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.junit.Test;
 
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
@@ -56,7 +56,7 @@ public class SetMessagesUpdateProcessorTest {
             systemMailboxesProvider,
             mailboxIdFactory,
             messageSender,
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             referenceUpdater);
         SetMessagesRequest requestWithEmptyUpdate = SetMessagesRequest.builder().build();
 
@@ -91,7 +91,7 @@ public class SetMessagesUpdateProcessorTest {
             systemMailboxesProvider,
             mailboxIdFactory,
             messageSender,
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             referenceUpdater);
         MessageId requestMessageId = TestMessageId.of(1);
         SetMessagesRequest requestWithInvalidUpdate = SetMessagesRequest.builder()
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
index ccc5bde..1c1463b 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFastViewFactoryTest.java
@@ -54,7 +54,7 @@ import org.apache.james.mailbox.model.ComposedMessageId;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.store.StoreBlobManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.ClassLoaderUtils;
 import org.apache.james.util.html.HtmlTextExtractor;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -135,7 +135,7 @@ class MessageFastViewFactoryTest {
                 .build(ClassLoaderUtils.getSystemResourceAsSharedStream("fullMessage.eml")),
             session);
 
-        fastViewProjection = new MemoryMessageFastViewProjection(new NoopMetricFactory());
+        fastViewProjection = new MemoryMessageFastViewProjection(new RecordingMetricFactory());
 
         Mono.from(fastViewProjection.store(previewComputedMessage1.getMessageId(), PROJECTION_1))
             .block();
@@ -146,7 +146,7 @@ class MessageFastViewFactoryTest {
 
         blobManager = resources.getBlobManager();
         messageFullViewFactory = new MessageFullViewFactory(blobManager, messageContentExtractor, htmlTextExtractor, messageIdManager,
-            new MemoryMessageFastViewProjection(new NoopMetricFactory()));
+            new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
         messageFastViewFactory = new MessageFastViewFactory(blobManager, messageIdManager, fastViewProjection, messageFullViewFactory);
     }
 
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
index 760d35f..c725d7a 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/message/view/MessageFullViewFactoryTest.java
@@ -68,7 +68,7 @@ import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.TestMessageId;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.ClassLoaderUtils;
 import org.apache.james.util.html.HtmlTextExtractor;
 import org.apache.james.util.mime.MessageContentExtractor;
@@ -118,7 +118,7 @@ class MessageFullViewFactoryTest {
                 .build(ClassLoaderUtils.getSystemResourceAsSharedStream("fullMessage.eml")),
             session);
 
-        fastViewProjection = spy(new MemoryMessageFastViewProjection(new NoopMetricFactory()));
+        fastViewProjection = spy(new MemoryMessageFastViewProjection(new RecordingMetricFactory()));
         messageFullViewFactory = new MessageFullViewFactory(resources.getBlobManager(), messageContentExtractor, htmlTextExtractor,
             messageIdManager,
             fastViewProjection);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
index e407db8..babc63d 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
@@ -55,7 +55,7 @@ import org.apache.james.mailbox.store.FakeAuthenticator;
 import org.apache.james.mailbox.store.FakeAuthorizator;
 import org.apache.james.mailbox.store.SessionProviderImpl;
 import org.apache.james.mailbox.store.StoreMailboxManager;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.util.ClassLoaderUtils;
 import org.apache.james.util.html.HtmlTextExtractor;
@@ -105,7 +105,7 @@ class ComputeMessageFastViewProjectionListenerTest {
         InMemoryIntegrationResources resources = InMemoryIntegrationResources.builder()
             .preProvisionnedFakeAuthenticator()
             .fakeAuthorizator()
-            .eventBus(new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()), RetryBackoffConfiguration.DEFAULT, eventDeadLetters))
+            .eventBus(new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()), RetryBackoffConfiguration.DEFAULT, eventDeadLetters))
             .defaultAnnotationLimits()
             .defaultMessageParser()
             .scanningSearchIndex()
@@ -116,7 +116,7 @@ class ComputeMessageFastViewProjectionListenerTest {
         mailboxManager = resources.getMailboxManager();
         messageIdManager = spy(resources.getMessageIdManager());
 
-        messageFastViewProjection = new MemoryMessageFastViewProjection(new NoopMetricFactory());
+        messageFastViewProjection = new MemoryMessageFastViewProjection(new RecordingMetricFactory());
 
         MessageContentExtractor messageContentExtractor = new MessageContentExtractor();
         HtmlTextExtractor htmlTextExtractor = new JsoupHtmlTextExtractor();
diff --git a/server/protocols/protocols-pop3/pom.xml b/server/protocols/protocols-pop3/pom.xml
index 60c797e..b41c6ed 100644
--- a/server/protocols/protocols-pop3/pom.xml
+++ b/server/protocols/protocols-pop3/pom.xml
@@ -90,6 +90,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/protocols-smtp/pom.xml b/server/protocols/protocols-smtp/pom.xml
index 125125e..548bc12 100644
--- a/server/protocols/protocols-smtp/pom.xml
+++ b/server/protocols/protocols-smtp/pom.xml
@@ -126,6 +126,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
index ac5f4f9..8414b7a 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
@@ -62,7 +62,7 @@ import org.apache.james.mailrepository.memory.MemoryMailRepositoryUrlStore;
 import org.apache.james.mailrepository.memory.TestingMailRepositoryLoader;
 import org.apache.james.metrics.api.Metric;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.protocols.api.utils.ProtocolServerUtils;
 import org.apache.james.protocols.lib.mock.MockProtocolHandlerLoader;
 import org.apache.james.protocols.netty.AbstractChannelPipelineFactory;
@@ -262,7 +262,7 @@ public class SMTPServerTest {
             .put(binder -> binder.bind(MailRepositoryStore.class).toInstance(mailRepositoryStore))
             .put(binder -> binder.bind(DNSService.class).toInstance(dnsServer))
             .put(binder -> binder.bind(UsersRepository.class).toInstance(usersRepository))
-            .put(binder -> binder.bind(MetricFactory.class).to(NoopMetricFactory.class))
+            .put(binder -> binder.bind(MetricFactory.class).to(RecordingMetricFactory.class))
             .build();
     }
 
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
index b7cbf2d..e650611 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
@@ -30,7 +30,7 @@ import javax.mail.internet.MimeMessage;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.MaybeSender;
 import org.apache.james.core.builder.MimeMessageBuilder;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
@@ -125,7 +125,7 @@ public class SpamAssassinHandlerTest {
     public void testNonSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage("test")));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
 
         handler.setSpamdHost(SPAMD_HOST);
         handler.setSpamdPort(spamd.getPort());
@@ -142,7 +142,7 @@ public class SpamAssassinHandlerTest {
     public void testSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
 
         handler.setSpamdHost(SPAMD_HOST);
         handler.setSpamdPort(spamd.getPort());
@@ -158,7 +158,7 @@ public class SpamAssassinHandlerTest {
     public void testSpamReject() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
 
         handler.setSpamdHost(SPAMD_HOST);
         handler.setSpamdPort(spamd.getPort());
diff --git a/server/protocols/webadmin/webadmin-cassandra-data/pom.xml b/server/protocols/webadmin/webadmin-cassandra-data/pom.xml
index 6829b6e..5168932 100644
--- a/server/protocols/webadmin/webadmin-cassandra-data/pom.xml
+++ b/server/protocols/webadmin/webadmin-cassandra-data/pom.xml
@@ -69,6 +69,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/webadmin/webadmin-cassandra/pom.xml b/server/protocols/webadmin/webadmin-cassandra/pom.xml
index a656406..e2187ca 100644
--- a/server/protocols/webadmin/webadmin-cassandra/pom.xml
+++ b/server/protocols/webadmin/webadmin-cassandra/pom.xml
@@ -54,6 +54,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/webadmin/webadmin-core/pom.xml b/server/protocols/webadmin/webadmin-core/pom.xml
index 606ec07..d77687a 100644
--- a/server/protocols/webadmin/webadmin-core/pom.xml
+++ b/server/protocols/webadmin/webadmin-core/pom.xml
@@ -55,6 +55,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-server-task-api</artifactId>
         </dependency>
         <dependency>
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
index 58b4af1..97de868 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminUtils.java
@@ -24,9 +24,8 @@ import static io.restassured.config.EncoderConfig.encoderConfig;
 import static io.restassured.config.RestAssuredConfig.newConfig;
 
 import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
 
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.Port;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 
@@ -43,7 +42,7 @@ public class WebAdminUtils {
         return new WebAdminServer(WebAdminConfiguration.TEST_CONFIGURATION,
             ImmutableList.copyOf(routes),
             new NoAuthenticationFilter(),
-            new NoopMetricFactory());
+            new RecordingMetricFactory());
     }
 
     public static RequestSpecBuilder buildRequestSpecification(WebAdminServer webAdminServer) {
diff --git a/server/protocols/webadmin/webadmin-data/pom.xml b/server/protocols/webadmin/webadmin-data/pom.xml
index fedd3c4..7f3f7e7 100644
--- a/server/protocols/webadmin/webadmin-data/pom.xml
+++ b/server/protocols/webadmin/webadmin-data/pom.xml
@@ -86,6 +86,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
@@ -96,11 +101,6 @@
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
         </dependency>
         <dependency>
             <groupId>io.rest-assured</groupId>
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/pom.xml b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/pom.xml
index c2fc74e..4fa99b4 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/pom.xml
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/pom.xml
@@ -114,6 +114,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
index 6f43b0e..a7457c0 100644
--- a/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox-deleted-message-vault/src/test/java/org/apache/james/webadmin/vault/routes/DeletedMessagesVaultRoutesTest.java
@@ -100,7 +100,7 @@ import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
 import org.apache.james.mailbox.model.SearchQuery;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.task.Hostname;
 import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.user.memory.MemoryUsersRepository;
@@ -176,7 +176,7 @@ class DeletedMessagesVaultRoutesTest {
         blobIdFactory = new HashBlobId.Factory();
         blobStore = spy(new MemoryBlobStore(blobIdFactory));
         clock = new UpdatableTickingClock(OLD_DELETION_DATE.toInstant());
-        vault = spy(new BlobStoreDeletedMessageVault(new NoopMetricFactory(), new MemoryDeletedMessageMetadataVault(),
+        vault = spy(new BlobStoreDeletedMessageVault(new RecordingMetricFactory(), new MemoryDeletedMessageMetadataVault(),
             blobStore, new BucketNameGenerator(clock), clock,
             RetentionConfiguration.DEFAULT));
         InMemoryIntegrationResources inMemoryResource = InMemoryIntegrationResources.defaultResources();
diff --git a/server/protocols/webadmin/webadmin-mailbox/pom.xml b/server/protocols/webadmin/webadmin-mailbox/pom.xml
index f90a0a7..a44a25c 100644
--- a/server/protocols/webadmin/webadmin-mailbox/pom.xml
+++ b/server/protocols/webadmin/webadmin-mailbox/pom.xml
@@ -138,6 +138,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
index 8db4d2c..a3a7a1e 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/EventDeadLettersRoutesTest.java
@@ -49,7 +49,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.store.event.EventFactory;
 import org.apache.james.mailbox.store.quota.DefaultUserQuotaRootResolver;
 import org.apache.james.mailbox.util.EventCollector;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.task.Hostname;
 import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.webadmin.WebAdminServer;
@@ -120,7 +120,7 @@ class EventDeadLettersRoutesTest {
         deadLetters = new MemoryEventDeadLetters();
         JsonTransformer jsonTransformer = new JsonTransformer();
         EventSerializer eventSerializer = new EventSerializer(new InMemoryId.Factory(), new InMemoryMessageId.Factory(), new DefaultUserQuotaRootResolver.DefaultQuotaRootDeserializer());
-        eventBus = new InVMEventBus(new InVmEventDelivery(new NoopMetricFactory()), RetryBackoffConfiguration.DEFAULT, deadLetters);
+        eventBus = new InVMEventBus(new InVmEventDelivery(new RecordingMetricFactory()), RetryBackoffConfiguration.DEFAULT, deadLetters);
         EventDeadLettersRedeliverService redeliverService = new EventDeadLettersRedeliverService(eventBus, deadLetters);
         EventDeadLettersService service = new EventDeadLettersService(redeliverService, deadLetters);
 
diff --git a/server/protocols/webadmin/webadmin-mailqueue/pom.xml b/server/protocols/webadmin/webadmin-mailqueue/pom.xml
index 1bc7d1f..f3beb1a 100644
--- a/server/protocols/webadmin/webadmin-mailqueue/pom.xml
+++ b/server/protocols/webadmin/webadmin-mailqueue/pom.xml
@@ -74,6 +74,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/protocols/webadmin/webadmin-mailrepository/pom.xml b/server/protocols/webadmin/webadmin-mailrepository/pom.xml
index e52a0bb..187e210 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/pom.xml
+++ b/server/protocols/webadmin/webadmin-mailrepository/pom.xml
@@ -96,6 +96,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactoryTest.java b/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactoryTest.java
index e50e9d4..5b1e927 100644
--- a/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactoryTest.java
+++ b/server/queue/queue-activemq/src/test/java/org/apache/james/queue/activemq/ActiveMQMailQueueFactoryTest.java
@@ -24,7 +24,7 @@ import javax.jms.ConnectionFactory;
 import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.activemq.broker.BrokerService;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.queue.api.MailQueueFactory;
 import org.apache.james.queue.api.MailQueueFactoryContract;
 import org.apache.james.queue.api.ManageableMailQueue;
@@ -47,7 +47,7 @@ public class ActiveMQMailQueueFactoryTest {
         public void setUp(BrokerService brokerService) {
             ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?create=false");
             RawMailQueueItemDecoratorFactory mailQueueItemDecoratorFactory = new RawMailQueueItemDecoratorFactory();
-            NoopMetricFactory metricFactory = new NoopMetricFactory();
+            RecordingMetricFactory metricFactory = new RecordingMetricFactory();
             NoopGaugeRegistry gaugeRegistry = new NoopGaugeRegistry();
             mailQueueFactory = new ActiveMQMailQueueFactory(connectionFactory, mailQueueItemDecoratorFactory, metricFactory, gaugeRegistry);
             mailQueueFactory.setUseJMX(false);
@@ -86,7 +86,7 @@ public class ActiveMQMailQueueFactoryTest {
             connectionFactory.setBlobTransferPolicy(policy);
 
             RawMailQueueItemDecoratorFactory mailQueueItemDecoratorFactory = new RawMailQueueItemDecoratorFactory();
-            NoopMetricFactory metricFactory = new NoopMetricFactory();
+            RecordingMetricFactory metricFactory = new RecordingMetricFactory();
             NoopGaugeRegistry gaugeRegistry = new NoopGaugeRegistry();
             mailQueueFactory = new ActiveMQMailQueueFactory(connectionFactory, mailQueueItemDecoratorFactory, metricFactory, gaugeRegistry);
             mailQueueFactory.setUseJMX(false);
diff --git a/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/JMSMailQueueFactoryTest.java b/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/JMSMailQueueFactoryTest.java
index c791d26..f98cf9d 100644
--- a/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/JMSMailQueueFactoryTest.java
+++ b/server/queue/queue-jms/src/test/java/org/apache/james/queue/jms/JMSMailQueueFactoryTest.java
@@ -25,7 +25,7 @@ import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.activemq.broker.BrokerService;
 import org.apache.james.metrics.api.GaugeRegistry;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.queue.api.MailQueueFactory;
 import org.apache.james.queue.api.MailQueueFactoryContract;
 import org.apache.james.queue.api.ManageableMailQueue;
@@ -45,7 +45,7 @@ public class JMSMailQueueFactoryTest implements MailQueueFactoryContract<Managea
     void setUp(BrokerService broker) {
         ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?create=false");
         RawMailQueueItemDecoratorFactory mailQueueItemDecoratorFactory = new RawMailQueueItemDecoratorFactory();
-        NoopMetricFactory metricFactory = new NoopMetricFactory();
+        RecordingMetricFactory metricFactory = new RecordingMetricFactory();
         GaugeRegistry gaugeRegistry = new NoopGaugeRegistry();
         mailQueueFactory = new JMSMailQueueFactory(connectionFactory, mailQueueItemDecoratorFactory, metricFactory, gaugeRegistry);
         mailQueueFactory.setUseJMX(false);
diff --git a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
index a67fd34..0e599f3 100644
--- a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
+++ b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMQMailQueueConfigurationChangeTest.java
@@ -42,7 +42,7 @@ import org.apache.james.blob.cassandra.CassandraBlobStore;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.eventsourcing.eventstore.cassandra.CassandraEventStoreModule;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.queue.api.MailQueue;
 import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.queue.api.RawMailQueueItemDecoratorFactory;
@@ -116,7 +116,7 @@ class RabbitMQMailQueueConfigurationChangeTest {
 
 
         RabbitMQMailQueueFactory.PrivateFactory privateFactory = new RabbitMQMailQueueFactory.PrivateFactory(
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             new NoopGaugeRegistry(),
             rabbitMQExtension.getRabbitChannelPool(),
             mimeMessageStoreFactory,
diff --git a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMqMailQueueFactoryTest.java b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMqMailQueueFactoryTest.java
index 81a5e18..16ab46d 100644
--- a/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMqMailQueueFactoryTest.java
+++ b/server/queue/queue-rabbitmq/src/test/java/org/apache/james/queue/rabbitmq/RabbitMqMailQueueFactoryTest.java
@@ -33,7 +33,7 @@ import org.apache.james.backends.rabbitmq.RabbitMQExtension;
 import org.apache.james.blob.api.HashBlobId;
 import org.apache.james.blob.mail.MimeMessageStore;
 import org.apache.james.metrics.api.NoopGaugeRegistry;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.queue.api.MailQueueFactory;
 import org.apache.james.queue.api.MailQueueFactoryContract;
 import org.apache.james.queue.api.RawMailQueueItemDecoratorFactory;
@@ -67,7 +67,7 @@ class RabbitMqMailQueueFactoryTest implements MailQueueFactoryContract<RabbitMQM
             .build();
 
         RabbitMQMailQueueFactory.PrivateFactory privateFactory = new RabbitMQMailQueueFactory.PrivateFactory(
-            new NoopMetricFactory(),
+            new RecordingMetricFactory(),
             new NoopGaugeRegistry(),
             rabbitMQExtension.getRabbitChannelPool(),
             mimeMessageStoreFactory,
diff --git a/third-party/spamassassin/pom.xml b/third-party/spamassassin/pom.xml
index 4268cab..03a095f 100644
--- a/third-party/spamassassin/pom.xml
+++ b/third-party/spamassassin/pom.xml
@@ -51,6 +51,11 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java
index 7f4b3c2..eee554c 100644
--- a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java
@@ -26,7 +26,7 @@ import java.nio.charset.StandardCharsets;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.james.core.Username;
-import org.apache.james.metrics.api.NoopMetricFactory;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.spamassassin.SpamAssassinExtension.SpamAssassin;
 import org.apache.james.util.MimeMessageUtil;
 import org.apache.mailet.Attribute;
@@ -46,7 +46,7 @@ public class SpamAssassinInvokerTest {
     @BeforeEach
     public void setup(SpamAssassin spamAssassin) throws Exception {
         this.spamAssassin = spamAssassin;
-        testee = new SpamAssassinInvoker(new NoopMetricFactory(), spamAssassin.getIp(), spamAssassin.getBindingPort());
+        testee = new SpamAssassinInvoker(new RecordingMetricFactory(), spamAssassin.getIp(), spamAssassin.getBindingPort());
     }
 
     @Test


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 12/13: JAMES-2991 Full content is required for preview computation

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit ffc5eb962eb6eb4eba5f4c70f26d213b9bcd6db2
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Dec 17 14:04:58 2019 +0700

    JAMES-2991 Full content is required for preview computation
    
    InMemory implementation do not support partial read.
---
 .../james/jmap/event/ComputeMessageFastViewProjectionListener.java      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
index d4e690e..4fe970a 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
@@ -79,7 +79,7 @@ public class ComputeMessageFastViewProjectionListener implements MailboxListener
     }
 
     private void handleAddedEvent(Added addedEvent, MailboxSession session) throws MailboxException {
-        Flux.fromIterable(messageIdManager.getMessages(addedEvent.getMessageIds(), FetchGroup.BODY_CONTENT, session))
+        Flux.fromIterable(messageIdManager.getMessages(addedEvent.getMessageIds(), FetchGroup.FULL_CONTENT, session))
             .flatMap(Throwing.function(messageResult -> Mono.fromCallable(
                 () -> Pair.of(messageResult.getMessageId(), computeFastViewPrecomputedProperties(messageResult)))
                     .subscribeOn(Schedulers.parallel())))


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 06/13: [Refactoring] PreDeleletionHook: Optional MetricFactory

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 6e98527680484570a4c3b0e16d37bff782b2ffef
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Dec 13 17:38:30 2019 +0700

    [Refactoring] PreDeleletionHook: Optional MetricFactory
---
 .../james/mailbox/store/PreDeletionHooks.java       | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/PreDeletionHooks.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/PreDeletionHooks.java
index b868d62..46f6e7a 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/PreDeletionHooks.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/PreDeletionHooks.java
@@ -19,13 +19,13 @@
 
 package org.apache.james.mailbox.store;
 
+import java.util.Optional;
 import java.util.Set;
 
 import javax.inject.Inject;
 
 import org.apache.james.mailbox.extension.PreDeletionHook;
 import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.metrics.api.NoopMetricFactory;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -35,15 +35,19 @@ import reactor.core.scheduler.Schedulers;
 
 public class PreDeletionHooks {
     private static final int CONCURRENCY = 1;
-    public static final PreDeletionHooks NO_PRE_DELETION_HOOK = new PreDeletionHooks(ImmutableSet.of(), new NoopMetricFactory());
+    public static final PreDeletionHooks NO_PRE_DELETION_HOOK = new PreDeletionHooks(ImmutableSet.of(), Optional.empty());
 
     static final String PRE_DELETION_HOOK_METRIC_NAME = "preDeletionHook";
 
     private final Set<PreDeletionHook> hooks;
-    private final MetricFactory metricFactory;
+    private final Optional<MetricFactory> metricFactory;
 
     @Inject
     public PreDeletionHooks(Set<PreDeletionHook> hooks, MetricFactory metricFactory) {
+        this(hooks, Optional.of(metricFactory));
+    }
+
+    private PreDeletionHooks(Set<PreDeletionHook> hooks, Optional<MetricFactory> metricFactory) {
         this.hooks = hooks;
         this.metricFactory = metricFactory;
     }
@@ -51,8 +55,15 @@ public class PreDeletionHooks {
     public Mono<Void> runHooks(PreDeletionHook.DeleteOperation deleteOperation) {
         return Flux.fromIterable(hooks)
             .publishOn(Schedulers.elastic())
-            .flatMap(hook -> metricFactory.runPublishingTimerMetric(PRE_DELETION_HOOK_METRIC_NAME,
-                Mono.from(hook.notifyDelete(deleteOperation))), CONCURRENCY)
+            .flatMap(hook -> metricFactory.map(factory -> publishMetric(deleteOperation, hook, factory))
+                    .orElse(Mono.empty()),
+                CONCURRENCY)
             .then();
     }
+
+    private Mono<Void> publishMetric(PreDeletionHook.DeleteOperation deleteOperation, PreDeletionHook hook, MetricFactory factory) {
+        return factory.runPublishingTimerMetric(
+            PRE_DELETION_HOOK_METRIC_NAME,
+            Mono.from(hook.notifyDelete(deleteOperation)));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 11/13: JAMES-2993 Create a Preview.Factory

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit cd3f6089548b0b1882cfb735121b73bf2c371eb7
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Dec 16 13:55:04 2019 +0700

    JAMES-2993 Create a Preview.Factory
---
 .../org/apache/james/jmap/api/model/Preview.java   |  50 +++++++
 .../MessageFastViewPrecomputedProperties.java      |  28 ++++
 .../ComputeMessageFastViewProjectionListener.java  |  17 +--
 .../MessageFastViewProjectionItemFactoryTest.java  | 144 +++++++++++++++++++++
 .../org/apache/james/jmap/PreviewFactoryTest.java  |  73 +++++++++++
 ...mputeMessageFastViewProjectionListenerTest.java |   3 +-
 .../src/test/resources/inlineAttachment.eml        |  24 ++++
 .../src/test/resources/oneAttachment.eml           |  16 +++
 8 files changed, 341 insertions(+), 14 deletions(-)

diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/Preview.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/Preview.java
index d4f7fb4..42b2428 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/Preview.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/model/Preview.java
@@ -19,15 +19,65 @@
 
 package org.apache.james.jmap.api.model;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
+import javax.inject.Inject;
+
 import org.apache.commons.lang3.StringUtils;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.stream.MimeConfig;
+import org.apache.james.util.html.HtmlTextExtractor;
+import org.apache.james.util.mime.MessageContentExtractor;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 
 public class Preview {
+    public static class Factory {
+        private final MessageContentExtractor messageContentExtractor;
+        private final HtmlTextExtractor htmlTextExtractor;
+
+        @Inject
+        public Factory(MessageContentExtractor messageContentExtractor, HtmlTextExtractor htmlTextExtractor) {
+            this.messageContentExtractor = messageContentExtractor;
+            this.htmlTextExtractor = htmlTextExtractor;
+        }
+
+        public Preview fromMessageResult(MessageResult messageResult) throws MailboxException, IOException {
+            try (InputStream inputStream = messageResult.getFullContent().getInputStream()) {
+                return fromInputStream(inputStream);
+            }
+        }
+
+        public Preview fromMessageAsString(String messageAsString) throws IOException {
+            return fromInputStream(new ByteArrayInputStream(messageAsString.getBytes(StandardCharsets.UTF_8)));
+        }
+
+        private Preview fromInputStream(InputStream inputStream) throws IOException {
+            return fromMime4JMessage(parse(inputStream));
+        }
+
+        private Preview fromMime4JMessage(Message mimeMessage) throws IOException {
+            MessageContentExtractor.MessageContent messageContent = messageContentExtractor.extract(mimeMessage);
+            return messageContent.extractMainTextContent(htmlTextExtractor)
+                .map(Preview::compute)
+                .orElse(Preview.EMPTY);
+        }
+
+        private Message parse(InputStream inputStream) throws IOException {
+            return Message.Builder.of()
+                .use(MimeConfig.PERMISSIVE)
+                .parse(inputStream)
+                .build();
+        }
+    }
 
     public static final Preview EMPTY = Preview.from("");
 
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/MessageFastViewPrecomputedProperties.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/MessageFastViewPrecomputedProperties.java
index 997ad66..f3dbe8b 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/MessageFastViewPrecomputedProperties.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/projections/MessageFastViewPrecomputedProperties.java
@@ -19,9 +19,16 @@
 
 package org.apache.james.jmap.api.projections;
 
+import java.io.IOException;
+import java.util.List;
 import java.util.Objects;
 
+import javax.inject.Inject;
+
 import org.apache.james.jmap.api.model.Preview;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.MessageAttachment;
+import org.apache.james.mailbox.model.MessageResult;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
@@ -66,6 +73,27 @@ public class MessageFastViewPrecomputedProperties {
         return preview -> hasAttachment -> new Builder.FinalStage(preview, hasAttachment);
     }
 
+    public static class Factory {
+        private final Preview.Factory previewFactory;
+
+        @Inject
+        public Factory(Preview.Factory previewFactory) {
+            this.previewFactory = previewFactory;
+        }
+
+        public MessageFastViewPrecomputedProperties from(MessageResult messageResult) throws MailboxException, IOException {
+            return builder()
+                .preview(previewFactory.fromMessageResult(messageResult))
+                .hasAttachment(hasAttachment(messageResult.getLoadedAttachments()))
+                .build();
+        }
+
+        private boolean hasAttachment(List<MessageAttachment> attachments) {
+            return attachments.stream()
+                .anyMatch(attachment -> !attachment.isInlinedWithCid());
+        }
+    }
+
     private final Preview preview;
     private final boolean hasAttachment;
 
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
index 87ce35f..d4e690e 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListener.java
@@ -24,11 +24,8 @@ import java.io.IOException;
 import javax.inject.Inject;
 
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.james.jmap.api.model.Preview;
 import org.apache.james.jmap.api.projections.MessageFastViewPrecomputedProperties;
 import org.apache.james.jmap.api.projections.MessageFastViewProjection;
-import org.apache.james.jmap.draft.model.message.view.MessageFullView;
-import org.apache.james.jmap.draft.model.message.view.MessageFullViewFactory;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageIdManager;
 import org.apache.james.mailbox.SessionProvider;
@@ -38,7 +35,6 @@ import org.apache.james.mailbox.events.MailboxListener;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.FetchGroup;
 import org.apache.james.mailbox.model.MessageResult;
-import org.parboiled.common.ImmutableList;
 
 import com.github.fge.lambdas.Throwing;
 import com.google.common.annotations.VisibleForTesting;
@@ -57,16 +53,16 @@ public class ComputeMessageFastViewProjectionListener implements MailboxListener
     private final MessageIdManager messageIdManager;
     private final MessageFastViewProjection messageFastViewProjection;
     private final SessionProvider sessionProvider;
-    private final MessageFullViewFactory messageFullViewFactory;
+    private final MessageFastViewPrecomputedProperties.Factory messageFastViewPrecomputedPropertiesFactory;
 
     @Inject
     public ComputeMessageFastViewProjectionListener(SessionProvider sessionProvider, MessageIdManager messageIdManager,
                                                     MessageFastViewProjection messageFastViewProjection,
-                                                    MessageFullViewFactory messageFullViewFactory) {
+                                                    MessageFastViewPrecomputedProperties.Factory messageFastViewPrecomputedPropertiesFactory) {
         this.sessionProvider = sessionProvider;
         this.messageIdManager = messageIdManager;
         this.messageFastViewProjection = messageFastViewProjection;
-        this.messageFullViewFactory = messageFullViewFactory;
+        this.messageFastViewPrecomputedPropertiesFactory = messageFastViewPrecomputedPropertiesFactory;
     }
 
     @Override
@@ -95,11 +91,6 @@ public class ComputeMessageFastViewProjectionListener implements MailboxListener
 
     @VisibleForTesting
     MessageFastViewPrecomputedProperties computeFastViewPrecomputedProperties(MessageResult messageResult) throws MailboxException, IOException {
-        MessageFullView message = messageFullViewFactory.fromMessageResults(ImmutableList.of(messageResult));
-
-        return MessageFastViewPrecomputedProperties.builder()
-            .preview(Preview.from(message.getPreview().getValue()))
-            .hasAttachment(message.isHasAttachment())
-            .build();
+        return messageFastViewPrecomputedPropertiesFactory.from(messageResult);
     }
 }
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/MessageFastViewProjectionItemFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/MessageFastViewProjectionItemFactoryTest.java
new file mode 100644
index 0000000..84fe433
--- /dev/null
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/MessageFastViewProjectionItemFactoryTest.java
@@ -0,0 +1,144 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.Username;
+import org.apache.james.jmap.api.model.Preview;
+import org.apache.james.jmap.api.projections.MessageFastViewPrecomputedProperties;
+import org.apache.james.jmap.draft.utils.JsoupHtmlTextExtractor;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.ComposedMessageId;
+import org.apache.james.mailbox.model.FetchGroup;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.util.ClassLoaderUtils;
+import org.apache.james.util.mime.MessageContentExtractor;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class MessageFastViewProjectionItemFactoryTest {
+    public static final Username BOB = Username.of("bob");
+    MessageFastViewPrecomputedProperties.Factory testee;
+    MailboxManager mailboxManager;
+    MailboxSession session;
+    MessageManager mailbox;
+
+    @BeforeEach
+    void setUp() throws Exception {
+        testee = new MessageFastViewPrecomputedProperties.Factory(
+            new Preview.Factory(new MessageContentExtractor(), new JsoupHtmlTextExtractor()));
+        mailboxManager = InMemoryIntegrationResources.defaultResources().getMailboxManager();
+        session = mailboxManager.createSystemSession(BOB);
+        MailboxId mailboxId = mailboxManager.createMailbox(MailboxPath.inbox(BOB), session).get();
+        mailbox = mailboxManager.getMailbox(mailboxId, session);
+    }
+
+    @Test
+    void fromShouldReturnEmptyWhenNoBodyPart() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult("header: value\r\n"));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.EMPTY)
+                .hasAttachment(false)
+                .build());
+    }
+
+    @Test
+    void fromShouldReturnEmptyWhenEmptyBodyPart() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult("header: value\r\n\r\n"));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.EMPTY)
+                .hasAttachment(false)
+                .build());
+    }
+
+    @Test
+    void fromShouldReturnEmptyWhenBlankBodyPart() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult("header: value\r\n\r\n  \r\n  \r\n"));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.EMPTY)
+                .hasAttachment(false)
+                .build());
+    }
+
+    @Test
+    void fromShouldReturnSanitizedBodyTextValue() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult("header: value\r\n\r\n  \r\nmessage  \r\n"));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.from("message"))
+                .hasAttachment(false)
+                .build());
+    }
+
+    @Test
+    void fromShouldExtractHtml() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult(ClassLoaderUtils.getSystemResourceAsString("fullMessage.eml")));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.from("blabla bloblo"))
+                .hasAttachment()
+                .build());
+    }
+
+    @Test
+    void fromShouldParseAttachmentWhenOnlyAttachment() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult(ClassLoaderUtils.getSystemResourceAsString("oneAttachment.eml")));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.EMPTY)
+                .hasAttachment()
+                .build());
+    }
+
+    @Test
+    void fromShouldIngnoreAttachmentsWhenInlined() throws Exception {
+        MessageFastViewPrecomputedProperties actual = testee.from(toMessageResult(ClassLoaderUtils.getSystemResourceAsString("inlineAttachment.eml")));
+
+        assertThat(actual)
+            .isEqualTo(MessageFastViewPrecomputedProperties.builder()
+                .preview(Preview.from("I'm the body!"))
+                .hasAttachment(false)
+                .build());
+    }
+
+    MessageResult toMessageResult(String messageAsString) throws Exception {
+        ComposedMessageId composedMessageId = mailbox.appendMessage(MessageManager.AppendCommand.builder()
+            .build(messageAsString), session);
+
+        return mailbox.getMessages(MessageRange.one(composedMessageId.getUid()), FetchGroup.FULL_CONTENT, session)
+            .next();
+    }
+}
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/PreviewFactoryTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/PreviewFactoryTest.java
new file mode 100644
index 0000000..f55ff31
--- /dev/null
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/PreviewFactoryTest.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.jmap.api.model.Preview;
+import org.apache.james.jmap.draft.utils.JsoupHtmlTextExtractor;
+import org.apache.james.util.ClassLoaderUtils;
+import org.apache.james.util.mime.MessageContentExtractor;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class PreviewFactoryTest {
+    Preview.Factory testee;
+
+    @BeforeEach
+    void setUp() {
+        testee = new Preview.Factory(new MessageContentExtractor(), new JsoupHtmlTextExtractor());
+    }
+
+    @Test
+    void fromMessageAsStringShouldReturnEmptyWhenNoBodyPart() throws Exception {
+        Preview actual = testee.fromMessageAsString("header: value\r\n");
+
+        assertThat(actual).isEqualTo(Preview.EMPTY);
+    }
+
+    @Test
+    void fromMessageAsStringShouldReturnEmptyWhenEmptyBodyPart() throws Exception {
+        Preview actual = testee.fromMessageAsString("header: value\r\n\r\n");
+
+        assertThat(actual).isEqualTo(Preview.EMPTY);
+    }
+
+    @Test
+    void fromMessageAsStringShouldReturnEmptyWhenBlankBodyPart() throws Exception {
+        Preview actual = testee.fromMessageAsString("header: value\r\n\r\n  \r\n  \r\n");
+
+        assertThat(actual).isEqualTo(Preview.EMPTY);
+    }
+
+    @Test
+    void fromMessageAsStringShouldReturnSanitizedBodyTextValue() throws Exception {
+        Preview actual = testee.fromMessageAsString("header: value\r\n\r\n  \r\nmessage  \r\n");
+
+        assertThat(actual).isEqualTo(Preview.from("message"));
+    }
+
+    @Test
+    void fromMessageAsStringShouldExtractHtml() throws Exception {
+        Preview actual = testee.fromMessageAsString(ClassLoaderUtils.getSystemResourceAsString("fullMessage.eml"));
+
+        assertThat(actual).isEqualTo(Preview.from("blabla bloblo"));
+    }
+}
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
index babc63d..aa20d96 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/event/ComputeMessageFastViewProjectionListenerTest.java
@@ -129,7 +129,8 @@ class ComputeMessageFastViewProjectionListenerTest {
         SessionProviderImpl sessionProvider = new SessionProviderImpl(authenticator, FakeAuthorizator.defaultReject());
 
         listener = spy(new ComputeMessageFastViewProjectionListener(sessionProvider, messageIdManager,
-            messageFastViewProjection, messageFullViewFactory));
+            messageFastViewProjection,
+            new MessageFastViewPrecomputedProperties.Factory(new Preview.Factory(messageContentExtractor, htmlTextExtractor))));
 
         resources.getEventBus().register(listener);
 
diff --git a/server/protocols/jmap-draft/src/test/resources/inlineAttachment.eml b/server/protocols/jmap-draft/src/test/resources/inlineAttachment.eml
new file mode 100644
index 0000000..79e4c11
--- /dev/null
+++ b/server/protocols/jmap-draft/src/test/resources/inlineAttachment.eml
@@ -0,0 +1,24 @@
+To: me@linagora.com
+From: Benoit Tellier <me...@linagora.com>
+Subject: Mail with text attachment
+Message-ID: <be...@any.com>
+Date: Thu, 13 Oct 2016 10:26:20 +0200
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="------------4FD2D252DB453546C22C25B2"
+
+This is a multi-part message in MIME format.
+--------------4FD2D252DB453546C22C25B2
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+
+I'm the body!
+
+--------------4FD2D252DB453546C22C25B2
+Content-Disposition: inline
+Content-Type: text/plain; charset=UTF-8;
+ name="attachment.txt"
+Content-ID: <id>
+
+I'm a Schroedinger cat
+--------------4FD2D252DB453546C22C25B2--
diff --git a/server/protocols/jmap-draft/src/test/resources/oneAttachment.eml b/server/protocols/jmap-draft/src/test/resources/oneAttachment.eml
new file mode 100644
index 0000000..3c422f9
--- /dev/null
+++ b/server/protocols/jmap-draft/src/test/resources/oneAttachment.eml
@@ -0,0 +1,16 @@
+Return-Path: <ch...@apache.org>
+Subject: 29989 btellier
+From: <an...@mail.com>
+Content-Disposition: attachment
+MIME-Version: 1.0
+Date: Sun, 02 Apr 2017 22:09:04 -0000
+Content-Type: application/zip; name="9559333830.zip"
+To: <ch...@apache.org>
+Message-ID: <14...@any.com>
+Content-Transfer-Encoding: base64
+
+UEsDBBQAAgAIAEQeg0oN2YT/EAsAAMsWAAAIABwAMjIwODUuanNVVAkAAxBy4VgQcuFYdXgLAAEE
+AAAAAAQAAAAApZhbi1zHFYWfY/B/MP3i7kwj1/2CokAwBPIQ+sGPkgJ1tURkdeiMbYzQf8+3q8+M
+ZmQllgn2aHrqnNq1L2uvtavnj2/b7evz26/Op5M6q/P+8OUX77784g8/lQtLisXTU/68vfzCv/Lg
+D9vqs/3b8fNXf92273ey4XTCykk9w9LpfD7tX+zGzU83b8pPg39uBr/Kmxe7w9PLuP3xwpFKTJ32
+AAEEAAAAAAQAAAAAUEsFBgAAAAABAAEATgAAAFILAAAAAA==


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 04/13: [Refactoring] use DropWizardMetric in Spring

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 2e9ce57ca809e369bf061252383ca45f8a989f5d
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Dec 13 17:01:40 2019 +0700

    [Refactoring] use DropWizardMetric in Spring
---
 mailbox/spring/pom.xml                                        | 4 ++++
 mailbox/spring/src/test/resources/META-INF/spring/metrics.xml | 5 ++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/mailbox/spring/pom.xml b/mailbox/spring/pom.xml
index 49f2e97..998bf28 100644
--- a/mailbox/spring/pom.xml
+++ b/mailbox/spring/pom.xml
@@ -76,6 +76,10 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>metrics-logger</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml b/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
index 83c8d78..159a9f9 100644
--- a/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
+++ b/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
@@ -22,6 +22,9 @@
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-    <bean id="metricFactory" class="org.apache.james.metrics.api.NoopMetricFactory"/>
+    <bean id="metricRegistry" class="com.codahale.metrics.MetricRegistry" />
+    <bean id="metricFactory" class="org.apache.james.metrics.dropwizard.DropWizardMetricFactory">
+        <constructor-arg index="0" ref="metricRegistry"/>
+    </bean>
 
 </beans>
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 13/13: JAMES-2919 MessageFastView projection changelog entry

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 9638ef45b2ad4f6732cb7945f001ccc54ef64116
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Tue Dec 17 15:08:25 2019 +0700

    JAMES-2919 MessageFastView projection changelog entry
---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2860550..667b0c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ of tasks being currently executed.
 - By default the cassandra keyspace creation by James is now disabled by default. This allow to have credentials limited to a keyspace. It can be enabled by setting cassandra.keyspace.create=true in the cassandra.properties file.
 - Usernames are assumed to be always lower cased. Many users recently complained about mails non received when sending to upper cased local recipients. We decided to simplify the handling of case for local recipients and users by always storing them lower cased.
 - Unhealthy health checks now return HTTP 503 instead of 500, degraded now returns 200 instead of 500. See JAMES-2576.
+- In order to fasten JMAP-draft message retrieval upon calls on properties expected to be fast to fetch, we now compute the preview and hasAttachment properties asynchronously and persist them in Cassandra to improve performance. See JAMES-2919.
 
 ### Fixed
 - JAMES-2828 & JAMES-2929 bugs affecting JDBCMailRepository usage with PostgresSQL thanks to Jörg Thomas & Sergey B


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 05/13: [Refactoring] Spring: Replacing NoopMetricFactory by RecordingMetricFactory

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit a36539ecca60e95aa24597cc32ca739e7abb18d7
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Fri Dec 13 17:27:44 2019 +0700

    [Refactoring] Spring: Replacing NoopMetricFactory by RecordingMetricFactory
---
 mailbox/spring/pom.xml                                        | 3 ++-
 mailbox/spring/src/test/resources/META-INF/spring/metrics.xml | 5 +----
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/mailbox/spring/pom.xml b/mailbox/spring/pom.xml
index 998bf28..df883f2 100644
--- a/mailbox/spring/pom.xml
+++ b/mailbox/spring/pom.xml
@@ -76,7 +76,8 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
-            <artifactId>metrics-logger</artifactId>
+            <artifactId>metrics-tests</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
diff --git a/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml b/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
index 159a9f9..4576596 100644
--- a/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
+++ b/mailbox/spring/src/test/resources/META-INF/spring/metrics.xml
@@ -22,9 +22,6 @@
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
-    <bean id="metricRegistry" class="com.codahale.metrics.MetricRegistry" />
-    <bean id="metricFactory" class="org.apache.james.metrics.dropwizard.DropWizardMetricFactory">
-        <constructor-arg index="0" ref="metricRegistry"/>
-    </bean>
+    <bean id="metricFactory" class="org.apache.james.metrics.tests.RecordingMetricFactory" />
 
 </beans>
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 09/13: [Refactoring] Drop NoopMetricFactory

Posted by bt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit b448717080c1dcefb8788f522c22b58f5568b0c0
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Mon Dec 16 10:37:48 2019 +0700

    [Refactoring] Drop NoopMetricFactory
---
 .../james/metrics/api/NoopMetricFactory.java       | 66 ----------------------
 1 file changed, 66 deletions(-)

diff --git a/metrics/metrics-api/src/main/java/org/apache/james/metrics/api/NoopMetricFactory.java b/metrics/metrics-api/src/main/java/org/apache/james/metrics/api/NoopMetricFactory.java
deleted file mode 100644
index 446af5a..0000000
--- a/metrics/metrics-api/src/main/java/org/apache/james/metrics/api/NoopMetricFactory.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.metrics.api;
-
-public class NoopMetricFactory implements MetricFactory {
-
-    @Override
-    public Metric generate(String name) {
-        return new NoopMetric();
-    }
-
-    public static class NoopMetric implements Metric  {
-
-        @Override
-        public void increment() {
-        }
-
-        @Override
-        public void decrement() {
-        }
-
-        @Override
-        public void add(int value) {
-        }
-
-        @Override
-        public void remove(int value) {
-        }
-    }
-
-    @Override
-    public TimeMetric timer(String name) {
-        return new NoopTimeMetric();
-    }
-
-    public static class NoopTimeMetric implements TimeMetric {
-
-        @Override
-        public String name() {
-            return "";
-        }
-
-
-        @Override
-        public long stopAndPublish() {
-            return 0;
-        }
-    }
-
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org