Guide for developers contributing to or customizing nullInvoice.
- Java 21, Spring Boot 3.5.3
- MariaDB + JPA
- Thymeleaf (UI)
- OpenHTMLToPDF (PDFBox)
- Tailwind CSS
- OpenAPI at
/openapi, Swagger UI at/swagger
nullInvoice/
├── src/main/java/ # Application code
├── src/main/resources/
│ ├── templates/ # UI templates (Thymeleaf)
│ ├── static/ # JS/CSS assets
│ │ ├── css/
│ │ ├── js/
│ │ ├── images/
│ │ └── fontawesome-free-7.1.0-web/
│ ├── fonts/ # DejaVu fonts for PDF
│ ├── db/migration/ # Flyway database migrations
│ ├── messages*.properties # i18n translations
│ └── application.yml # Main config
├── src/test/ # Tests
└── target/ # Build output
templates/ # Example invoice templates (6 languages)
integration-tests/ # Load testing scripts
build-tailwind.sh # Tailwind CSS build script
twbin/ # Tailwind CSS standalone binary
docker-compose.yml # Docker setup
The UI uses Tailwind CSS, which must be rebuilt when CSS changes are made.
-
Download the Tailwind CSS standalone binary from GitHub releases
-
Place the binary in the
twbin/directory (e.g.,twbin/tailwindcss-linux-x64) -
Run the build script:
./build-tailwind.sh
This rebuilds nullInvoice/src/main/resources/static/css/tailwind.css from the source file tailwind-src.css.
For rapid development without rebuilding Tailwind, uncomment the CDN script in nullInvoice/src/main/resources/templates/fragments/head.html:
<script src="https://cdn.tailwindcss.com"></script>Remember to rebuild Tailwind CSS before deploying to production.
A script is included to stress test the invoice generation API with concurrent requests.
API_KEY=your_api_key ./integration-tests/gen-test.sh [SUPPLIER_ID] [COUNT] [BASE_URL]Or pass the API key as the 4th argument:
./integration-tests/gen-test.sh [SUPPLIER_ID] [COUNT] [BASE_URL] [API_KEY]SUPPLIER_ID- supplier ID to use for test invoices (default: 1)COUNT- number of concurrent invoice requests to generate (default: 20)BASE_URL- application base URL (default: http://localhost:8080)API_KEY- your API key (required, can be set as environment variable)
API_KEY=abc123-your-key ./integration-tests/gen-test.sh 1 50 http://localhost:8080This fires concurrent invoice generation requests to test the pessimistic locking mechanism and overall API performance under load.
cd nullInvoice
mvn clean packageThe built JAR will be in target/nullinvoice-0.0.1-SNAPSHOT.jar
mvn testjava -jar target/nullinvoice-0.0.1-SNAPSHOT.jarOr via Maven:
mvn spring-boot:runDatabase schema changes are managed with Flyway migrations.
- Create a new SQL file in
nullInvoice/src/main/resources/db/migration/ - Follow naming convention:
V{version}__{description}.sql- Example:
V3__add_customer_notes.sql
- Example:
- Migrations run automatically on application startup
- Flyway tracks applied migrations in the
flyway_schema_historytable
- Never modify existing migrations that have been applied
- Use descriptive names for migrations
- Test migrations on a copy of production data
- Ensure migrations are idempotent when possible
- Keep migrations small and focused
The application UI is fully internationalized with message bundles:
- English (EN) ✅
- Bulgarian (BG) ✅
- German (DE) ✅
- Spanish (ES) ✅
- Italian (IT) ✅
- Russian (RU) ✅
- Create
nullInvoice/src/main/resources/messages_{lang}.properties - Copy keys from
messages.properties(English) - Translate all values to your language
- Test by setting your locale in the UI
messages.properties- English (default/fallback)messages_bg.properties- Bulgarianmessages_de.properties- Germanmessages_es.properties- Spanishmessages_it.properties- Italianmessages_ru.properties- Russianmessages_tr.properties- Turkish
We welcome contributions for:
- 🌍 UI translations (
messages_{lang}.propertiesinnullInvoice/src/main/resources/) - 📄 Example invoice templates for your language/region (
templates/{lang}/) - 🎨 Font recommendations for optimal PDF rendering in your language
- 📝 Documentation improvements and translations
- 🐛 Bug fixes and feature improvements
The application can generate invoices in any language with proper font support:
- Arabic (UAE, Saudi Arabia, etc.) - RTL support via CSS, needs templates & UI translations
- East Asian (Chinese, Japanese, Korean) - Unicode fonts supported, needs templates & UI translations
- Hebrew - RTL support via CSS, needs templates & UI translations
- Any other Unicode-based language
The DejaVu font family bundled with the application supports extensive Unicode coverage. For languages requiring specific fonts, use @font-face in invoice templates to load web fonts with fallback to DejaVu.
- Follow standard Java conventions
- Use meaningful variable and method names
- Document public APIs with Javadoc
- Keep methods focused and concise
- Write tests for new features and bug fixes
The project was built with NetBeans and includes nbactions.xml for IDE integration.
- Import as Maven project
- Set JDK to Java 21
- Enable annotation processing
- Set environment variables in run configurations
- Install Java Extension Pack
- Install Spring Boot Extension Pack
- Configure environment variables in
launch.json
logging:
level:
com.nullinvoice: DEBUGRun with debug enabled:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \
-jar target/nullinvoice-0.0.1-SNAPSHOT.jarConnect your IDE debugger to localhost:5005
docker compose builddocker compose up -ddocker logs -f nullinvoice- Uses pessimistic locking to prevent race conditions on invoice numbering
- Concurrent requests for the same supplier are serialized
- Different suppliers can process concurrently
- PDFs are rendered on-demand from stored HTML snapshots
- First PDF generation may be slower due to font loading
- Subsequent generations are faster with cached resources
- JPA queries are optimized with proper indexing
- Soft deletes use
deletedflag instead of actual deletion - Invoice searches use database indexes on number, date, supplier, and client