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 2020/04/07 08:01:25 UTC

[james-project] branch master updated (30fb436 -> e2596a7)

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 30fb436  [Refactoring] Rely of CassandraVersionManager instead of its DAO
     new 4a60093  [ADR] Cassandra Blob store cache
     new ca88636  [ADR] Accept Message and mailbox counter consistency solving ADRs
     new adc399b  [ADR] Removing a configured additional MailboxListener
     new 19a35e0  [ADR] Event bus errors upon dispatch
     new a3e2064  [ADR] Recompute mailbox quotas
     new 488ebd2  JAMES-3078 JMAP Get/Set filter should be reactive
     new e2596a7  [Enhencement] Add glowroot pugins

The 7 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:
 .../destination/glowroot/plugins/jmap.json         | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../destination/glowroot/plugins/smtp.json         | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../destination/glowroot/plugins/task.json         | 19 +++++++
 .../destination/glowroot/plugins/jmap.json         | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../destination/glowroot/plugins/smtp.json         | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../destination/glowroot/plugins/task.json         | 19 +++++++
 .../destination/glowroot/plugins/jmap.json         | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../destination/glowroot/plugins/smtp.json         | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../destination/glowroot/plugins/task.json         | 19 +++++++
 .../destination/glowroot/plugins/jmap.json         | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../destination/glowroot/plugins/smtp.json         | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../destination/glowroot/plugins/task.json         | 19 +++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ---------
 .../destination/glowroot/plugins/imap.json         | 19 -------
 .../destination/glowroot/plugins/smtp.json         | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../destination/glowroot/plugins/task.json         | 19 +++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ---------
 .../jpa/destination/glowroot/plugins/jmap.json     | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../jpa/destination/glowroot/plugins/smtp.json     | 19 +++++++
 .../jpa/destination/glowroot/plugins/spooler.json  | 26 +++++++++
 .../jpa/destination/glowroot/plugins/task.json     | 19 +++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ---------
 .../memory/destination/glowroot/plugins/jmap.json  | 19 +++++++
 .../glowroot/plugins/mailboxListener.json          | 19 +++++++
 .../memory/destination/glowroot/plugins/smtp.json  | 19 +++++++
 .../destination/glowroot/plugins/spooler.json      | 26 +++++++++
 .../memory/destination/glowroot/plugins/task.json  | 19 +++++++
 .../jmap/api/filtering/FilteringManagement.java    | 10 ++--
 .../impl/EventSourcingFilteringManagement.java     |  4 +-
 .../api/filtering/FilteringManagementContract.java | 21 +++----
 .../james/jmap/draft/methods/GetFilterMethod.java  | 33 +++++------
 .../james/jmap/draft/methods/SetFilterMethod.java  | 55 ++++++++++--------
 .../jmap/mailet/filter/JMAPFilteringExtension.java |  4 +-
 .../jmap/mailet/filter/JMAPFilteringTest.java      | 30 +++++-----
 src/adr/0022-cassandra-message-inconsistency.md    |  2 +-
 ...3-cassandra-mailbox-counters-inconsistencies.md |  2 +-
 src/adr/0025-cassandra-blob-store-cache.md         | 66 ++++++++++++++++++++++
 ...oving-configured-additional-mailboxListeners.md | 40 +++++++++++++
 .../0027-eventBus-error-handling-upon-dispatch.md  | 33 +++++++++++
 src/adr/0028-Recompute-mailbox-quotas.md           | 47 +++++++++++++++
 50 files changed, 944 insertions(+), 176 deletions(-)
 create mode 100644 dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/task.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/task.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/task.json
 create mode 100644 dockerfiles/run/guice/cassandra/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/cassandra/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/cassandra/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/cassandra/destination/glowroot/plugins/task.json
 delete mode 100644 dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/blobstore.json
 delete mode 100644 dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/imap.json
 create mode 100644 dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/task.json
 delete mode 100644 dockerfiles/run/guice/jpa/destination/glowroot/plugins/blobstore.json
 create mode 100644 dockerfiles/run/guice/jpa/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/jpa/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/jpa/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/jpa/destination/glowroot/plugins/task.json
 delete mode 100644 dockerfiles/run/guice/memory/destination/glowroot/plugins/blobstore.json
 create mode 100644 dockerfiles/run/guice/memory/destination/glowroot/plugins/jmap.json
 create mode 100644 dockerfiles/run/guice/memory/destination/glowroot/plugins/mailboxListener.json
 create mode 100644 dockerfiles/run/guice/memory/destination/glowroot/plugins/smtp.json
 create mode 100644 dockerfiles/run/guice/memory/destination/glowroot/plugins/task.json
 create mode 100644 src/adr/0025-cassandra-blob-store-cache.md
 create mode 100644 src/adr/0026-removing-configured-additional-mailboxListeners.md
 create mode 100644 src/adr/0027-eventBus-error-handling-upon-dispatch.md
 create mode 100644 src/adr/0028-Recompute-mailbox-quotas.md


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


[james-project] 01/07: [ADR] Cassandra Blob store cache

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 4a60093e2b4d92ee75df23a4054500dfe33f9529
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Apr 3 11:58:48 2020 +0700

    [ADR] Cassandra Blob store cache
---
 src/adr/0025-cassandra-blob-store-cache.md | 66 ++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/src/adr/0025-cassandra-blob-store-cache.md b/src/adr/0025-cassandra-blob-store-cache.md
new file mode 100644
index 0000000..40a25f1
--- /dev/null
+++ b/src/adr/0025-cassandra-blob-store-cache.md
@@ -0,0 +1,66 @@
+# 25. Cassandra Blob Store Cache
+
+Date: 2020-04-03
+
+## Status
+
+Proposed
+
+Supercedes [14. Add storage policies for BlobStore](0014-blobstore-storage-policies.md)
+
+## Context
+
+James exposes a simple BlobStore API for storing raw data. However such raw data often vary in size and access patterns.
+
+As an example:
+
+ - Mailbox message headers are expected to be small and frequently accessed
+ - Mailbox message body are expected to have sizes ranging from small to big but are unfrequently accessed
+ - DeletedMessageVault message headers are expected to be small and unfrequently accessed
+
+The access pattern of some of these kind of blobs does not fit Object Storage characteristics: good at storing big blobs, but 
+it induces high latencies for reading small blobs. We observe latencies of around 50-100ms while Cassandra latency is of 4ms.
+
+This gets some operations slow (for instance IMAP FETCH headers, or listing JMAP messages).
+
+## Decision
+
+Implement a write through cache to have better read latency for smaller objects.
+
+Such a cache needs to be distributed in order to be more efficient.
+
+Given that we don't want to introduce new technologies, we will implement it using Cassandra.
+
+The cache should be implemented as a key-value table on a dedicated 'cache' keyspace, with a replication factor of 1, 
+and be queried with a consistency level of ONE. 
+
+We will leverage a configurable TTL as an eviction policy. Cache will be populated upon writes and missed read, if the 
+blob size is below a configurable threashold. We will use the TimeWindow compaction strategy.
+
+Failure to read the cache, or cache miss will result in a read in the object storage.
+
+## Consequences
+
+Metadata queries are expected not to query the object storage anymore.
+
+[Performance tests](https://github.com/linagora/james-project/pull/3031#issuecomment-572865478) proved such strategies
+to be highly effective. We expect comparable performance improvements compared to an un-cached ObjectStorage blob store.
+
+HybridBlobStore should be removed.
+
+## Alternatives
+
+[14. Add storage policies for BlobStore](0014-blobstore-storage-policies.md) proposes to use the CassandraBlobStore to
+mimic a cache.
+
+This solution needed further work as we decided to add an option to write all blobs to the object storage in order:
+ - To get a centralized source of truth
+ - Being able to instantly rollback Hybrid blob store adoption
+ 
+See [this pull request](https://github.com/linagora/james-project/pull/3162)
+
+With such a proposal there is no eviction policy. Also, the storage is done on the main keyspace with a high replication
+factor, and QUORUM consistency level (high cost).
+
+To be noted, as cached entries are small, we can assume they are small enough to fit in a single Cassandra row. This is more 
+optimized than the large blob handling through blobParts the CassandraBlobStore is doing.


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


[james-project] 02/07: [ADR] Accept Message and mailbox counter consistency solving ADRs

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 ca88636f96f5590d26eb0746cb858f2887710aff
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Apr 3 12:01:34 2020 +0700

    [ADR] Accept Message and mailbox counter consistency solving ADRs
---
 src/adr/0022-cassandra-message-inconsistency.md            | 2 +-
 src/adr/0023-cassandra-mailbox-counters-inconsistencies.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/adr/0022-cassandra-message-inconsistency.md b/src/adr/0022-cassandra-message-inconsistency.md
index 8634048..ac366a7 100644
--- a/src/adr/0022-cassandra-message-inconsistency.md
+++ b/src/adr/0022-cassandra-message-inconsistency.md
@@ -4,7 +4,7 @@ Date: 2020-02-27
 
 ## Status
 
-Proposed
+Accepted (lazy consensus)
 
 ## Context
 
diff --git a/src/adr/0023-cassandra-mailbox-counters-inconsistencies.md b/src/adr/0023-cassandra-mailbox-counters-inconsistencies.md
index 377ff17..0ca1195 100644
--- a/src/adr/0023-cassandra-mailbox-counters-inconsistencies.md
+++ b/src/adr/0023-cassandra-mailbox-counters-inconsistencies.md
@@ -4,7 +4,7 @@ Date: 2020-03-07
 
 ## Status
 
-Proposed
+Accepted (lazy consensus)
 
 ## Context
 


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


[james-project] 05/07: [ADR] Recompute mailbox quotas

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 a3e2064a0f04e0846b1d051b75271b7f7aa493f9
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Apr 3 12:36:30 2020 +0700

    [ADR] Recompute mailbox quotas
---
 src/adr/0028-Recompute-mailbox-quotas.md | 47 ++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/src/adr/0028-Recompute-mailbox-quotas.md b/src/adr/0028-Recompute-mailbox-quotas.md
new file mode 100644
index 0000000..16182cd
--- /dev/null
+++ b/src/adr/0028-Recompute-mailbox-quotas.md
@@ -0,0 +1,47 @@
+# 28. Recompute mailbox quotas
+
+Date: 2020-04-03
+
+## Status
+
+Accepted (lazy consensus)
+
+## Context
+
+JMAP custom quota extension, as well as IMAP [RFC-2087](https://tools.ietf.org/html/rfc2087) enables a user to monitor
+the amount of space and message count he is allowed to use, and that he is effectively using.
+
+To track the quota values a user is effectively using, James relies on the 
+[eventBus](../site/markdown/server/manage-guice-distributed-james.md#mailbox-event-bus) to increment a Cassandra counter
+corresponding to this user.
+
+However, upon Cassandra failure, this value can be incorrect, hence the need of correcting it.
+
+## Data model details
+
+Table: imapUidTable: Holds mailbox and flags for each message, lookup by message ID
+
+Table: messageV2: Holds message metadata, independently of any mailboxes. Content of messages is stored in `blobs` 
+       and `blobparts` tables.
+       
+Table: currentQuota: Holds per quota-root current values. Quota-roots defines groups of mailboxes which share quotas 
+limitations.
+
+Operation:
+ - Quota updates are done asynchronously (event bus + listener) for successful mailbox operations.
+   - If the quota update is not applied, then we are inconsistent
+   - EventBus errors are retried upon errors, counters being non-indempotent, this can result in inconsistent quotas
+
+## Decision
+
+We will implement a generic corrective task exposed via webadmin.
+
+This task can reuse the `CurrentQuotaCalculator` and call it for each and every quotaRoot of each user.
+
+This way, non-Cassandra implementation will also benefit from this task.
+
+## Consequences
+
+This task is not concurrent-safe. Concurrent operations will result in an invalid quota to be persisted.
+
+However, as the source of truth is not altered, re-running this task will eventually return the correct result.
\ 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] 07/07: [Enhencement] Add glowroot pugins

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 e2596a7f044ad1b449489214b6db4815a092d208
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Apr 6 11:25:50 2020 +0700

    [Enhencement] Add glowroot pugins
    
    Added pluging:
     - SMTP: Allow review of incoming SMTP traffic, with a per-command analysis
     - JMAP: Allow review per method
    
    Because so far JMAP relies on HTTP plugin, all method calls are presented under the same web transaction
    which prevent us from doing a in depth per method review.
    
    This new JMAP plugin aims at enhancing this.
    
     - MailboxListener: monitor per mailbox listener consumed resources
     - Task: Allow a per task performance analysis
    
    Enhenced plugins:
     - Spooler: add recording per Mailet / Matcher to contextualize more spooler statistics
---
 .../destination/glowroot/plugins/jmap.json         | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../destination/glowroot/plugins/smtp.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../destination/glowroot/plugins/task.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/jmap.json         | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../destination/glowroot/plugins/smtp.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../destination/glowroot/plugins/task.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/jmap.json         | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../destination/glowroot/plugins/smtp.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../destination/glowroot/plugins/task.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/jmap.json         | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../destination/glowroot/plugins/smtp.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../destination/glowroot/plugins/task.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ----------------------
 .../destination/glowroot/plugins/imap.json         | 19 ----------------
 .../destination/glowroot/plugins/smtp.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../destination/glowroot/plugins/task.json         | 19 ++++++++++++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ----------------------
 .../jpa/destination/glowroot/plugins/jmap.json     | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../jpa/destination/glowroot/plugins/smtp.json     | 19 ++++++++++++++++
 .../jpa/destination/glowroot/plugins/spooler.json  | 26 ++++++++++++++++++++++
 .../jpa/destination/glowroot/plugins/task.json     | 19 ++++++++++++++++
 .../destination/glowroot/plugins/blobstore.json    | 26 ----------------------
 .../memory/destination/glowroot/plugins/jmap.json  | 19 ++++++++++++++++
 .../glowroot/plugins/mailboxListener.json          | 19 ++++++++++++++++
 .../memory/destination/glowroot/plugins/smtp.json  | 19 ++++++++++++++++
 .../destination/glowroot/plugins/spooler.json      | 26 ++++++++++++++++++++++
 .../memory/destination/glowroot/plugins/task.json  | 19 ++++++++++++++++
 37 files changed, 676 insertions(+), 97 deletions(-)

diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/cassandra/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/blobstore.json b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/blobstore.json
deleted file mode 100644
index 84291c6..0000000
--- a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/blobstore.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "name": "BlobStore Plugin",
-  "id": "blob_store",
-  "instrumentation": [
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putDirectly",
-      "methodParameterTypes": [
-        ".."
-      ]
-    },
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putAndComputeId",
-      "methodParameterTypes": [
-        ".."
-      ]
-    }
-  ]
-}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/imap.json b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/imap.json
deleted file mode 100644
index d27904f..0000000
--- a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/imap.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "name": "IMAP Plugin",
-  "id": "imap",
-  "instrumentation": [
-    {
-      "className": "org.apache.james.imap.processor.base.AbstractChainedProcessor",
-      "methodName": "doProcess",
-      "methodParameterTypes": [
-        ".."
-      ],
-      "captureKind": "transaction",
-      "transactionType": "IMAP",
-      "transactionNameTemplate": "IMAP processor : {{this.class.name}}",
-      "alreadyInTransactionBehavior": "capture-trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "imapProcessor"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/jpa-smtp/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/blobstore.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/blobstore.json
deleted file mode 100644
index 84291c6..0000000
--- a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/blobstore.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "name": "BlobStore Plugin",
-  "id": "blob_store",
-  "instrumentation": [
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putDirectly",
-      "methodParameterTypes": [
-        ".."
-      ]
-    },
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putAndComputeId",
-      "methodParameterTypes": [
-        ".."
-      ]
-    }
-  ]
-}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/jpa/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/jpa/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/blobstore.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/blobstore.json
deleted file mode 100644
index 84291c6..0000000
--- a/dockerfiles/run/guice/memory/destination/glowroot/plugins/blobstore.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "name": "BlobStore Plugin",
-  "id": "blob_store",
-  "instrumentation": [
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putDirectly",
-      "methodParameterTypes": [
-        ".."
-      ]
-    },
-    {
-      "captureKind": "trace-entry",
-      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
-      "timerName": "blobstore",
-      "className": "org.apache.james.blob.objectstorage.BlobPutter",
-      "methodName": "putAndComputeId",
-      "methodParameterTypes": [
-        ".."
-      ]
-    }
-  ]
-}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/jmap.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/jmap.json
new file mode 100644
index 0000000..9afce4b
--- /dev/null
+++ b/dockerfiles/run/guice/memory/destination/glowroot/plugins/jmap.json
@@ -0,0 +1,19 @@
+{
+  "name": "JMAP Plugin",
+  "id": "jmap",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.jmap.draft.methods.Method",
+      "methodName": "processToStream",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "JMAP",
+      "transactionNameTemplate": "JMAP method : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "jmapMethod"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/mailboxListener.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/mailboxListener.json
new file mode 100644
index 0000000..54a55ac
--- /dev/null
+++ b/dockerfiles/run/guice/memory/destination/glowroot/plugins/mailboxListener.json
@@ -0,0 +1,19 @@
+{
+  "name": "MailboxListener Plugin",
+  "id": "mailboxListener",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.mailbox.events.MailboxListener",
+      "methodName": "event",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "MailboxListener",
+      "transactionNameTemplate": "MailboxListener : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailboxListener"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/smtp.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/smtp.json
new file mode 100644
index 0000000..393bac9
--- /dev/null
+++ b/dockerfiles/run/guice/memory/destination/glowroot/plugins/smtp.json
@@ -0,0 +1,19 @@
+{
+  "name": "SMTP Plugin",
+  "id": "smtp",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler",
+      "methodName": "onCommand",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "SMTP",
+      "transactionNameTemplate": "SMTP command : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "smtpProcessor"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/spooler.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/spooler.json
index b9623a0..fd7732d 100644
--- a/dockerfiles/run/guice/memory/destination/glowroot/plugins/spooler.json
+++ b/dockerfiles/run/guice/memory/destination/glowroot/plugins/spooler.json
@@ -14,6 +14,32 @@
       "alreadyInTransactionBehavior": "capture-trace-entry",
       "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
       "timerName": "mailetProcessor"
+    },
+    {
+      "className": "org.apache.mailet.Mailet",
+      "methodName": "service",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Mailet",
+      "transactionNameTemplate": "Mailet : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "mailet"
+    },
+    {
+      "className": "org.apache.mailet.Matcher",
+      "methodName": "match",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "Matcher",
+      "transactionNameTemplate": "Mailet processor : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "matcher"
     }
   ]
 }
\ No newline at end of file
diff --git a/dockerfiles/run/guice/memory/destination/glowroot/plugins/task.json b/dockerfiles/run/guice/memory/destination/glowroot/plugins/task.json
new file mode 100644
index 0000000..8f04c69
--- /dev/null
+++ b/dockerfiles/run/guice/memory/destination/glowroot/plugins/task.json
@@ -0,0 +1,19 @@
+{
+  "name": "Task Plugin",
+  "id": "task",
+  "instrumentation": [
+    {
+      "className": "org.apache.james.task.Task",
+      "methodName": "run",
+      "methodParameterTypes": [
+        ".."
+      ],
+      "captureKind": "transaction",
+      "transactionType": "TASK",
+      "transactionNameTemplate": "TASK : {{this.class.name}}",
+      "alreadyInTransactionBehavior": "capture-trace-entry",
+      "traceEntryMessageTemplate": "{{this.class.name}}.{{methodName}}",
+      "timerName": "task"
+    }
+  ]
+}
\ 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] 04/07: [ADR] Event bus errors upon dispatch

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 19a35e0bebe117f8e81c30f7f8b438560b0c5924
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Apr 3 12:19:32 2020 +0700

    [ADR] Event bus errors upon dispatch
---
 .../0027-eventBus-error-handling-upon-dispatch.md  | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/src/adr/0027-eventBus-error-handling-upon-dispatch.md b/src/adr/0027-eventBus-error-handling-upon-dispatch.md
new file mode 100644
index 0000000..60e5cba
--- /dev/null
+++ b/src/adr/0027-eventBus-error-handling-upon-dispatch.md
@@ -0,0 +1,33 @@
+# 27. EventBus error handling upon dispatch
+
+Date: 2020-04-03
+
+## Status
+
+Accepted (lazy consensus)
+
+## Context
+
+James allows asynchronous processing for mailbox events via MailboxListener. This processing is abstracted by the 
+EventBus.
+
+If the processing of an event via a mailbox listener fails, it is retried, until it succeeds. If a maxRetries parameter 
+is exceeded, the event is stored in deadLetter and no further processing is attended.
+
+The administrator can then look at the content of deadLetter to diagnose processing issues and schedule a reDelivery in 
+order to retry their processing via webAdmin APIs.
+
+However no such capabilities are supported upon dispatching the event on the eventbus. A failed dispatch will result in message loss.
+
+## Decision
+
+Upon dispatch failure, the eventBus should save events in dead letter using a dedicated group.
+
+Reprocessing this group an admin can re-trigger these events dispatch.
+
+In order to ensure auto healing, James will periodically check the corresponding group in deadLetter is empty. If not a
+re-dispatching of these events will be attempted. 
+
+## Consequence
+
+In distributed James Guice project an administrator have a way to be eventually consistent upon rabbitMQ failure.
\ 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] 03/07: [ADR] Removing a configured additional MailboxListener

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 adc399bdc156aaa0d28ef9cda09034edee46192d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Fri Apr 3 12:10:11 2020 +0700

    [ADR] Removing a configured additional MailboxListener
---
 ...oving-configured-additional-mailboxListeners.md | 40 ++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/adr/0026-removing-configured-additional-mailboxListeners.md b/src/adr/0026-removing-configured-additional-mailboxListeners.md
new file mode 100644
index 0000000..3158aaf
--- /dev/null
+++ b/src/adr/0026-removing-configured-additional-mailboxListeners.md
@@ -0,0 +1,40 @@
+# 26. Removing a configured additional MailboxListener
+
+Date: 2020-04-03
+
+## Status
+
+Accepted (lazy consensus)
+
+## Context
+
+James enables a user to register additional mailbox listeners.
+
+The distributed James server is handling mailbox event processing (mailboxListener execution) using a RabbitMQ work-queue
+per listener.
+
+The distributed James server then declares a queue upon start for each one of these user registered listeners, that it
+binds to the main event exchange. 
+
+If the user unconfigures the listener, the queue and the binding are still present but not consumed. This results in 
+unbounded queue growth eventually causing RabbitMQ resource exhaustion and failure.
+
+## Decision
+
+For rabbitMQ, configuration changes of additional mailbox listeners should be tracked via event sourcing. Event sourcing is 
+desirable as it allows:
+ - Detecting previously removed MailboxListener upon start
+ - Audit of unbind decisions
+ - Enables writing more complex business rules in the future
+
+We need, upon start, to sanitize bindings, and remove the ones corresponding to mailboxListeners that were removed not configured.
+
+The queue should not be deleted to prevent message loss.
+
+Given a James topology with a non uniform configuration, the effective RabbitMQ routing will be the one of the latest 
+started James server.
+
+## Alternatives
+
+We could also consider adding a webadmin endpoint to sanitize eventBus bindings, allowing more predictability than the
+above solution but it would require admin intervention.


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


[james-project] 06/07: JAMES-3078 JMAP Get/Set filter should be reactive

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 488ebd20d69c99492006750a5296d3b2343df361
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Apr 5 15:30:48 2020 +0700

    JAMES-3078 JMAP Get/Set filter should be reactive
---
 .../jmap/api/filtering/FilteringManagement.java    | 10 ++--
 .../impl/EventSourcingFilteringManagement.java     |  4 +-
 .../api/filtering/FilteringManagementContract.java | 21 +++++----
 .../james/jmap/draft/methods/GetFilterMethod.java  | 33 +++++--------
 .../james/jmap/draft/methods/SetFilterMethod.java  | 55 ++++++++++++----------
 .../jmap/mailet/filter/JMAPFilteringExtension.java |  4 +-
 .../jmap/mailet/filter/JMAPFilteringTest.java      | 30 ++++++------
 7 files changed, 80 insertions(+), 77 deletions(-)

diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java
index 6e780f9..3305ead 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/FilteringManagement.java
@@ -29,14 +29,14 @@ import com.google.common.collect.ImmutableList;
 
 public interface FilteringManagement {
 
-    void defineRulesForUser(Username username, List<Rule> rules);
+    Publisher<Void> defineRulesForUser(Username username, List<Rule> rules);
 
-    default void defineRulesForUser(Username username, Rule... rules) {
-        defineRulesForUser(username, Arrays.asList(rules));
+    default Publisher<Void> defineRulesForUser(Username username, Rule... rules) {
+        return defineRulesForUser(username, Arrays.asList(rules));
     }
 
-    default void clearRulesForUser(Username username) {
-        defineRulesForUser(username, ImmutableList.of());
+    default Publisher<Void> clearRulesForUser(Username username) {
+        return defineRulesForUser(username, ImmutableList.of());
     }
 
     Publisher<Rule> listRulesForUser(Username username);
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java
index 429cc79..72af24d 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/impl/EventSourcingFilteringManagement.java
@@ -54,8 +54,8 @@ public class EventSourcingFilteringManagement implements FilteringManagement {
     }
 
     @Override
-    public void defineRulesForUser(Username username, List<Rule> rules) {
-        Mono.from(eventSourcingSystem.dispatch(new DefineRulesCommand(username, rules))).block();
+    public Publisher<Void> defineRulesForUser(Username username, List<Rule> rules) {
+        return eventSourcingSystem.dispatch(new DefineRulesCommand(username, rules));
     }
 
     @Override
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java
index 7a355d4..6dcf8c6 100644
--- a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/filtering/FilteringManagementContract.java
@@ -36,6 +36,7 @@ import org.apache.james.jmap.api.filtering.impl.EventSourcingFilteringManagement
 import org.junit.jupiter.api.Test;
 
 import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
 
 public interface FilteringManagementContract {
 
@@ -63,7 +64,7 @@ public interface FilteringManagementContract {
     default void listingRulesShouldReturnDefinedRules(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        testee.defineRulesForUser(USERNAME, RULE_1, RULE_2);
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_1, RULE_2)).block();
 
         assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream())
             .containsExactly(RULE_1, RULE_2);
@@ -73,8 +74,8 @@ public interface FilteringManagementContract {
     default void listingRulesShouldReturnLastDefinedRules(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        testee.defineRulesForUser(USERNAME, RULE_1, RULE_2);
-        testee.defineRulesForUser(USERNAME, RULE_2, RULE_1);
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_1, RULE_2)).block();
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_2, RULE_1)).block();
 
         assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream())
             .containsExactly(RULE_2, RULE_1);
@@ -84,7 +85,7 @@ public interface FilteringManagementContract {
     default void definingRulesShouldThrowWhenDuplicateRules(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        assertThatThrownBy(() -> testee.defineRulesForUser(USERNAME, RULE_1, RULE_1))
+        assertThatThrownBy(() -> Mono.from(testee.defineRulesForUser(USERNAME, RULE_1, RULE_1)).block())
             .isInstanceOf(IllegalArgumentException.class);
     }
 
@@ -92,7 +93,7 @@ public interface FilteringManagementContract {
     default void definingRulesShouldThrowWhenNullUser(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        assertThatThrownBy(() -> testee.defineRulesForUser(null, RULE_1, RULE_1))
+        assertThatThrownBy(() -> Mono.from(testee.defineRulesForUser(null, RULE_1, RULE_1)).block())
             .isInstanceOf(NullPointerException.class);
     }
 
@@ -101,14 +102,14 @@ public interface FilteringManagementContract {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
         List<Rule> rules = null;
-        assertThatThrownBy(() -> testee.defineRulesForUser(USERNAME, rules))
+        assertThatThrownBy(() -> Mono.from(testee.defineRulesForUser(USERNAME, rules)).block())
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
     default void definingRulesShouldKeepOrdering(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
-        testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1);
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1)).block();
 
         assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream())
             .containsExactly(RULE_3, RULE_2, RULE_1);
@@ -118,8 +119,8 @@ public interface FilteringManagementContract {
     default void definingEmptyRuleListShouldRemoveExistingRules(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1);
-        testee.clearRulesForUser(USERNAME);
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_3, RULE_2, RULE_1)).block();
+        Mono.from(testee.clearRulesForUser(USERNAME)).block();
 
         assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream()).isEmpty();
     }
@@ -128,7 +129,7 @@ public interface FilteringManagementContract {
     default void allFieldsAndComparatorShouldWellBeStored(EventStore eventStore) {
         FilteringManagement testee = instantiateFilteringManagement(eventStore);
 
-        testee.defineRulesForUser(USERNAME, RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1);
+        Mono.from(testee.defineRulesForUser(USERNAME, RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1)).block();
 
         assertThat(Flux.from(testee.listRulesForUser(USERNAME)).toStream())
             .containsExactly(RULE_FROM, RULE_RECIPIENT, RULE_SUBJECT, RULE_TO, RULE_1);
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
index 618d862..6c1ca63 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetFilterMethod.java
@@ -19,7 +19,7 @@
 
 package org.apache.james.jmap.draft.methods;
 
-import java.util.stream.Stream;
+import static org.apache.james.util.ReactorUtils.context;
 
 import javax.inject.Inject;
 
@@ -67,7 +67,7 @@ public class GetFilterMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Flux<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
@@ -75,26 +75,21 @@ public class GetFilterMethod implements Method {
 
         GetFilterRequest filterRequest = (GetFilterRequest) request;
 
-
-        return MDCBuilder.create()
-            .addContext(MDCBuilder.ACTION, "GET_FILTER")
-            .wrapArround(
-                () -> metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
-                    () -> process(methodCallId, mailboxSession, filterRequest)))
-            .get();
+        return Flux.from(metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
+            () -> process(methodCallId, mailboxSession, filterRequest)
+                .subscriberContext(context("GET_FILTER", MDCBuilder.of(MDCBuilder.ACTION, "GET_FILTER")))));
     }
 
-    private Stream<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, GetFilterRequest request) {
-        try {
-            return retrieveFilter(methodCallId, mailboxSession.getUser());
-        } catch (Exception e) {
-            LOGGER.warn("Failed to retrieve filter");
+    private Mono<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, GetFilterRequest request) {
+        return retrieveFilter(methodCallId, mailboxSession.getUser())
+            .onErrorResume(e -> {
+                LOGGER.warn("Failed to retrieve filter", e);
 
-            return Stream.of(unKnownError(methodCallId));
-        }
+                return Mono.just(unKnownError(methodCallId));
+            });
     }
 
-    private Stream<JmapResponse> retrieveFilter(MethodCallId methodCallId, Username username) {
+    private Mono<JmapResponse> retrieveFilter(MethodCallId methodCallId, Username username) {
         return Flux.from(filteringManagement.listRulesForUser(username))
             .collect(Guavate.toImmutableList())
             .map(rules -> GetFilterResponse.builder()
@@ -104,9 +99,7 @@ public class GetFilterMethod implements Method {
                 .methodCallId(methodCallId)
                 .response(getFilterResponse)
                 .responseName(RESPONSE_NAME)
-                .build())
-            .flatMapMany(Mono::just)
-            .toStream();
+                .build());
     }
 
     private JmapResponse unKnownError(MethodCallId methodCallId) {
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
index b6e82d7..f0ac91a 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetFilterMethod.java
@@ -19,11 +19,13 @@
 
 package org.apache.james.jmap.draft.methods;
 
+import static org.apache.james.jmap.http.LoggingHelper.jmapAction;
+import static org.apache.james.util.ReactorUtils.context;
+
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
 
@@ -38,13 +40,18 @@ import org.apache.james.jmap.draft.model.SetFilterResponse;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.util.MDCBuilder;
+import org.apache.james.util.ReactorUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.steveash.guavate.Guavate;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableListMultimap;
 
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
 public class SetFilterMethod implements Method {
 
     public static class DuplicatedRuleException extends Exception {
@@ -102,7 +109,7 @@ public class SetFilterMethod implements Method {
     }
 
     @Override
-    public Stream<JmapResponse> processToStream(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
+    public Flux<JmapResponse> process(JmapRequest request, MethodCallId methodCallId, MailboxSession mailboxSession) {
         Preconditions.checkNotNull(request);
         Preconditions.checkNotNull(methodCallId);
         Preconditions.checkNotNull(mailboxSession);
@@ -111,52 +118,50 @@ public class SetFilterMethod implements Method {
 
         SetFilterRequest setFilterRequest = (SetFilterRequest) request;
 
-        return MDCBuilder.create()
-            .addContext(MDCBuilder.ACTION, "SET_FILTER")
-            .addContext("update", setFilterRequest.getSingleton())
-            .wrapArround(
-                () -> metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
-                    () -> process(methodCallId, mailboxSession, setFilterRequest)))
-            .get();
+        return Flux.from(metricFactory.runPublishingTimerMetricLogP99(JMAP_PREFIX + METHOD_NAME.getName(),
+            () -> process(methodCallId, mailboxSession, setFilterRequest)
+                .subscriberContext(jmapAction("SET_FILTER"))
+                .subscriberContext(context("SET_FILTER", MDCBuilder.of("update", setFilterRequest.getSingleton())))));
     }
 
-    private Stream<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, SetFilterRequest request) {
+    private Mono<JmapResponse> process(MethodCallId methodCallId, MailboxSession mailboxSession, SetFilterRequest request) {
         try {
-            return updateFilter(methodCallId, request, mailboxSession.getUser());
+            return updateFilter(methodCallId, request, mailboxSession.getUser())
+                .doOnEach(ReactorUtils.logOnError(e -> LOGGER.warn("Failed setting Rules", e)))
+                .onErrorResume(e -> Mono.just(unKnownError(methodCallId)));
         } catch (MultipleMailboxIdException e) {
             LOGGER.debug("Rule targeting several mailboxes", e);
-            return Stream.of(multipleMailboxesError(methodCallId, e));
+            return Mono.just(multipleMailboxesError(methodCallId, e));
         }  catch (DuplicatedRuleException e) {
             LOGGER.debug("Duplicated rules", e);
-            return Stream.of(duplicatedIdsError(methodCallId, e));
-        } catch (Exception e) {
+            return Mono.just(duplicatedIdsError(methodCallId, e));
+        }  catch (Exception e) {
             LOGGER.warn("Failed setting Rules", e);
-            return Stream.of(unKnownError(methodCallId));
+            return Mono.just(unKnownError(methodCallId));
         }
     }
 
-    private Stream<JmapResponse> updateFilter(MethodCallId methodCallId, SetFilterRequest request, Username username) throws DuplicatedRuleException, MultipleMailboxIdException {
+    private Mono<JmapResponse> updateFilter(MethodCallId methodCallId, SetFilterRequest request, Username username) throws DuplicatedRuleException, MultipleMailboxIdException {
         ImmutableList<Rule> rules = request.getSingleton().stream()
             .map(JmapRuleDTO::toRule)
-            .collect(ImmutableList.toImmutableList());
+            .collect(Guavate.toImmutableList());
 
         ensureNoDuplicatedRules(rules);
         ensureNoMultipleMailboxesRules(rules);
 
-        filteringManagement.defineRulesForUser(username, rules);
-
-        return Stream.of(JmapResponse.builder()
-            .methodCallId(methodCallId)
-            .responseName(RESPONSE_NAME)
-            .response(SetFilterResponse.updated())
-            .build());
+        return Mono.from(filteringManagement.defineRulesForUser(username, rules))
+            .thenReturn(JmapResponse.builder()
+                .methodCallId(methodCallId)
+                .responseName(RESPONSE_NAME)
+                .response(SetFilterResponse.updated())
+                .build());
     }
 
     private void ensureNoMultipleMailboxesRules(ImmutableList<Rule> rules) throws MultipleMailboxIdException {
         ImmutableList<Rule.Id> idWithMultipleMailboxes = rules.stream()
             .filter(rule -> rule.getAction().getAppendInMailboxes().getMailboxIds().size() > 1)
             .map(Rule::getId)
-            .collect(ImmutableList.toImmutableList());
+            .collect(Guavate.toImmutableList());
 
         if (!idWithMultipleMailboxes.isEmpty()) {
             throw new MultipleMailboxIdException(idWithMultipleMailboxes);
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringExtension.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringExtension.java
index 4232100..6ad8f2e 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringExtension.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringExtension.java
@@ -53,6 +53,8 @@ import org.junit.jupiter.api.extension.ParameterResolver;
 
 import com.google.common.collect.ImmutableList;
 
+import reactor.core.publisher.Mono;
+
 public class JMAPFilteringExtension implements BeforeEachCallback, ParameterResolver {
     private static final DomainList NO_DOMAIN_LIST = null;
 
@@ -114,7 +116,7 @@ public class JMAPFilteringExtension implements BeforeEachCallback, ParameterReso
                     .build())
                 .collect(ImmutableList.toImmutableList());
 
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, rules);
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, rules)).block();
         }
 
         public FakeMail asMail(MimeMessageBuilder mimeMessageBuilder) throws MessagingException {
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
index b28d8e1..27d503a 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
@@ -80,6 +80,8 @@ import com.github.fge.lambdas.Throwing;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
+import reactor.core.publisher.Mono;
+
 @ExtendWith(JMAPFilteringExtension.class)
 class JMAPFilteringTest {
 
@@ -692,7 +694,7 @@ class JMAPFilteringTest {
             MailboxId mailbox2Id = testSystem.createMailbox(RECIPIENT_1_USERNAME, "RECIPIENT_1_MAILBOX_2");
             MailboxId mailbox3Id = testSystem.createMailbox(RECIPIENT_1_USERNAME, "RECIPIENT_1_MAILBOX_3");
 
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
@@ -710,7 +712,7 @@ class JMAPFilteringTest {
                     .name("rule 3")
                     .condition(Rule.Condition.of(TO, EXACTLY_EQUALS, USER_3_ADDRESS))
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(mailbox3Id.serialize())))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                     .addFrom(USER_2_ADDRESS)
@@ -729,7 +731,7 @@ class JMAPFilteringTest {
             MailboxId mailbox2Id = testSystem.createMailbox(RECIPIENT_1_USERNAME, "RECIPIENT_1_MAILBOX_2");
             MailboxId mailbox3Id = testSystem.createMailbox(RECIPIENT_1_USERNAME, "RECIPIENT_1_MAILBOX_3");
 
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
@@ -738,7 +740,7 @@ class JMAPFilteringTest {
                         mailbox3Id.serialize(),
                         mailbox2Id.serialize(),
                         mailbox1Id.serialize()))))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                     .setSubject(UNSCRAMBLED_SUBJECT));
@@ -753,7 +755,7 @@ class JMAPFilteringTest {
         void rulesWithEmptyMailboxIdsShouldBeSkept(JMAPFilteringTestSystem testSystem) throws Exception {
             MailboxId mailbox1Id = testSystem.createMailbox(RECIPIENT_1_USERNAME, "RECIPIENT_1_MAILBOX_1");
 
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
@@ -766,7 +768,7 @@ class JMAPFilteringTest {
                     .condition(Rule.Condition.of(SUBJECT, CONTAINS, UNSCRAMBLED_SUBJECT))
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(ImmutableList.of(
                         mailbox1Id.serialize()))))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                     .setSubject(UNSCRAMBLED_SUBJECT));
@@ -822,13 +824,13 @@ class JMAPFilteringTest {
         @Test
         void serviceShouldNotThrowWhenUnknownMailboxId(JMAPFilteringTestSystem testSystem) throws Exception {
             String unknownMailboxId = "4242";
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
                     .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME))
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(unknownMailboxId)))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                 .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS));
@@ -840,13 +842,13 @@ class JMAPFilteringTest {
         @Test
         void mailDirectiveShouldNotBeSetWhenUnknownMailboxId(JMAPFilteringTestSystem testSystem) throws Exception {
             String unknownMailboxId = "4242";
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
                     .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME))
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(unknownMailboxId)))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                 .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS));
@@ -860,7 +862,7 @@ class JMAPFilteringTest {
         @Test
         void rulesWithInvalidMailboxIdsShouldBeSkept(JMAPFilteringTestSystem testSystem) throws Exception {
             String unknownMailboxId = "4242";
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
@@ -873,7 +875,7 @@ class JMAPFilteringTest {
                     .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME))
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(
                         testSystem.getRecipient1MailboxId().serialize())))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                 .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS));
@@ -888,7 +890,7 @@ class JMAPFilteringTest {
         void rulesWithMultipleMailboxIdsShouldFallbackWhenInvalidFirstMailboxId(JMAPFilteringTestSystem testSystem) throws Exception {
             String unknownMailboxId = "4242";
 
-            testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
+            Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME,
                 Rule.builder()
                     .id(Rule.Id.of("1"))
                     .name("rule 1")
@@ -896,7 +898,7 @@ class JMAPFilteringTest {
                     .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(
                         unknownMailboxId,
                         testSystem.getRecipient1MailboxId().serialize())))
-                    .build());
+                    .build())).block();
 
             FakeMail mail = testSystem.asMail(mimeMessageBuilder()
                 .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS));


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