# S04 — Modules, records, Optional and dates Guide: (Step 5) and the "Dependency Footprint" table [`before/S04ModulesAndRecords.java`](../jackson2-before/src/main/java/com/ankurm/migration/before/S04ModulesAndRecords.java) · [`after/S04ModulesAndRecords.java`](../jackson3-after/src/main/java/com/ankurm/migration/after/S04ModulesAndRecords.java) The clearest win in the whole migration. Compare the two poms: **[`jackson2-before/pom.xml`](../jackson2-before/pom.xml)** — four artifacts plus a compiler flag: ```xml com.fasterxml.jackson.core:jackson-databind com.fasterxml.jackson.datatype:jackson-datatype-jsr310 com.fasterxml.jackson.datatype:jackson-datatype-jdk8 com.fasterxml.jackson.module:jackson-module-parameter-names ... -parameters ``` **[`jackson3-after/pom.xml`](../jackson3-after/pom.xml)** — one artifact, no compiler args: ```xml tools.jackson.core:jackson-databind ``` The three module classes have no `tools.jackson` equivalent, so leaving the `registerModule` calls in place is a compile error, not a no-op. Delete them. ## Output **Jackson 2 — `jackson2-before`** ``` with modules : {"id":1,"departure":"2026-09-15","seat":"12A"} round-trip : TravelPlan[id=1, departure=2026-09-15, seat=Optional[12A]] bare mapper : FAILS -> InvalidDefinitionException bare, dates only: FAILS -> InvalidDefinitionException ``` **Jackson 3 — `jackson3-after`** ``` no modules : {"id":1,"departure":"2026-09-15","seat":"12A"} round-trip : TravelPlan[id=1, departure=2026-09-15, seat=Optional[12A]] dates : {"d":"2026-09-15"} empty Optional : {"id":2,"departure":"2026-09-16","seat":null} ``` The first two lines are byte-identical across versions. The difference is everything that had to be set up to get there. The `bare mapper` lines in the Jackson 2 output are the point: without the modules, a Jackson 2 mapper cannot serialise `Optional` or `LocalDate` at all — it throws `InvalidDefinitionException`. The Jackson 3 mapper in the "after" file has no modules registered because there are none to register.