Maven Multi-Module Project Structure and Module Dependencies in DD Poker
The DD Poker repository implements a classic Maven aggregator architecture where a parent POM at code/pom.xml coordinates 23 child modules sharing the com.donohoedigital groupId and version 3.0, with inter-module dependencies resolved automatically through standard Maven dependency declarations.
The DD Poker open-source project demonstrates enterprise-grade Maven organization for a complex Java application spanning poker engines, network protocols, and web interfaces. Understanding its Maven multi-module project structure and module dependencies reveals how the codebase maintains clean separation of concerns through modular architecture and standardized build configuration.
Parent Aggregator POM Structure
The foundation of the build system resides in code/pom.xml, which serves as both the parent and aggregator POM. This file declares the <modules> section listing all 23 sub-modules in exact build order, ensuring Maven compiles foundational libraries before dependent applications.
Key configurations defined in the parent include:
- Group ID:
com.donohoedigitalshared uniformly across all artifacts - Version:
3.0synchronized across the entire project - Java Target: Java 25 via the Maven Compiler Plugin
- Dependency Management: Centralized version properties for Log4j2, SLF4J, Spring, Hibernate, Jetty, JUnit, and Apache Wicket
The parent POM uses <packaging>pom</packaging> and the artifactId all, distinguishing it as an aggregator rather than a deployable artifact.
Child Module Configuration
Each module resides in a subdirectory under code/ and inherits from the parent through a standardized POM template. The server module at code/server/pom.xml illustrates this pattern:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.donohoedigital</groupId>
<artifactId>all</artifactId>
<version>3.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>server</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.donohoedigital</groupId>
<artifactId>common</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${servlet.api.version}</version>
</dependency>
</dependencies>
</project>
Child modules declare intra-project dependencies by referencing sibling artifactIds with the shared groupId. Maven resolves these automatically during the reactor build, placing dependent JARs on the classpath according to the dependency graph.
Inter-Module Dependency Graph
The 23 modules form a directed acyclic graph that determines compilation order. The parent POM sequences modules so that foundational utilities build first, while higher-level game logic modules build last.
Foundation modules (no intra-project dependencies):
common– Core utilities and loggingdb– Database abstractionsddpoker– Stand-alone poker library
Infrastructure modules:
mail→ depends oncommongui→ depends oncommonserver→ depends oncommonudp→ depends oncommoninstaller→ depends oncommontools→ depends oncommon
Web and application layers:
wicket→ depends oncommon,gui,mailjsp→ depends oncommon,gui
Game engine hierarchy:
gamecommon→ depends onservergameengine→ depends onservergameserver→ depends onserver,gamecommongametools→ depends oncommon,gameserver
Poker-specific stack:
pokerengine→ depends ondb,gamecommon,ddpokerpokernetwork→ depends onpokerengine,udppoker→ depends onpokerengine,gameengine,gameserverpokerserver→ depends onpokerengine,gamecommon,mailpokerwicket→ depends onpokerengine,wicket,guiproto→ depends oncommon(network protocol utilities)
Practical Build Examples
Compiling the Entire Project
To build all modules in dependency order, execute from the code/ directory:
cd code
mvn clean install
Maven automatically detects the parent POM, reads the <modules> list, and constructs the reactor build plan. The common module compiles first, followed by mail, gui, and proceeding upward through pokerengine to pokerwicket.
Adding Functionality Across Modules
When adding a feature that uses utilities from common within the gui module, import classes normally:
package com.donohoedigital.myfeature;
import com.donohoedigital.common.Logging;
public class MyFeature {
public void initialize() {
Logging.info("Feature initialized");
}
}
The gui/pom.xml already declares the common dependency, so the compiler resolves the Logging class without additional configuration.
Creating a New Module
To extend the project with a new module named analyticsserver:
- Create
code/analyticsserver/pom.xml:
<project>
<parent>
<groupId>com.donohoedigital</groupId>
<artifactId>all</artifactId>
<version>3.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>analyticsserver</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.donohoedigital</groupId>
<artifactId>pokerengine</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
</project>
-
Add
<module>analyticsserver</module>to the parentpom.xmlin the appropriate position (afterpokerenginein this case). -
Run
mvn clean installto verify the module integrates correctly into the build reactor.
Running Multi-Module Tests
Unit tests in higher-level modules automatically receive transitive dependencies. A test class in pokerserver can instantiate PokerServer (from the same module) which internally uses Logging (from common) and GameEvent (from gamecommon), because pokerserver/pom.xml declares:
<dependencies>
<dependency>
<groupId>com.donohoedigital</groupId>
<artifactId>pokerengine</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.donohoedigital</groupId>
<artifactId>gamecommon</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.donohoedigital</groupId>
<artifactId>mail</artifactId>
<version>3.0</version>
</dependency>
</dependencies>
Summary
- The parent POM at
code/pom.xmlaggregates 23 modules and centralizes dependency versions for Java 25, Spring, Hibernate, and Wicket. - Inter-module dependencies use the shared
com.donohoedigitalgroupId and version 3.0, with Maven resolving the directed acyclic graph automatically during reactor builds. - Foundation modules like
common,db, andserverprovide core functionality with minimal coupling, while specialized modules likepokerengineandpokerservercompose these into game-specific logic. - Build order is enforced by the parent POM's
<modules>list, ensuring compile-time dependencies are satisfied before dependent modules build.
Frequently Asked Questions
How do I add a new module to the DD Poker Maven project?
Create a new directory under code/ with a pom.xml declaring the parent as com.donohoedigital:all:3.0, specify your artifactId and dependencies, then add the module name to the <modules> list in code/pom.xml. Position the entry after all modules your new code depends on to maintain correct build order.
What determines the compilation order of modules?
Maven calculates the reactor build order from the <modules> sequence in the parent POM combined with the explicit dependency graph declared in each module's <dependencies> section. The parent POM lists modules such that common builds first, followed by infrastructure modules like server and mail, then game logic modules like pokerengine, and finally application modules like pokerwicket.
Which modules have no dependencies on other DD Poker modules?
The common, db, and ddpoker modules serve as the foundation with zero intra-project dependencies. The common module provides logging and utility classes used by nearly every other module, while db offers database abstractions and ddpoker contains stand-alone poker logic.
How are third-party library versions managed across all modules?
The parent POM at code/pom.xml defines version numbers as properties (e.g., ${log4j2.version}, ${spring.version}). Child modules reference these properties in their dependency declarations, ensuring consistent versions of Log4j2, SLF4J, Servlet API, and testing frameworks across the entire multi-module project.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →