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.donohoedigital shared uniformly across all artifacts
  • Version: 3.0 synchronized 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 logging
  • db – Database abstractions
  • ddpoker – Stand-alone poker library

Infrastructure modules:

  • mail → depends on common
  • gui → depends on common
  • server → depends on common
  • udp → depends on common
  • installer → depends on common
  • tools → depends on common

Web and application layers:

  • wicket → depends on common, gui, mail
  • jsp → depends on common, gui

Game engine hierarchy:

  • gamecommon → depends on server
  • gameengine → depends on server
  • gameserver → depends on server, gamecommon
  • gametools → depends on common, gameserver

Poker-specific stack:

  • pokerengine → depends on db, gamecommon, ddpoker
  • pokernetwork → depends on pokerengine, udp
  • poker → depends on pokerengine, gameengine, gameserver
  • pokerserver → depends on pokerengine, gamecommon, mail
  • pokerwicket → depends on pokerengine, wicket, gui
  • proto → depends on common (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:

  1. 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>
  1. Add <module>analyticsserver</module> to the parent pom.xml in the appropriate position (after pokerengine in this case).

  2. Run mvn clean install to 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.xml aggregates 23 modules and centralizes dependency versions for Java 25, Spring, Hibernate, and Wicket.
  • Inter-module dependencies use the shared com.donohoedigital groupId and version 3.0, with Maven resolving the directed acyclic graph automatically during reactor builds.
  • Foundation modules like common, db, and server provide core functionality with minimal coupling, while specialized modules like pokerengine and pokerserver compose 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →