This is an automated email from the ASF dual-hosted git repository. jhelou pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push: new a06577193f [JAMES-4128] improves Mailet config encapsulation a06577193f is described below commit a06577193f2f729c040c9449040d4c9a90b824a6 Author: Matthieu Baechler <matth...@baechler-craftsmanship.fr> AuthorDate: Tue Mar 25 16:59:01 2025 +0100 [JAMES-4128] improves Mailet config encapsulation The mailet configuration is injected from the mailet container, exposing it back publicly breaks encapsulation. We propose to remove the `getMailetConfig` method ( yes this is a breaking api change ) and add 1 method to the interface to clarify the contract: `String getName()` returns the name of the mailet. a default implementation is `GenericMailet#getMailetName()` though we want to avoid repeating `Mailet` in the interface. --- CHANGELOG.md | 7 +- .../src/main/java/org/apache/mailet/Mailet.java | 21 ++---- .../java/org/apache/mailet/base/GenericMailet.java | 5 +- .../mailet/constructor/ConstructorMailet.java | 5 -- .../excluded/ExcludedFromDocumentationMailet.java | 5 -- .../NotExcludedFromDocumentationMailet.java | 5 -- .../mailet/experimental/ExperimentalMailet.java | 5 -- .../mailet/experimental/NonExperimentalMailet.java | 5 -- .../modules/server/MailetContainerModule.java | 65 ++++++++++-------- .../mailets/sub/ConstructorBoundTestMailet.java | 4 +- .../apache/james/utils/GuiceMailetLoaderTest.java | 2 +- .../api/mock/ExceptionThrowingMailet.java | 4 +- .../james/mailetcontainer/api/mock/MockMailet.java | 4 +- .../mailetcontainer/impl/MailetProcessorImpl.java | 2 +- .../mailetcontainer/impl/MatcherMailetPair.java | 31 ++++++--- .../mailetcontainer/impl/MatcherSplitter.java | 3 +- .../james/mailetcontainer/impl/ProcessorImpl.java | 29 ++++---- .../impl/jmx/JMXStateMailetProcessorListener.java | 14 +++- .../mailetcontainer/impl/jmx/MailetManagement.java | 29 ++++---- .../lib/AbstractStateCompositeProcessor.java | 21 +++--- .../lib/AbstractStateMailetProcessor.java | 11 ++- .../MailProcessingErrorHandlingConfiguration.java} | 79 ++++++++++------------ .../impl/MailetProcessorImplTest.java | 27 ++++---- .../lib/AbstractStateMailetProcessorTest.java | 77 ++++++++++++--------- .../james/samples/mailets/HelloWorldMailet.java | 8 +-- .../samples/mailets/InstrumentationMailet.java | 8 +-- upgrade-instructions.md | 13 ++++ 27 files changed, 259 insertions(+), 230 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfd2fbdd80..841006b8ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) - Upgrade javax -> jakarta. See releated upgrade instructions. - Upgrade Java 11 -> 21. See related upgrade instructions. - API change: CassandraModule and all associated Cassandra*Module were renamed to CassandraDataDefinition and Cassandra*DataDefinition respectively. - + - API change : Mailet API has been cleaned up and no longer exposes the mailet config, exposing only the mailet's name instead. + - API change : GenericMailet can have its config bound by constructor and this is the preferred way to initialize your mailets. `init` is still called but will eventually be removed in a later release. + ### Removals - JAMES-3946 WhiteList manager removals (#2299) @@ -82,7 +84,8 @@ Please use RFC-8621 implementation rather than this outdated draft. - JAMES-3824 SMTP Extension for Message Transfer Priorities ### Improvements - + + - JAMES-4125 rework mailet api - JAMES-4123 Renames CassandraModule to CassandraDataDefinition - JAMES-4103 Allow customizing MessageParser - JAMES-3967 RelayLimit: add error log diff --git a/mailet/api/src/main/java/org/apache/mailet/Mailet.java b/mailet/api/src/main/java/org/apache/mailet/Mailet.java index f59fc8b9dd..b9743da23c 100644 --- a/mailet/api/src/main/java/org/apache/mailet/Mailet.java +++ b/mailet/api/src/main/java/org/apache/mailet/Mailet.java @@ -42,10 +42,7 @@ import com.google.common.collect.ImmutableList; * </ol> * <p> * In addition to the life-cycle methods, this interface provides the - * {@link #getMailetConfig} method, which provides the Mailet with - * its initialization parameters and a {@link MailetContext} through which - * it can interact with the mailet container, and the {@link #getMailetInfo} - * method, which provides basic information about the Mailet. + * {@link #getMailetInfo} method, which provides basic information about the Mailet. * <p> * Mailets are grouped by the mailet container's configuration into processors. * Each processor is comprised of an ordered sequence of Mailets, each with a @@ -114,18 +111,12 @@ public interface Mailet { } /** - * Returns a MailetConfig object, which provides initialization parameters - * and a {@link MailetContext} through which it can interact with the - * mailet container. - * <p> - * Implementations of this interface are responsible for storing the - * MailetConfig which they receive in the {@link #init} method so - * that this method can return it. - * - * @return the MailetConfig that this mailet was initialized with + * @return mailet name */ - MailetConfig getMailetConfig(); - + default String getName() { + return this.getClass().getSimpleName(); + } + /** * Returns information about the mailet, such as author, version and * copyright. diff --git a/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java b/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java index 3f12f4bf22..cac316e745 100644 --- a/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java +++ b/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java @@ -177,7 +177,6 @@ public abstract class GenericMailet implements Mailet, MailetConfig { * * @return the MailetConfig object that initialized this mailet */ - @Override public MailetConfig getMailetConfig() { return config; } @@ -204,6 +203,10 @@ public abstract class GenericMailet implements Mailet, MailetConfig { return config.getMailetName(); } + @Override + public String getName() { + return getMailetName(); + } /** * <p>Called by the mailet container to indicate to a mailet that the diff --git a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/constructor/ConstructorMailet.java b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/constructor/ConstructorMailet.java index 905ef7b08b..9f6fcc76f1 100644 --- a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/constructor/ConstructorMailet.java +++ b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/constructor/ConstructorMailet.java @@ -44,11 +44,6 @@ public class ConstructorMailet implements Mailet { public void destroy() { } - @Override - public MailetConfig getMailetConfig() { - return null; - } - @Override public String getMailetInfo() { return "info"; diff --git a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/ExcludedFromDocumentationMailet.java b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/ExcludedFromDocumentationMailet.java index bc69216455..a728ab0e49 100644 --- a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/ExcludedFromDocumentationMailet.java +++ b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/ExcludedFromDocumentationMailet.java @@ -41,11 +41,6 @@ public class ExcludedFromDocumentationMailet implements Mailet { public void destroy() { } - @Override - public MailetConfig getMailetConfig() { - return null; - } - @Override public String getMailetInfo() { return null; diff --git a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/NotExcludedFromDocumentationMailet.java b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/NotExcludedFromDocumentationMailet.java index 46405f0daa..7195d76b35 100644 --- a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/NotExcludedFromDocumentationMailet.java +++ b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/excluded/NotExcludedFromDocumentationMailet.java @@ -39,11 +39,6 @@ public class NotExcludedFromDocumentationMailet implements Mailet { public void destroy() { } - @Override - public MailetConfig getMailetConfig() { - return null; - } - @Override public String getMailetInfo() { return null; diff --git a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/ExperimentalMailet.java b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/ExperimentalMailet.java index 09fe15d9e1..dba296dd63 100644 --- a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/ExperimentalMailet.java +++ b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/ExperimentalMailet.java @@ -41,11 +41,6 @@ public class ExperimentalMailet implements Mailet { public void destroy() { } - @Override - public MailetConfig getMailetConfig() { - return null; - } - @Override public String getMailetInfo() { return null; diff --git a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/NonExperimentalMailet.java b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/NonExperimentalMailet.java index 107cfcc57a..db9fc08c74 100644 --- a/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/NonExperimentalMailet.java +++ b/mailet/mailetdocs-maven-plugin/src/test/java/org/apache/james/mailet/experimental/NonExperimentalMailet.java @@ -39,11 +39,6 @@ public class NonExperimentalMailet implements Mailet { public void destroy() { } - @Override - public MailetConfig getMailetConfig() { - return null; - } - @Override public String getMailetInfo() { return null; diff --git a/server/container/guice/mailet/src/main/java/org/apache/james/modules/server/MailetContainerModule.java b/server/container/guice/mailet/src/main/java/org/apache/james/modules/server/MailetContainerModule.java index e6ef0a8e9b..9a7120f49b 100644 --- a/server/container/guice/mailet/src/main/java/org/apache/james/modules/server/MailetContainerModule.java +++ b/server/container/guice/mailet/src/main/java/org/apache/james/modules/server/MailetContainerModule.java @@ -60,6 +60,7 @@ import org.apache.mailet.Mailet; import org.apache.mailet.MailetContext; import org.apache.mailet.Matcher; import org.apache.mailet.base.AutomaticallySentMailDetector; +import org.apache.mailet.base.GenericMailet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,11 +84,19 @@ public class MailetContainerModule extends AbstractModule { private static final boolean MAILET_CONTAINER_CHECK_ENABLED = Boolean.parseBoolean(System.getProperty("james.mailet.container.check.enabled", "true")); public static final ProcessorsCheck.Impl BCC_Check = new ProcessorsCheck.Impl( - "transport", - All.class, - RemoveMimeHeader.class, - pair -> Arrays.asList(pair.getMailet().getMailetConfig().getInitParameter("name").toLowerCase().split(",")).contains("bcc"), - "Should be configured to remove Bcc header"); + "transport", + All.class, + RemoveMimeHeader.class, + pair -> { + if (pair.getMailet() instanceof GenericMailet genericMailet) { + return Arrays + .asList(genericMailet.getMailetConfig().getInitParameter("name").toLowerCase().split(",")) + .contains("bcc"); + } else { + return false; + } + }, + "Should be configured to remove Bcc header"); @Override protected void configure() { @@ -128,7 +137,7 @@ public class MailetContainerModule extends AbstractModule { private HierarchicalConfiguration<ImmutableNode> getJamesSpoolerConfiguration(ConfigurationProvider configurationProvider) { try { return configurationProvider.getConfiguration("mailetcontainer") - .configurationAt("spooler"); + .configurationAt("spooler"); } catch (Exception e) { LOGGER.warn("Could not locate configuration for James Spooler. Assuming empty configuration for this component."); return new BaseHierarchicalConfiguration(); @@ -138,8 +147,8 @@ public class MailetContainerModule extends AbstractModule { @ProvidesIntoSet InitializationOperation initMailetContext(ConfigurationProvider configurationProvider, JamesMailetContext mailetContext) { return InitilizationOperationBuilder - .forClass(JamesMailetContext.class) - .init(() -> mailetContext.configure(getMailetContextConfiguration(configurationProvider))); + .forClass(JamesMailetContext.class) + .init(() -> mailetContext.configure(getMailetContextConfiguration(configurationProvider))); } @VisibleForTesting @@ -206,19 +215,19 @@ public class MailetContainerModule extends AbstractModule { private void checkProcessors() throws ConfigurationException { ImmutableListMultimap<String, MatcherMailetPair> processors = Arrays.stream(compositeProcessorImpl.getProcessorStates()) - .flatMap(state -> { - MailProcessor processor = compositeProcessorImpl.getProcessor(state); - if (processor instanceof MailetProcessorImpl) { - MailetProcessorImpl camelProcessor = (MailetProcessorImpl) processor; - return camelProcessor.getPairs().stream() - .map(pair -> Pair.of(state, pair)); - } else { - throw new RuntimeException("Can not perform checks as transport processor is not an instance of " + MailProcessor.class); - } - }) - .collect(ImmutableListMultimap.toImmutableListMultimap( - Pair::getKey, - Pair::getValue)); + .flatMap(state -> { + MailProcessor processor = compositeProcessorImpl.getProcessor(state); + if (processor instanceof MailetProcessorImpl) { + MailetProcessorImpl camelProcessor = (MailetProcessorImpl) processor; + return camelProcessor.getPairs().stream() + .map(pair -> Pair.of(state, pair)); + } else { + throw new RuntimeException("Can not perform checks as transport processor is not an instance of " + MailProcessor.class); + } + }) + .collect(ImmutableListMultimap.toImmutableListMultimap( + Pair::getKey, + Pair::getValue)); for (ProcessorsCheck check : processorsCheckSet) { check.check(processors); } @@ -283,7 +292,7 @@ public class MailetContainerModule extends AbstractModule { this(processorName, matcherClass, mailetClass, Optional.empty(), Optional.empty()); } - public Impl(String processorName, Class<? extends Matcher> matcherClass, Class<? extends Mailet> mailetClass, Predicate<? super MatcherMailetPair> additionalFilter, String additionalErrorMessage) { + public Impl(String processorName, Class<? extends Matcher> matcherClass, Class<? extends GenericMailet> mailetClass, Predicate<? super MatcherMailetPair> additionalFilter, String additionalErrorMessage) { this(processorName, matcherClass, mailetClass, Optional.of(additionalFilter), Optional.of(additionalErrorMessage)); } @@ -303,12 +312,12 @@ public class MailetContainerModule extends AbstractModule { } Preconditions.checkNotNull(pairs); pairs.stream() - .filter(pair -> pair.getMailet().getClass().equals(mailetClass)) - .filter(pair -> pair.getMatcher().getClass().equals(matcherClass)) - .filter(additionalFilter.orElse(any -> true)) - .findAny() - .orElseThrow(() -> new ConfigurationException("Missing " + mailetClass.getName() + " in mailets configuration (mailetcontainer -> processors -> " + processorName + "). " + - additionalErrorMessage.orElse(""))); + .filter(pair -> pair.getMailet().getClass().equals(mailetClass)) + .filter(pair -> pair.getMatcher().getClass().equals(matcherClass)) + .filter(additionalFilter.orElse(any -> true)) + .findAny() + .orElseThrow(() -> new ConfigurationException("Missing " + mailetClass.getName() + " in mailets configuration (mailetcontainer -> processors -> " + processorName + "). " + + additionalErrorMessage.orElse(""))); } } } diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java b/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java index ed582c04c1..a05fae1f69 100644 --- a/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java +++ b/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java @@ -40,7 +40,7 @@ public class ConstructorBoundTestMailet implements Mailet { } @Override - public MailetConfig getMailetConfig() { - return config; + public String getName() { + return config.getMailetName(); } } diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java index 792955cd0a..b8591e2a33 100644 --- a/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java +++ b/server/container/guice/mailet/src/test/java/org/apache/james/utils/GuiceMailetLoaderTest.java @@ -68,7 +68,7 @@ class GuiceMailetLoaderTest { .build()); assertThat(mailet).isInstanceOf(ConstructorBoundTestMailet.class); - assertThat(mailet.getMailetConfig()).isNotNull(); + assertThat(mailet.getName()).isEqualTo("sub.ConstructorBoundTestMailet"); } @Test diff --git a/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/ExceptionThrowingMailet.java b/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/ExceptionThrowingMailet.java index 61b98ce44d..2763c042e6 100644 --- a/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/ExceptionThrowingMailet.java +++ b/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/ExceptionThrowingMailet.java @@ -33,8 +33,8 @@ public class ExceptionThrowingMailet implements Mailet { } @Override - public MailetConfig getMailetConfig() { - return config; + public String getName() { + return config.getMailetName(); } @Override diff --git a/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/MockMailet.java b/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/MockMailet.java index 1e128f34ea..c673577831 100644 --- a/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/MockMailet.java +++ b/server/mailet/mailetcontainer-api/src/test/java/org/apache/james/mailetcontainer/api/mock/MockMailet.java @@ -31,8 +31,8 @@ public class MockMailet implements Mailet { } @Override - public MailetConfig getMailetConfig() { - return config; + public String getName() { + return config.getMailetName(); } @Override diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MailetProcessorImpl.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MailetProcessorImpl.java index e1440a52ab..a76e164c43 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MailetProcessorImpl.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MailetProcessorImpl.java @@ -202,7 +202,7 @@ public class MailetProcessorImpl extends AbstractStateMailetProcessor { this.pairs = pairs; this.pairsToBeProcessed = pairs.stream() .map(pair -> Pair.of(new MatcherSplitter(metricFactory, this, pair), - new ProcessorImpl(metricFactory, this, pair.getMailet()))) + new ProcessorImpl(metricFactory, pair.getMailet(), pair.processingErrorConfig(), this.getListeners()))) .collect(ImmutableMap.toImmutableMap(Pair::getKey, Pair::getValue)); } catch (Exception e) { throw new MessagingException("Unable to setup routing for MailetMatcherPairs", e); diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherMailetPair.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherMailetPair.java index b2d1540239..1d8585ab31 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherMailetPair.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherMailetPair.java @@ -18,24 +18,30 @@ ****************************************************************/ package org.apache.james.mailetcontainer.impl; +import java.util.Optional; + +import org.apache.james.mailetcontainer.lib.MailProcessingErrorHandlingConfiguration; import org.apache.mailet.Mailet; import org.apache.mailet.Matcher; +import com.google.common.annotations.VisibleForTesting; + /** * A pair of {@link Matcher} and {@link Mailet} */ -public class MatcherMailetPair { - private final Matcher matcher; - private final Mailet mailet; - +public record MatcherMailetPair( + Matcher matcher, + Mailet mailet, + MailProcessingErrorHandlingConfiguration processingErrorConfig +) { + @VisibleForTesting public MatcherMailetPair(Matcher matcher, Mailet mailet) { - this.matcher = matcher; - this.mailet = mailet; + this(matcher, mailet, MailProcessingErrorHandlingConfiguration.empty()); } /** * Return the {@link Matcher} of this pair - * + * * @return matcher */ public Matcher getMatcher() { @@ -44,16 +50,19 @@ public class MatcherMailetPair { /** * Return the {@link Mailet} of this pair - * + * * @return mailet */ public Mailet getMailet() { return mailet; } - public String getOnMatchException() { - return mailet.getMailetConfig() - .getInitParameter("onMatchException"); + public Optional<String> onMatchException() { + return processingErrorConfig.onMatchException(); + } + + public Optional<String> onMailetException() { + return processingErrorConfig.onMailetException(); } } diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherSplitter.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherSplitter.java index 84d3564a97..9e872bd675 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherSplitter.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/MatcherSplitter.java @@ -24,7 +24,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; -import java.util.Optional; import jakarta.mail.MessagingException; @@ -63,7 +62,7 @@ public class MatcherSplitter { this.metricFactory = metricFactory; this.container = container; this.matcher = pair.getMatcher(); - this.onMatchException = Optional.ofNullable(pair.getOnMatchException()) + this.onMatchException = pair.onMatchException() .map(s -> s.trim().toLowerCase(Locale.US)) .orElse(Mail.ERROR); } diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorImpl.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorImpl.java index 2fe5c0e80d..416f284e5a 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorImpl.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/ProcessorImpl.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Locale; import org.apache.james.mailetcontainer.lib.AbstractStateMailetProcessor.MailetProcessorListener; +import org.apache.james.mailetcontainer.lib.MailProcessingErrorHandlingConfiguration; import org.apache.james.metrics.api.MetricFactory; import org.apache.james.metrics.api.TimeMetric; import org.apache.james.util.MDCBuilder; @@ -30,7 +31,6 @@ import org.apache.mailet.Attribute; import org.apache.mailet.AttributeValue; import org.apache.mailet.Mail; import org.apache.mailet.Mailet; -import org.apache.mailet.MailetConfig; import org.apache.mailet.base.MailetPipelineLogging; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,12 +44,19 @@ public class ProcessorImpl { private static final Logger LOGGER = LoggerFactory.getLogger(ProcessorImpl.class); private final MetricFactory metricFactory; + private final MailProcessingErrorHandlingConfiguration processingErrorHandlingConfiguration; + private final List<MailetProcessorListener> listeners; private final Mailet mailet; - private final MailetProcessorImpl processor; - public ProcessorImpl(MetricFactory metricFactory, MailetProcessorImpl processor, Mailet mailet) { + public ProcessorImpl( + MetricFactory metricFactory, + Mailet mailet, + MailProcessingErrorHandlingConfiguration processingErrorHandlingConfiguration, + List<MailetProcessorListener> listeners + ) { this.metricFactory = metricFactory; - this.processor = processor; + this.processingErrorHandlingConfiguration = processingErrorHandlingConfiguration; + this.listeners = listeners; this.mailet = mailet; } @@ -81,17 +88,8 @@ public class ProcessorImpl { mailet.service(mail); } catch (Throwable me) { ex = me; - String onMailetException = null; + String onMailetException = processingErrorHandlingConfiguration.onMailetException().map(value -> value.trim().toLowerCase(Locale.US)).orElse(Mail.ERROR); - MailetConfig mailetConfig = mailet.getMailetConfig(); - if (mailetConfig instanceof MailetConfigImpl) { - onMailetException = mailetConfig.getInitParameter("onMailetException"); - } - if (onMailetException == null) { - onMailetException = Mail.ERROR; - } else { - onMailetException = onMailetException.trim().toLowerCase(Locale.US); - } if (onMailetException.equalsIgnoreCase("ignore")) { // ignore the exception and continue // this option should not be used if the mail object can be @@ -101,13 +99,12 @@ public class ProcessorImpl { } else if (onMailetException.equalsIgnoreCase("propagate")) { throw me; } else { - ProcessorUtil.handleException(me, mail, mailet.getMailetConfig().getMailetName(), onMailetException, LOGGER); + ProcessorUtil.handleException(me, mail, mailet.getName(), onMailetException, LOGGER); } } finally { timeMetric.stopAndPublish(); MailetPipelineLogging.logEndOfMailetProcess(mailet, mail); - List<MailetProcessorListener> listeners = processor.getListeners(); long complete = System.currentTimeMillis() - start; if (mail.getRecipients().isEmpty()) { mail.setState(Mail.GHOST); diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/JMXStateMailetProcessorListener.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/JMXStateMailetProcessorListener.java index bc4bdbc09f..028ea14451 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/JMXStateMailetProcessorListener.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/JMXStateMailetProcessorListener.java @@ -25,9 +25,11 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Optional; import javax.management.JMException; import javax.management.MBeanServer; +import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import org.apache.james.core.MailAddress; @@ -36,7 +38,9 @@ import org.apache.james.mailetcontainer.impl.matchers.CompositeMatcher; import org.apache.james.mailetcontainer.lib.AbstractStateMailetProcessor; import org.apache.james.mailetcontainer.lib.AbstractStateMailetProcessor.MailetProcessorListener; import org.apache.mailet.Mailet; +import org.apache.mailet.MailetConfig; import org.apache.mailet.Matcher; +import org.apache.mailet.base.GenericMailet; /** * {@link MailetProcessorListener} implementation which register MBean's for all @@ -98,7 +102,7 @@ public class JMXStateMailetProcessorListener implements MailetProcessorListener, int i = 0; while (mailets.hasNext()) { Mailet mailet = mailets.next(); - MailetManagement mailetManagement = new MailetManagement(mailet.getMailetConfig()); + MailetManagement mailetManagement = new MailetManagement(getOptionalMailetConfig(mailet), mailet.getName()); String mailetMBeanName = parentMBeanName + ",subtype=mailet,index=" + (i++) + ",mailetname=" + mailetManagement.getMailetName(); registerMBean(mailetMBeanName, mailetManagement); @@ -107,6 +111,14 @@ public class JMXStateMailetProcessorListener implements MailetProcessorListener, } + private Optional<MailetConfig> getOptionalMailetConfig(Mailet mailet) throws NotCompliantMBeanException { + if (mailet instanceof GenericMailet m) { + return Optional.ofNullable(m.getMailetConfig()); + } else { + return Optional.empty(); + } + } + /** * Register the {@link Matcher}'s as JMX MBeans */ diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/MailetManagement.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/MailetManagement.java index 5ae817124d..9b48e4b08d 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/MailetManagement.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/impl/jmx/MailetManagement.java @@ -21,6 +21,7 @@ package org.apache.james.mailetcontainer.impl.jmx; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import javax.management.NotCompliantMBeanException; @@ -37,12 +38,13 @@ public final class MailetManagement extends StandardMBean implements MailetManag private final AtomicLong slowestProcessing = new AtomicLong(-1); private final AtomicLong lastProcessing = new AtomicLong(-1); - private final MailetConfig config; + private final Optional<MailetConfig> config; + private final String mailetName; - public MailetManagement(MailetConfig config) throws NotCompliantMBeanException { + public MailetManagement(Optional<MailetConfig> config, String mailetName) throws NotCompliantMBeanException { super(MailetManagementMBean.class); this.config = config; - + this.mailetName = mailetName; } public void update(long processTime, boolean success) { @@ -65,19 +67,22 @@ public final class MailetManagement extends StandardMBean implements MailetManag @Override public String getMailetName() { - return config.getMailetName(); + return mailetName; } @Override public String[] getMailetParameters() { - List<String> parameterList = new ArrayList<>(); - Iterator<String> iterator = config.getInitParameterNames(); - while (iterator.hasNext()) { - String name = iterator.next(); - String value = config.getInitParameter(name); - parameterList.add(name + "=" + value); - } - return parameterList.toArray(String[]::new); + return config.map(c -> { + List<String> parameterList = new ArrayList<>(); + Iterator<String> iterator = c.getInitParameterNames(); + while (iterator.hasNext()) { + String name = iterator.next(); + String value = c.getInitParameter(name); + parameterList.add(name + "=" + value); + } + return parameterList.toArray(String[]::new); + } + ).orElse(new String[0]); } @Override diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateCompositeProcessor.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateCompositeProcessor.java index 77446cee39..a176a7b5d9 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateCompositeProcessor.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateCompositeProcessor.java @@ -42,7 +42,6 @@ import org.apache.james.mailetcontainer.impl.MatcherMailetPair; import org.apache.james.mailetcontainer.impl.ProcessorImpl; import org.apache.james.mailetcontainer.impl.jmx.JMXStateCompositeProcessorListener; import org.apache.mailet.Mail; -import org.apache.mailet.Mailet; import org.apache.mailet.ProcessingState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -137,7 +136,7 @@ public abstract class AbstractStateCompositeProcessor implements MailProcessor, .stream() .filter(MailetProcessorImpl.class::isInstance) .map(MailetProcessorImpl.class::cast) - .flatMap(processor -> processor.getPairs().stream().map(MatcherMailetPair::getMailet)) + .flatMap(processor -> processor.getPairs().stream()) .flatMap(this::requiredProcessorStates) .filter(state -> !state.equals(new ProcessingState("propagate")) && !state.equals(new ProcessingState("ignore")) @@ -151,13 +150,17 @@ public abstract class AbstractStateCompositeProcessor implements MailProcessor, } } - private Stream<ProcessingState> requiredProcessorStates(Mailet mailet) { - return Stream.concat(mailet.requiredProcessingState().stream(), - Stream.of( - Optional.ofNullable(mailet.getMailetConfig().getInitParameter("onMailetException")), - Optional.ofNullable(mailet.getMailetConfig().getInitParameter("onMatchException"))) - .flatMap(Optional::stream) - .map(ProcessingState::new)); + private Stream<ProcessingState> requiredProcessorStates(MatcherMailetPair matcherMailetPair) { + var mailet = matcherMailetPair.getMailet(); + + return Stream.concat( + mailet.requiredProcessingState().stream(), + Stream.of( + matcherMailetPair.onMailetException(), + matcherMailetPair.onMatchException() + ).flatMap(Optional::stream) + .map(ProcessingState::new) + ); } @PostConstruct diff --git a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessor.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessor.java index c031b5e4ea..eb5b6b6c36 100644 --- a/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessor.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessor.java @@ -319,7 +319,8 @@ public abstract class AbstractStateMailetProcessor implements MailProcessor, Con throw new ConfigurationException("Unable to init matcher " + matcherName, ex); } try { - mailet = mailetLoader.getMailet(createMailetConfig(mailetClassName, c)); + MailetConfig mailetConfig = createMailetConfig(mailetClassName, c); + mailet = mailetLoader.getMailet(mailetConfig); LOGGER.info("Mailet {} instantiated.", mailetClassName); } catch (MessagingException ex) { // **** Do better job printing out exception @@ -331,7 +332,13 @@ public abstract class AbstractStateMailetProcessor implements MailProcessor, Con } if (matcher != null && mailet != null) { - pairs.add(new MatcherMailetPair(matcher, mailet)); + var processingErrorConfig = new MailProcessingErrorHandlingConfiguration( + Optional.ofNullable(c.getString("onMailetException")), + Optional.ofNullable(c.getString("onMatchException")) + ); + + + pairs.add(new MatcherMailetPair(matcher, mailet, processingErrorConfig)); } else { throw new ConfigurationException("Unable to load Mailet or Matcher"); } diff --git a/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/MailProcessingErrorHandlingConfiguration.java similarity index 61% copy from server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java copy to server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/MailProcessingErrorHandlingConfiguration.java index ed582c04c1..75b7f1a139 100644 --- a/server/container/guice/mailet/src/test/java/org/apache/james/transport/mailets/sub/ConstructorBoundTestMailet.java +++ b/server/mailet/mailetcontainer-impl/src/main/java/org/apache/james/mailetcontainer/lib/MailProcessingErrorHandlingConfiguration.java @@ -1,46 +1,35 @@ -/**************************************************************** - * 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.transport.mailets.sub; - -import jakarta.inject.Inject; -import jakarta.mail.MessagingException; - -import org.apache.mailet.Mail; -import org.apache.mailet.Mailet; -import org.apache.mailet.MailetConfig; - -public class ConstructorBoundTestMailet implements Mailet { - private final MailetConfig config; - - @Inject - public ConstructorBoundTestMailet(MailetConfig config) { - this.config = config; - } - - @Override - public void service(Mail mail) throws MessagingException { - - } - - @Override - public MailetConfig getMailetConfig() { - return config; +/****************************************************************************** + * 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.mailetcontainer.lib; + +import java.util.Optional; + +public record MailProcessingErrorHandlingConfiguration( + Optional<String> onMailetException, + Optional<String> onMatchException +) { + public static MailProcessingErrorHandlingConfiguration empty() { + return new MailProcessingErrorHandlingConfiguration( + Optional.empty(), + Optional.empty() + + ); } -} +} \ No newline at end of file diff --git a/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/impl/MailetProcessorImplTest.java b/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/impl/MailetProcessorImplTest.java index 51ba22afb0..65d18d6193 100644 --- a/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/impl/MailetProcessorImplTest.java +++ b/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/impl/MailetProcessorImplTest.java @@ -21,6 +21,8 @@ package org.apache.james.mailetcontainer.impl; import static org.mockito.Mockito.mock; +import java.util.Collection; + import org.apache.commons.configuration2.HierarchicalConfiguration; import org.apache.commons.configuration2.tree.ImmutableNode; import org.apache.james.mailetcontainer.api.MailProcessor; @@ -34,22 +36,19 @@ import org.apache.mailet.base.test.FakeMailContext; public class MailetProcessorImplTest extends AbstractStateMailetProcessorTest { @Override - protected AbstractStateMailetProcessor createProcessor(HierarchicalConfiguration<ImmutableNode> configuration) throws Exception { + protected AbstractStateMailetProcessor createProcessor(HierarchicalConfiguration<ImmutableNode> configuration, Collection<AbstractStateMailetProcessor.MailetProcessorListener> listeners) throws Exception { MailetProcessorImpl processor = null; - try { - processor = new MailetProcessorImpl("anyName", new RecordingMetricFactory()); - processor.setMailetContext(FakeMailContext.defaultContext()); - processor.setMailetLoader(new MockMailetLoader()); - processor.setMatcherLoader(new MockMatcherLoader()); - processor.setRootMailProcessor(mock(MailProcessor.class)); - processor.configure(configuration); - processor.init(); - return processor; - } finally { - if (processor != null) { - processor.destroy(); - } + processor = new MailetProcessorImpl("anyName", new RecordingMetricFactory()); + processor.setMailetContext(FakeMailContext.defaultContext()); + processor.setMailetLoader(new MockMailetLoader()); + processor.setMatcherLoader(new MockMatcherLoader()); + processor.setRootMailProcessor(mock(MailProcessor.class)); + processor.configure(configuration); + for (var listener : listeners) { + processor.addListener(listener); } + processor.init(); + return processor; } } diff --git a/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessorTest.java b/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessorTest.java index 8e467d287a..29a04381b9 100644 --- a/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessorTest.java +++ b/server/mailet/mailetcontainer-impl/src/test/java/org/apache/james/mailetcontainer/lib/AbstractStateMailetProcessorTest.java @@ -23,7 +23,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayInputStream; import java.util.Collection; +import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import jakarta.mail.MessagingException; @@ -47,8 +49,10 @@ import org.junit.jupiter.api.Test; public abstract class AbstractStateMailetProcessorTest { - protected abstract AbstractStateMailetProcessor createProcessor(HierarchicalConfiguration<ImmutableNode> configuration) throws - Exception; + protected abstract AbstractStateMailetProcessor createProcessor( + HierarchicalConfiguration<ImmutableNode> configuration, + Collection<AbstractStateMailetProcessor.MailetProcessorListener> listeners + ) throws Exception; private HierarchicalConfiguration<ImmutableNode> createConfig(Class<?> matcherClass, Class<?> mailetClass, int count) throws ConfigurationException { @@ -69,9 +73,7 @@ public abstract class AbstractStateMailetProcessorTest { final CountDownLatch latch = new CountDownLatch(2); final MailImpl mail = newMail(); - AbstractStateMailetProcessor processor = createProcessor(createConfig(MockMatcher.class, MockMailet.class, 1)); - processor.addListener(new MailetProcessorListener() { - + MailetProcessorListener listener = new MailetProcessorListener() { @Override public void afterMatcher(Matcher m, String mailName, Collection<MailAddress> recipients, Collection<MailAddress> matches, long processTime, Throwable e) { @@ -96,7 +98,11 @@ public abstract class AbstractStateMailetProcessorTest { latch.countDown(); } } - }); + }; + AbstractStateMailetProcessor processor = createProcessor( + createConfig(MockMatcher.class, MockMailet.class, 1), + List.of(listener) + ); assertThat(mail.getState()).isEqualTo(Mail.DEFAULT); processor.service(mail); @@ -104,7 +110,7 @@ public abstract class AbstractStateMailetProcessorTest { // the source mail should be ghosted as it reached the end of processor as only one recipient matched assertThat(mail.getState()).isEqualTo(Mail.GHOST); - latch.await(); + assertThat(latch.await(3L, TimeUnit.SECONDS)).isTrue(); processor.destroy(); } @@ -114,8 +120,7 @@ public abstract class AbstractStateMailetProcessorTest { final CountDownLatch latch = new CountDownLatch(2); final MailImpl mail = newMail(); - AbstractStateMailetProcessor processor = createProcessor(createConfig(MockMatcher.class, MockMailet.class, 2)); - processor.addListener(new MailetProcessorListener() { + MailetProcessorListener listener = new MailetProcessorListener() { @Override public void afterMatcher(Matcher m, String mailName, Collection<MailAddress> recipients, @@ -142,7 +147,11 @@ public abstract class AbstractStateMailetProcessorTest { latch.countDown(); } } - }); + }; + AbstractStateMailetProcessor processor = createProcessor( + createConfig(MockMatcher.class, MockMailet.class, 2), + List.of(listener) + ); assertThat(mail.getState()).isEqualTo(Mail.DEFAULT); processor.service(mail); @@ -150,7 +159,7 @@ public abstract class AbstractStateMailetProcessorTest { // the source mail should have the new state as it was a full match assertThat(mail.getState()).isEqualTo("test"); - latch.await(); + assertThat(latch.await(3L, TimeUnit.SECONDS)).isTrue(); processor.destroy(); } @@ -160,9 +169,7 @@ public abstract class AbstractStateMailetProcessorTest { final CountDownLatch latch = new CountDownLatch(1); final MailImpl mail = newMail(); - AbstractStateMailetProcessor processor = createProcessor(createConfig(ExceptionThrowingMatcher.class, - MockMailet.class, 0)); - processor.addListener(new MailetProcessorListener() { + MailetProcessorListener listener = new MailetProcessorListener() { @Override public void afterMatcher(Matcher m, String mailName, Collection<MailAddress> recipients, @@ -181,7 +188,11 @@ public abstract class AbstractStateMailetProcessorTest { public void afterMailet(Mailet m, String mailName, String state, long processTime, Throwable e) { throw new RuntimeException("Should not call any mailet!"); } - }); + }; + AbstractStateMailetProcessor processor = createProcessor( + createConfig(ExceptionThrowingMatcher.class, MockMailet.class, 0), + List.of(listener) + ); assertThat(mail.getState()).isEqualTo(Mail.DEFAULT); @@ -189,7 +200,7 @@ public abstract class AbstractStateMailetProcessorTest { // the source mail should have state error as the exception was thrown assertThat(mail.getState()).isEqualTo(Mail.ERROR); - latch.await(); + assertThat(latch.await(3L, TimeUnit.SECONDS)).isTrue(); processor.destroy(); } @@ -199,9 +210,7 @@ public abstract class AbstractStateMailetProcessorTest { final CountDownLatch latch = new CountDownLatch(1); final MailImpl mail = newMail(); - AbstractStateMailetProcessor processor = createProcessor(createConfig(ExceptionThrowingMatcher.class, - MockMailet.class, 0)); - processor.addListener(new MailetProcessorListener() { + MailetProcessorListener listener = new MailetProcessorListener() { @Override public void afterMatcher(Matcher m, String mailName, Collection<MailAddress> recipients, @@ -216,14 +225,18 @@ public abstract class AbstractStateMailetProcessorTest { public void afterMailet(Mailet m, String mailName, String state, long processTime, Throwable e) { throw new RuntimeException("Should not call any mailet!"); } - }); + }; + AbstractStateMailetProcessor processor = createProcessor( + createConfig(ExceptionThrowingMatcher.class, MockMailet.class, 0), + List.of(listener) + ); processor.service(mail); // the source mail should have captured the exception which was thrown assertThat(mail.getAttribute(Mail.MAILET_ERROR)).hasValueSatisfying(attribute -> assertThat(attribute.getValue().value().getClass()).isEqualTo(MessagingException.class)); - latch.await(); + assertThat(latch.await(3L, TimeUnit.SECONDS)).isTrue(); processor.destroy(); } @@ -232,9 +245,7 @@ public abstract class AbstractStateMailetProcessorTest { final CountDownLatch latch = new CountDownLatch(2); final MailImpl mail = newMail(); - AbstractStateMailetProcessor processor = createProcessor(createConfig(MockMatcher.class, - ExceptionThrowingMailet.class, 1)); - processor.addListener(new MailetProcessorListener() { + MailetProcessorListener listener = new MailetProcessorListener() { @Override public void afterMatcher(Matcher m, String mailName, Collection<MailAddress> recipients, @@ -259,7 +270,11 @@ public abstract class AbstractStateMailetProcessorTest { latch.countDown(); } } - }); + }; + AbstractStateMailetProcessor processor = createProcessor( + createConfig(MockMatcher.class, ExceptionThrowingMailet.class, 1), + List.of(listener) + ); assertThat(mail.getState()).isEqualTo(Mail.DEFAULT); @@ -272,11 +287,11 @@ public abstract class AbstractStateMailetProcessorTest { private MailImpl newMail() throws MessagingException { return MailImpl.builder() - .name(MailImpl.getId()) - .sender("test@localhost") - .addRecipient("test@localhost") - .addRecipient("test2@localhost") - .mimeMessage(MimeMessageUtil.mimeMessageFromBytes("header: value\r\n".getBytes(UTF_8))) - .build(); + .name(MailImpl.getId()) + .sender("test@localhost") + .addRecipient("test@localhost") + .addRecipient("test2@localhost") + .mimeMessage(MimeMessageUtil.mimeMessageFromBytes("header: value\r\n".getBytes(UTF_8))) + .build(); } } diff --git a/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/HelloWorldMailet.java b/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/HelloWorldMailet.java index 186d08756b..8dcfd2744c 100644 --- a/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/HelloWorldMailet.java +++ b/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/HelloWorldMailet.java @@ -38,13 +38,13 @@ public class HelloWorldMailet implements Mailet { } @Override - public String getMailetInfo() { - return "Example mailet"; + public String getName() { + return config.getMailetName(); } @Override - public MailetConfig getMailetConfig() { - return config; + public String getMailetInfo() { + return "Example mailet"; } @Override diff --git a/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/InstrumentationMailet.java b/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/InstrumentationMailet.java index 9523513d60..046696f917 100644 --- a/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/InstrumentationMailet.java +++ b/server/mailet/mailets/src/test/java/org/apache/james/samples/mailets/InstrumentationMailet.java @@ -53,13 +53,13 @@ public class InstrumentationMailet implements Mailet { } @Override - public String getMailetInfo() { - return "Example mailet"; + public String getName() { + return config.getMailetName(); } @Override - public MailetConfig getMailetConfig() { - return config; + public String getMailetInfo() { + return "Example mailet"; } @Override diff --git a/upgrade-instructions.md b/upgrade-instructions.md index 755ef83bad..c7a01d6f8f 100644 --- a/upgrade-instructions.md +++ b/upgrade-instructions.md @@ -36,6 +36,19 @@ Change list: - [JAMES-4052 Details in quota index](#james-4052-details-in-quota-index) - [JAMES-1409 Change JPARecipientRewriteTable to store separate record per target address](#james-1409-change-jparecipientrewritetable-to-store-separate-record-per-target-address) - [JAMES-4118 Cleanup message previews](#james-4118-cleanup-message-previews) + - [JAMES-4128 Breaking Mailet API changes](#james-4128-breaking-mailet-api-changes) + +### JAMES-4128 Breaking Mailet API changes +Date: 02/04/2025 + +JIRA: https://issues.apache.org/jira/browse/JAMES-4126 + +The Mailet API has been slightly reworked to improve mailet encapsulation and make implementation easier. + +- Method getMailetConfig() has been removed +- Method getName() has been added with a default to the simple class name +- implementers no longer have to override getMailetInfo, init or destroy +- implementers of mailets can inject the configuration through the constructor when using guice. Constructor injection of the config is not compatible with spring applications. ### JAMES-4118 Cleanup message previews --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org