Local Development
Windows: Maven build fails with a file-lock error
Symptom:
Failed to delete .../target/classes/.../some-file.html: ... The process
cannot access the file because it is being used by another processThis can also block a pre-push git hook that runs a build.
Cause: a stale java.exe process — usually a spring-boot:run you forgot
was still running, or an IDE-managed run — still has a file inside target/
open, blocking Maven’s clean goal from deleting it.
Fix:
# Find the offending process
tasklist //FI "IMAGENAME eq java.exe"
# Kill it (use the actual PID from the output above)
taskkill //F //PID <pid> //T
# Retry
./mvnw clean package -DskipTestsBefore killing anything, check the process’s full command line first (e.g.
via Get-CimInstance Win32_Process) — it’s easy to have multiple unrelated
java.exe processes running (an IDE’s language server, a build daemon,
your actual dev server). Only kill the one that’s actually your app’s dev
server.
Running the backend test suite
# Full suite
./mvnw test
# Single test class
./mvnw test -Dtest=SomeServiceTest
# Single test class + method
./mvnw test -Dtest=SomeServiceTest#someTestMethod
# Compile only, no tests (fast sanity check)
./mvnw -q compileThe backend test suite is intentionally database-free — every test is a plain unit test with mocked dependencies, no live Spring context. This is what makes it safe to run in a pre-commit hook without provisioning a database.
Currency conversion returns a 500
Symptom: the currency selector works in the UI, but generating a quote or invoice in a non-default currency throws a server error.
Cause: the exchange-rate API key environment variable isn’t set — or is
set in the wrong place (e.g. only as a CI secret, not in the actual runtime
environment’s .env).
Fix: confirm the key is present in the environment the API process actually reads from, not just wherever you think you set it.
Exchange rates look stale
This is expected, not a bug — rates are cached client-side and refreshed at
most once every few days to avoid burning through a free-tier API quota.
Clear the relevant localStorage key to force an immediate refetch if you
need to verify against a live rate.