This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 0b8557b02560fc9603b6bf6ea002dbe225b8e60c Author: Benoit TELLIER <[email protected]> AuthorDate: Fri Aug 28 18:22:44 2026 +0700 [DOC] Harden dev section following src/site --- docs/modules/development/nav.adoc | 3 + .../development/pages/build-from-source.adoc | 159 +++++++++++++++++++++ docs/modules/development/pages/index.adoc | 6 + docs/modules/development/pages/source-code.adoc | 96 +++++++++++++ 4 files changed, 264 insertions(+) diff --git a/docs/modules/development/nav.adoc b/docs/modules/development/nav.adoc index ab8cd95318..8356798a3c 100644 --- a/docs/modules/development/nav.adoc +++ b/docs/modules/development/nav.adoc @@ -1,2 +1,5 @@ * xref:index.adoc[] +** xref:source-code.adoc[] +** xref:build-from-source.adoc[] ** xref:logging.adoc[] +** xref:deployment-tests.adoc[] diff --git a/docs/modules/development/pages/build-from-source.adoc b/docs/modules/development/pages/build-from-source.adoc new file mode 100644 index 0000000000..c8c238b483 --- /dev/null +++ b/docs/modules/development/pages/build-from-source.adoc @@ -0,0 +1,159 @@ += Building Apache James from source +:navtitle: Building from source + +Running James does not require building it: every application is published as a +link:https://hub.docker.com/r/apache/james[docker image] and as an archive on the +link:https://james.apache.org/download.cgi[download page]. You need to build only to work on James itself, to try +out an unreleased change, or to ship your own assembly of its components. + +== Getting the sources + +The whole project - the servers, the mailbox, the protocol implementations, the mailets - lives in a single git +repository: + +[source,bash] +---- +$ git clone https://github.com/apache/james-project.git +$ cd james-project +---- + +The `master` branch is the development branch: it builds, its tests pass, but it is not a release. Released +versions are tagged. + +== Requirements + +* A *JDK {java-version}*. James is compiled with `--release {java-version}` and will not build on an older one. +* *Maven 3.8.1* or later. Older versions are rejected by the build itself, through the maven enforcer plugin. + +The build is memory hungry - it compiles Java and Scala, and runs a large test suite. Give Maven some room: + +[source,bash] +---- +$ export MAVEN_OPTS="-Xmx2g" +---- + +== Building + +From the root of the repository: + +[source,bash] +---- +$ mvn clean install -DskipTests +---- + +This compiles every module and installs the artifacts in your local repository. The usual Maven lifecycle applies: +`clean` wipes the `target` folders, `compile` builds the classes, `test` runs the unit tests, `install` produces +and installs the packaged artifacts. + +*Skipping the tests is not optional in practice*: a full run takes hours, as a large part of the suite starts +Cassandra, OpenSearch, RabbitMQ and S3 containers through +link:https://www.testcontainers.org/[Testcontainers], and therefore needs a working docker daemon. Run the tests of +the module you are working on instead: + +[source,bash] +---- +$ mvn test -pl mailbox/store +---- + +=== Where the applications land + +Each application produces, in its own `target` folder, a jar and a `.lib` folder holding its dependencies: + +* `server/apps/distributed-app/target` - xref:servers:distributed/index.adoc[Distributed server] +* `server/apps/postgres-app/target` - xref:servers:postgres/index.adoc[Postgres server] +* `server/apps/jpa-app/target` - xref:servers:jpa/index.adoc[JPA server] +* `server/apps/memory-app/target` - xref:servers:test.adoc[Memory server] +* `server/apps/spring-app/target` - xref:servers:spring/index.adoc[Spring server], packaged as a zip holding the +whole `bin`/`conf`/`lib`/`var` layout + +Each server's *Run with Java* page - xref:servers:distributed/run/run-java.adoc[Distributed], +xref:servers:postgres/run/run-java.adoc[Postgres], xref:servers:jpa/run/run-java.adoc[JPA], +xref:servers:spring/run.adoc[Spring] - documents how to start what you just built. + +=== Building the docker images + +The Guice applications are containerised with +link:https://github.com/GoogleContainerTools/jib[jib], which needs no docker daemon to build the image. The build +writes a `jib-image.tar` next to the jar, which you then load: + +[source,bash] +---- +$ docker image load -i server/apps/distributed-app/target/jib-image.tar +---- + +=== Running the CLI from the sources + +The xref:servers:distributed/operate/cli.adoc[command line interface] can be run without packaging it, from +`server/apps/cli`: + +[source,bash] +---- +$ mvn exec:java -Dexec.args="-h localhost -p 9999 listdomains" +---- + +== Working on James in an IDE + +James is a Java *and Scala* project - JMAP in particular is written in Scala. Any IDE you use has to support both; +this is the reason the project no longer documents an Eclipse set up. + +=== IntelliJ IDEA + +Open the root `pom.xml` as a project and let the Maven importer run. Three plugins are worth installing: + +* *Scala*, without which a good part of JMAP will not resolve; +* *CheckStyle-IDEA*, to catch style violations before the build does. Declare the `checkstyle.xml` file sitting at +the root of the repository under *Settings > Tools > Checkstyle*, then scan a file, a module or the project from +the CheckStyle panel; +* *AsciiDoc*, to preview the documentation you are reading. + +=== Import layout + +Checkstyle enforces the order of the imports, and getting it wrong is the most common reason for a build to fail +on a otherwise correct change. Configure your IDE to produce it - in IntelliJ IDEA, under +*Settings > Editor > Code Style > Java > Imports* and *> Scala > Imports*. + +For Java: + +.... +import static all other imports + +import java.* + +import javax.* + +import jakarta.* + +import org.* + +import com.* + +import all other imports +.... + +For Scala: + +.... +base package imports + +java + +all other imports + +scala +.... + +=== The OpenJPA agent + +The JPA based applications need the OpenJPA java agent, which performs the runtime enhancement of the entity +classes. Running `mvn package` does that enhancement at build time; if you start a JPA application from your IDE +instead, add the agent to the VM options of your run configuration: + +.... +-javaagent:$HOME/.m2/repository/org/apache/openjpa/openjpa/4.1.1/openjpa-4.1.1.jar +.... + +== Contributing your change back + +xref:james-site::contributing.adoc[The contribution guidelines] describe how to get a change reviewed and merged. +The xref:logging.adoc[logging conventions] and the +xref:servers:distributed/customization/index.adoc[extension mechanisms] are worth reading before writing code. diff --git a/docs/modules/development/pages/index.adoc b/docs/modules/development/pages/index.adoc index 9b56baa8b4..642c500f4d 100644 --- a/docs/modules/development/pages/index.adoc +++ b/docs/modules/development/pages/index.adoc @@ -5,6 +5,12 @@ This page aggregates common knowledge for contributing to Apache james servers. xref:james-site::contributing.adoc[Contribution guidelines] apply. +xref:source-code.adoc[This page] maps the code base: how the modules are organised, and where a change belongs. + +xref:build-from-source.adoc[This page] explains how to *build James from source*, and how to set up an IDE for it. + xref:logging.adoc[This page] explains how *logging* should be done. +xref:deployment-tests.adoc[This page] explains how to run the *deployment tests*. + Help of kind contributors is more than welcome to write guides explaining newcomers your hard-learned lessons! diff --git a/docs/modules/development/pages/source-code.adoc b/docs/modules/development/pages/source-code.adoc new file mode 100644 index 0000000000..558c2acd33 --- /dev/null +++ b/docs/modules/development/pages/source-code.adoc @@ -0,0 +1,96 @@ += How the James code base is organised +:navtitle: Code base organisation + +Apache James is not a single application but a *set of components* that get assembled into one. The servers +documented in xref:servers:index.adoc[the servers section] are precisely such assemblies: the same mailbox, the +same protocol implementations and the same mailet container, wired onto different storage backends. This page maps +the repository so that you know where to look, and where a change belongs. + +== The three kinds of module + +Every module of the repository falls into one of three categories, and the dependency rules between them are what +keeps the project assemblable: + +API:: +Interfaces and value objects, with no implementation detail and next to no dependency. `mailet/api`, +`mailbox/api`, `protocols/api`, `metrics/metrics-api`, `event-bus/api` are the ones you will meet most often. An +API module must stay implementable by a backend that does not exist yet. + +Library:: +Reusable code that depends only on API modules and on third party jars, never on another library. `mailet/base` +and `core` are examples. A library is justified only when several functions share it. + +Function:: +Everything else - an implementation of an API, a protocol, a storage backend. Functions should depend on APIs and +libraries, and as little as possible on each other: it is code reuse that is expected between them, not direct +reuse of a jar. + +The practical consequence is that a new storage backend is written by implementing the API modules, without +touching anything else, and is then wired into an application by a Guice module. + +== The main modules + +`core`:: +The domain objects shared by everything: `Username`, `Domain`, `MailAddress`, `MaybeSender`, and the `Mail` +implementation itself. + +`mailet`:: +The link:https://james.apache.org/mailet/api/[Mailet API] - `Mailet`, `Matcher`, `MailetConfig` - in +`mailet/api`, the `GenericMailet` toolkit in `mailet/base`, and the packaged mailets and matchers in +`mailet/standard`, `mailet/crypto` (S/MIME), `mailet/icalendar` and `mailet/amqp`. `mailet/mailetdocs-maven-plugin` +extracts the javadoc of those classes into the reference lists you can read in the +xref:servers:distributed/configure/mailets.adoc[configuration pages]. + +`mailbox`:: +The storage of the emails. `mailbox/api` defines `MailboxManager`, `MessageManager` and `SubscriptionManager`; +`mailbox/store` holds the backend agnostic logic built on top of a set of mappers; and one module per backend +implements those mappers - `mailbox/cassandra`, `mailbox/postgres`, `mailbox/jpa`, `mailbox/memory`. Search is +pluggable the same way: `mailbox/opensearch`, `mailbox/lucene` and `mailbox/scanning-search`. + +`protocols`:: +The protocol implementations, kept independent of the mailbox: `protocols/smtp`, `protocols/imap`, +`protocols/pop3`, `protocols/lmtp`, `protocols/managesieve`, the SASL mechanisms in `protocols/sasl`, and the +Netty plumbing they share in `protocols/netty`. + +`server`:: +The server itself. `server/data` holds the users, domains, rewriting rules and mail repositories, again with one +module per backend; `server/mailet` the mailet container; `server/queue` the mail queue implementations; +`server/protocols` the glue binding the protocol implementations to the mailbox, and the WebAdmin routes; +`server/container` the Guice and Spring wiring; and `server/apps` the assemblies that make up the shipped +applications. + +`backends-common`:: +The low level clients of the storage dependencies - Cassandra, Postgres, OpenSearch, RabbitMQ, Redis, Pulsar - +along with the test resources that start them in a container. + +`event-bus`, `event-sourcing`, `json`, `metrics`, `mdn`:: +Cross cutting infrastructure: event distribution, event sourced aggregates, JSON serialisation, metric collection, +message disposition notifications. + +`mpt`:: +The Mail Protocols Tester, a scripted protocol testing framework used to check the IMAP and SMTP implementations +against recorded sessions. See xref:deployment-tests.adoc[running deployment tests]. + +`examples`:: +Working examples of every extension mechanism - custom mailets, matchers, SMTP hooks, mailbox listeners, WebAdmin +routes - each one a small maven project you can copy. The +xref:servers:distributed/customization/index.adoc[customization section] walks through them. + +== Standards compliance + +James implements published standards, most of them IETF RFCs, and treats them as its requirements document: what +each server implements is listed on its *implemented standards* page - +xref:servers:distributed/architecture/implemented-standards.adoc[Distributed], +xref:servers:postgres/architecture/implemented-standards.adoc[Postgres], +xref:servers:jpa/architecture/implemented-standards.adoc[JPA], +xref:servers:spring/architecture/implemented-standards.adoc[Spring]. + +This occasionally conflicts with what other implementations actually do. The project's position is that adhering +to the published standard is what makes interoperability achievable without access to undocumented behaviour, and +therefore: + +* a deviation from a standard, when it is needed and can be worked around safely, is *disabled by default*, +prominently documented as a violation, and enabled by an explicit configuration option - so that using it is a +conscious decision of the operator; +* a behaviour that no standard James claims to support covers - a de-facto convention, a draft RFC - may be +implemented, provided it is documented well enough that operators know what to expect. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
