|
| 1 | +# Upgrade prompt: `com.open-elements:java-parent` 1.0.0 → 1.1.0 |
| 2 | + |
| 3 | +## Prompt |
| 4 | + |
| 5 | +You are upgrading a Maven project that uses `com.open-elements:java-parent` as its `<parent>`, moving from `1.0.0` to `1.1.0`. This is a **minor release that is breaking-light**: nothing fails to compile from the bump alone, but the parent **stops contributing two build settings that children inherited in `1.0.0`** — the `-parameters` compiler flag and the Surefire `--add-opens` test JVM flags. Code that relied on either can change behavior or fail **at runtime / during tests**, silently, with no compile error. |
| 6 | + |
| 7 | +There are **no managed-dependency version changes** (Spring Boot stays `3.5.14`, Testcontainers stays `2.0.5`) and **no API/code changes** — this is a build-model change only. The two additive items (an active Spotless config and `git-commit-id` manifest stamping) require **no consumer action**. Apply exactly the changes below and nothing outside this scope. |
| 8 | + |
| 9 | +### What changed in 1.1.0 |
| 10 | + |
| 11 | +#### Dependencies |
| 12 | + |
| 13 | +Bump only the `<parent>` version of `com.open-elements:java-parent` to `1.1.0`. The **BOM-managed versions are unchanged**: `spring-boot-dependencies` stays at `3.5.14` and `testcontainers-bom` stays at `2.0.5`, both still imported via the parent's `<dependencyManagement>`. Do **not** bump those, and do **not** bump any Maven / JReleaser / CycloneDX / Spotless / git-commit-id plugin version in the consumer — the plugin set in `1.1.0` is internal to the parent and has no consumer-facing version effect. |
| 14 | + |
| 15 | +#### Breaking-light: parent no longer adds `-parameters` to the compiler |
| 16 | + |
| 17 | +In `1.0.0` the parent's top-level `<build><plugins>` actively configured the compiler so that **method/constructor parameter names were retained in the bytecode**: |
| 18 | + |
| 19 | +```xml |
| 20 | +<!-- present in 1.0.0 (parent <build><plugins>), REMOVED in 1.1.0 --> |
| 21 | +<plugin> |
| 22 | + <groupId>org.apache.maven.plugins</groupId> |
| 23 | + <artifactId>maven-compiler-plugin</artifactId> |
| 24 | + <configuration> |
| 25 | + <parameters>true</parameters> |
| 26 | + </configuration> |
| 27 | +</plugin> |
| 28 | +``` |
| 29 | + |
| 30 | +In `1.1.0` this block is gone. The `maven-compiler-plugin` is still **version-managed** in the parent's `<pluginManagement>` (`3.15.0`), but it no longer sets `<parameters>true</parameters>`, so children compile **without** `-parameters` unless they set it themselves. This compiles cleanly — the breakage is at **runtime**, in frameworks that look up parameters by name: |
| 31 | + |
| 32 | +- Spring MVC handler args without an explicit name: `@PathVariable Long id`, `@RequestParam String q` → `IllegalArgumentException: Name for argument of type [...] not specified, and parameter name information not available via reflection`. |
| 33 | +- Spring Data derived/`@Query` method parameters bound by name. |
| 34 | +- Jackson `ParameterNamesModule` constructor binding. |
| 35 | +- Any code calling `Parameter#getName()` and expecting the real name instead of `arg0`, `arg1`, … |
| 36 | + |
| 37 | +A consumer that **relies on parameter-name retention** must restore the flag in its **own** `pom.xml`: |
| 38 | + |
| 39 | +```xml |
| 40 | +<!-- Add to the consumer's <build><plugins> only if it relies on -parameters --> |
| 41 | +<plugin> |
| 42 | + <groupId>org.apache.maven.plugins</groupId> |
| 43 | + <artifactId>maven-compiler-plugin</artifactId> |
| 44 | + <configuration> |
| 45 | + <parameters>true</parameters> |
| 46 | + </configuration> |
| 47 | +</plugin> |
| 48 | +``` |
| 49 | + |
| 50 | +A consumer that does not depend on parameter names (or already sets `-parameters` itself, e.g. via Spring Boot's own parent in a non-inheriting setup) is unaffected and needs no action. |
| 51 | + |
| 52 | +#### Breaking-light: parent no longer adds `--add-opens` to the test JVM |
| 53 | + |
| 54 | +In `1.0.0` the parent's top-level `<build><plugins>` set a Surefire `argLine` that opened three JDK packages to reflective access during tests: |
| 55 | + |
| 56 | +```xml |
| 57 | +<!-- present in 1.0.0 (parent <build><plugins>), REMOVED in 1.1.0 --> |
| 58 | +<plugin> |
| 59 | + <groupId>org.apache.maven.plugins</groupId> |
| 60 | + <artifactId>maven-surefire-plugin</artifactId> |
| 61 | + <configuration> |
| 62 | + <argLine> |
| 63 | + --add-opens java.base/java.lang=ALL-UNNAMED |
| 64 | + --add-opens java.base/java.lang.reflect=ALL-UNNAMED |
| 65 | + --add-opens java.base/java.util=ALL-UNNAMED |
| 66 | + </argLine> |
| 67 | + </configuration> |
| 68 | +</plugin> |
| 69 | +``` |
| 70 | + |
| 71 | +In `1.1.0` this block is gone. `maven-surefire-plugin` is still version-managed (`3.5.5`) but injects no `argLine`. Tests compile and start, but reflection-heavy test/mocking libraries that deep-reflect into `java.base` can now fail at runtime with: |
| 72 | + |
| 73 | +``` |
| 74 | +java.lang.reflect.InaccessibleObjectException: Unable to make ... accessible: |
| 75 | +module java.base does not "opens java.lang" to unnamed module ... |
| 76 | +``` |
| 77 | + |
| 78 | +A consumer whose test suite needs that access must restore it in its **own** `pom.xml`: |
| 79 | + |
| 80 | +```xml |
| 81 | +<!-- Add to the consumer's <build><plugins> only if its tests need deep reflection --> |
| 82 | +<plugin> |
| 83 | + <groupId>org.apache.maven.plugins</groupId> |
| 84 | + <artifactId>maven-surefire-plugin</artifactId> |
| 85 | + <configuration> |
| 86 | + <argLine> |
| 87 | + --add-opens java.base/java.lang=ALL-UNNAMED |
| 88 | + --add-opens java.base/java.lang.reflect=ALL-UNNAMED |
| 89 | + --add-opens java.base/java.util=ALL-UNNAMED |
| 90 | + </argLine> |
| 91 | + </configuration> |
| 92 | +</plugin> |
| 93 | +``` |
| 94 | + |
| 95 | +If the consumer **already uses JaCoCo** (or anything else that injects a Surefire `argLine` via the `${argLine}` property), do **not** hard-overwrite it. Reference the injected value so coverage instrumentation is preserved: |
| 96 | + |
| 97 | +```xml |
| 98 | +<argLine>@{argLine} --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED</argLine> |
| 99 | +``` |
| 100 | + |
| 101 | +A consumer whose tests do not perform such reflection is unaffected and needs no action. |
| 102 | + |
| 103 | +#### Additive: Spotless is now actively configured (Google Java Format) |
| 104 | + |
| 105 | +In `1.0.0` `spotless-maven-plugin` was only **version-managed** in `<pluginManagement>`. In `1.1.0` the parent also activates it in its top-level `<build><plugins>` with Google Java Format: |
| 106 | + |
| 107 | +```xml |
| 108 | +<!-- new in 1.1.0 (parent <build><plugins>) --> |
| 109 | +<plugin> |
| 110 | + <groupId>com.diffplug.spotless</groupId> |
| 111 | + <artifactId>spotless-maven-plugin</artifactId> |
| 112 | + <configuration> |
| 113 | + <java> |
| 114 | + <googleJavaFormat/> |
| 115 | + </java> |
| 116 | + </configuration> |
| 117 | +</plugin> |
| 118 | +``` |
| 119 | + |
| 120 | +There is **no `<execution>` binding**, so Spotless does **not** run during `clean verify` and **cannot fail the build automatically**. Children simply gain working `mvn spotless:apply` / `mvn spotless:check` goals that reformat to Google Java Format. Adoption is **optional**; skipping it leaves the build behaving exactly as before. |
| 121 | + |
| 122 | +Caveat: if the consumer **already configures Spotless itself**, Maven merges the parent's `<configuration>` into the child's, which can pull in `<googleJavaFormat/>` unexpectedly. A consumer with its own formatter (e.g. Palantir, a custom `eclipse` config) should keep its existing `<configuration>` explicit so the merge does not silently switch the formatter. |
| 123 | + |
| 124 | +#### Additive: Git metadata stamped into the jar manifest (`-Pfull-build` only) |
| 125 | + |
| 126 | +`1.1.0` adds `git-commit-id-maven-plugin` (`10.0.0`), version-managed in `<pluginManagement>` and wired into the **`full-build` profile only**. When a child builds with `-Pfull-build`, each jar's `MANIFEST.MF` gains `Git-Commit`, `Git-Commit-Time`, `Git-Branch`, `Git-Tag`, and `Git-Dirty` entries. No `git.properties` file is written (deliberately, to avoid classpath collisions), and the config is tuned for reproducible builds (UTC commit time, volatile properties excluded, `failOnNoGitDirectory=false`). A normal `clean verify` is unaffected. **No consumer action required.** |
| 127 | + |
| 128 | +#### Internal (no consumer action) |
| 129 | + |
| 130 | +These changed in the `java-parent` repository but have no consumer-facing effect: changes to the parent's own `release.yml` / `snapshot.yml` CI workflows, README updates, and `.gitignore` adjustments. |
| 131 | + |
| 132 | +### Steps |
| 133 | + |
| 134 | +1. In the consumer's `pom.xml`, set the `<parent>` `<version>` of `com.open-elements:java-parent` to `1.1.0`. Leave all other coordinates untouched. |
| 135 | +2. Determine whether the consumer relies on **parameter-name retention**. Search its source for parameterless `@PathVariable` / `@RequestParam` / `@RequestHeader` / `@MatrixVariable`, Spring Data query methods, Jackson `ParameterNamesModule`, or any `Parameter#getName()` use. If found, add the `maven-compiler-plugin` `<parameters>true</parameters>` block (above) to the consumer's `<build><plugins>`. |
| 136 | +3. Determine whether the consumer's **tests need deep reflection** into `java.base`. If the test suite previously passed only because of the inherited `--add-opens`, add the `maven-surefire-plugin` `argLine` block (above) to the consumer's `<build><plugins>` — using the `@{argLine}` form if JaCoCo is present. |
| 137 | +4. (Optional) If you want Google Java Format, run `mvn spotless:apply`; otherwise do nothing — Spotless will not run in `verify`. |
| 138 | +5. Run `mvn -U clean verify` (or the project's equivalent) and confirm the project compiles, **all tests pass at runtime**, and dependencies resolve before committing. Pay attention to runtime failures that a compile check would miss (the two breaking-light items surface only here). |
| 139 | + |
| 140 | +### Guard rails |
| 141 | + |
| 142 | +- Do **not** bump Spring Boot, Testcontainers, or any plugin version in the consumer to "match 1.1.0" — the BOM-managed versions are unchanged and the plugin set is internal to the parent. |
| 143 | +- Add the `-parameters` block **only if** the consumer actually relies on parameter names; do not add it speculatively to every project. |
| 144 | +- Add the Surefire `--add-opens` block **only if** the consumer's tests actually need it. If JaCoCo (or another `argLine` injector) is in play, preserve `@{argLine}` — do not clobber it with a bare `argLine`. |
| 145 | +- Restore the two flags in the **consumer's own `pom.xml`**, not by editing `java-parent`. |
| 146 | +- Do **not** add a Spotless `<execution>` that binds `check` to `verify` as part of this upgrade — that would turn an optional formatter into a build-breaking gate the parent never imposed. |
| 147 | + |
| 148 | +### Don't do this |
| 149 | + |
| 150 | +- Do not "shim" the change by pinning the consumer back to `1.0.0` in an intermediate parent so children keep inheriting the old flags — restore only the flags the consumer needs, explicitly. |
| 151 | +- Do not blanket-add both `-parameters` and `--add-opens` to a project that demonstrably needs neither; the release intentionally stopped imposing them globally. |
| 152 | +- Do not adopt Google Java Format reformatting (`spotless:apply`) in the same change as the version bump — a repo-wide reformat buried in an upgrade commit makes the diff unreviewable. Do it as a separate, isolated commit if at all. |
| 153 | +- Do not bundle this upgrade with unrelated dependency bumps, plugin changes, or feature work in the same PR. |
0 commit comments