The Apache Software Foundation

Write Custom James server assembly

Find this example on GitHub.

The current project demonstrates how to write a custom assembly in order to write your own tailor-made server.

    This enables:
  • Arbitrary composition of technologies (example JPA mailbox with Cassandra user management)
  • Write any additional components
  • Drop any unneeded component
  • You have control on the dependencies and can reduce the classpath size

Example: Write an IMAP+SMTP only memory server

In order to do this select the modules you wished to assemble in the Guice building blocks. We encourage you to have a fine grain control of your dependencies but for the sake of simplicity this example will reuse the dependencies of an existing James application:

<dependency>
 <groupId>${james.groupId}</groupId>
 <artifactId>james-server-memory-app</artifactId>
 <version>${project.version}</version>
</dependency>

Once done assemble the guice modules together in a class implementing JamesServerMain:

public class CustomJamesServerMain implements JamesServerMain {
 public static final Module PROTOCOLS = Modules.combine(
 new IMAPServerModule(),
 new ProtocolHandlerModule(),
 new MailRepositoryTaskSerializationModule(),
 new SMTPServerModule());
 public static final Module CUSTOM_SERVER_MODULE = Modules.combine(
 new MailetProcessingModule(),
 new MailboxModule(),
 new MemoryDataModule(),
 new MemoryEventStoreModule(),
 new MemoryMailboxModule(),
 new MemoryMailQueueModule(),
 new TaskManagerModule(),
 new RawPostDequeueDecoratorModule(),
 binder -> binder.bind(MailetContainerModule.DefaultProcessorsConfigurationSupplier.class)
 .toInstance(BaseHierarchicalConfiguration::new));
 public static final Module CUSTOM_SERVER_AGGREGATE_MODULE = Modules.combine(
 CUSTOM_SERVER_MODULE,
 PROTOCOLS);
 public static void main(String[] args) throws Exception {
 Configuration configuration = Configuration.builder()
 .useWorkingDirectoryEnvProperty()
 .build();
 JamesServerMain.main(GuiceJamesServer.forConfiguration(configuration)
 .combineWith(CUSTOM_SERVER_AGGREGATE_MODULE));
 }
 }

You need to write a minimal main method launching your guice module composition.

We do provide in this example JIB to package this custom James assembly into docker:

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>jib-maven-plugin</artifactId>
 <version>2.7.1</version>
 <configuration>
 <from>
 <image>adoptopenjdk:11-jdk-hotspot</image>
 </from>
 <to>
 <image>apache/james</image>
 <tags>
 <tag>custom-latest</tag>
 </tags>
 </to>
 <container>
 <mainClass>org.apache.james.examples.CustomJamesServerMain</mainClass>
 <ports>
 <port>25</port> <!-- JMAP -->
 <port>143</port> <!-- IMAP -->
 </ports>
 <appRoot>/root</appRoot>
 <jvmFlags>
 <jvmFlag>-Dlogback.configurationFile=/root/conf/logback.xml</jvmFlag>
 <jvmFlag>-Dworking.directory=/root/</jvmFlag>
 </jvmFlags>
 <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
 </container>
 <extraDirectories>
 <paths>
 <path>
 <from>sample-configuration</from>
 <into>/root/conf</into>
 </path>
 </paths>
 </extraDirectories>
 </configuration>
 <executions>
 <execution>
 <goals>
 <goal>buildTar</goal>
 </goals>
 <phase>package</phase>
 </execution>
 </executions>
</plugin>}

We provide a minimal sample configuration.

You can compile this example project:

mvn clean install

Create a keystore (default password being james72laBalle):

keytool -genkey -alias james -keyalg RSA -keystore keystore

Import the build result:

$ docker load -i target/jib-image.tar

Then launch your custom server with docker:

docker run \
 -v $PWD/keystore:/root/conf/keystore \
 -p 25:25 \
 -p 143:143 \
 -ti \
 apache/james:custom-latest
 

You will see that your custom James server starts smoothly:

...
09:40:25.884 [INFO ] o.a.j.GuiceJamesServer - JAMES server started

AltStyle によって変換されたページ (->オリジナル) /