1
0
Files
spring-boot-demo/spring-aop/scripts/env.sh
Ankur Mhatre 86246dc860 Three new article modules: configuration binding, profiles and config data, Spring AOP
configuration-properties/  @ConfigurationProperties vs @Value on Spring Boot 4.1.1.
  The relaxed-binding matrix is generated by binding each spelling rather than
  transcribed, and re-checked against real processes -- the in-process probe was
  wrong twice before it was right. Records the three findings that came out of it:
  @Value does get relaxed resolution inside Spring Boot (Boot attaches
  ConfigurationPropertySources), the configuration processor silently stops
  generating metadata on JDK 23+ when declared as a plain dependency, and @Valid is
  not what makes nested constraints run.

profiles-and-config/       Precedence, profiles, spring.config.import and config trees.
  /precedence reports every source holding a property in rank order with file and
  line, which turns "my profile file had no effect" into a two-line answer. Also
  pins the counterintuitive one: an imported file outranks the file that imported it.

spring-aop/                Designators, proxy types, and aspects that do not fire.
  One advice per supported designator so the reference table is generated from real
  matches; all fourteen unsupported designators fed to the parser. Two corrections to
  the reference documentation: unsupported designators throw
  UnsupportedPointcutPrimitiveException (extends RuntimeException, not
  IllegalArgumentException), and spring-boot-starter-aop was renamed to
  spring-boot-starter-aspectj in Boot 4.

19 contract tests across the three modules, 15 captured transcripts, all regenerated
by scripts/run-all.sh. Verified on Spring Boot 4.1.1, Spring Framework 7.0.9,
JDK 25.0.4.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gip4srpzMwjgoba6uEfbr5
2026-09-08 16:47:48 +00:00

62 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Shared environment. Point JAVA_HOME at a JDK 25 (or newer) installation.
: "${JAVA_HOME:?set JAVA_HOME to a JDK 25+ installation}"
export PATH="$JAVA_HOME/bin:$PATH"
MVN="${MVN:-mvn}"
JAR="target/spring-aop-demo-1.0.0.jar"
APP_MAIN="com.ankurm.aop.AopApplication"
APP_PORT="${APP_PORT:-8080}"
# Strip environment noise that is an artefact of the machine, not of Spring:
# the JVM prints a JAVA_TOOL_OPTIONS banner to stderr on every launch when a proxy
# truststore is configured, and it would otherwise end up in every committed transcript.
clean() { grep -v "Picked up JAVA_TOOL_OPTIONS" | grep -v "^OpenJDK 64-Bit Server VM warning"; }
# Start the demo jar detached, record its PID, and block until it answers.
# Extra arguments are passed to the application. Environment variables for the run are
# passed by setting them on the call: `APP_ENV="A=1 B=2" start_app --spring.profiles.active=x`
start_app() {
stop_app
mkdir -p target
# Deliberately NOT setsid: setsid forks when it is not already a process-group leader,
# so $! would be the PID of a process that exits immediately and the JVM would survive
# every later stop_app. A surviving JVM keeps the port, the next scenario fails to bind,
# and curl answers from the previous scenario -- which reads exactly like the
# configuration change under test having had no effect. Three wrong findings in this
# repository came from that before it was tracked down.
if [ -n "${APP_ENV:-}" ]; then
# shellcheck disable=SC2086
env $APP_ENV nohup java -jar "$JAR" "$@" > /tmp/aop-demo.log 2>&1 < /dev/null &
else
nohup java -jar "$JAR" "$@" > /tmp/aop-demo.log 2>&1 < /dev/null &
fi
echo $! > target/app.pid
for _ in $(seq 1 60); do
curl -s -o /dev/null "http://127.0.0.1:${APP_PORT}/aop/proxies" 2>/dev/null && return 0
kill -0 "$(cat target/app.pid)" 2>/dev/null || { echo "JVM exited during startup:"
tail -20 /tmp/aop-demo.log; return 1; }
sleep 1
done
echo "application did not answer"; tail -20 /tmp/aop-demo.log; return 1
}
# Stop it by recorded PID. Never by pattern: `ps | grep <jar name>` also matches the shell
# running the script, because the jar name is on that shell's own command line.
stop_app() {
if [ -f target/app.pid ]; then
pid=$(cat target/app.pid)
if [ -n "$pid" ] && grep -qa "spring-aop-demo" "/proc/$pid/cmdline" 2>/dev/null; then
kill -9 "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true # reap, so bash prints no "Killed" notice
fi
rm -f target/app.pid
fi
for _ in $(seq 1 40); do
if ! (exec 3<>/dev/tcp/127.0.0.1/"${APP_PORT:-8080}") 2>/dev/null; then break; fi
sleep 0.25
done
exec 3<&- 2>/dev/null || true
}
# Print the precedence report for one property, compactly.