Development Guide

1. Prerequisites

Before building this project, install and configure the following dependencies:

1.1. Node.js and npm

Node.js is used to run a development web server and build the project. Install Node either from source or as a pre-packaged bundle for your system.

Angular CLI with Webpack is used as the build system.

npm manages CSS and JavaScript dependencies. Upgrade dependencies by specifying newer versions in package.json.

npm update
npm install

Run npm run to list all available scripts for this project.

1.2. Java

The backend requires Java Development Kit (JDK) version 11 LTS or later.

1.3. Environment Variables

Configure the following environment variables:

  • JAVA_HOME - Points to your JDK installation

  • MVN_HOME - Points to your Maven installation

Ensure both $JAVA_HOME/bin and $MVN_HOME/bin are in your PATH. Remove any conflicting Java installation directories from the PATH.

2. Installing Dependencies

After installing Node, run the following command to install dependencies and development tools:

npm install

Run this command again when dependencies change in package.json.

2.1. Adding New Dependencies

To add a runtime dependency (example: Leaflet library):

npm install --save --save-exact leaflet

To add TypeScript type definitions from DefinitelyTyped:

npm install --save-dev --save-exact @types/leaflet

Then import the JS and CSS files in your application:

src/main/webapp/app/app.module.ts
import 'leaflet/dist/leaflet.js';
src/main/webapp/content/scss/vendor.scss
@import 'leaflet/dist/leaflet.css';

3. Using Angular CLI

Use Angular CLI to generate custom client code:

ng generate component my-component

This generates:

create src/main/webapp/app/my-component/my-component.component.html
create src/main/webapp/app/my-component/my-component.component.ts
update src/main/webapp/app/app.module.ts

4. PWA Support

This application includes Progressive Web App (PWA) support, disabled by default.

To enable the service worker, uncomment the following in src/main/webapp/app/app.module.ts:

ServiceWorkerModule.register('ngsw-worker.js', { enabled: false }),

5. Building for Production

5.1. Packaging as JAR

Build the optimized production JAR:

./mvnw -Pprod clean verify

This concatenates and minifies client CSS and JavaScript files and updates index.html to reference them.

Run the built application:

java -jar target/*.jar

Navigate to http://localhost:12505 in your browser.

See Using JHipster in production for more details.

5.2. Packaging as WAR

To deploy to an application server:

./mvnw -Pprod,war clean verify

6. Using Docker

Docker configurations are available in src/main/docker to launch required services.

6.1. Starting Services

Start a MySQL database:

docker compose -f src/main/docker/mysql.yml up -d

Stop and remove the container:

docker compose -f src/main/docker/mysql.yml down

6.2. Dockerizing the Application

Build a Docker image:

npm run java:docker

For ARM64 processors (e.g., Apple M1):

npm run java:docker:arm64

Run the dockerized application:

docker compose -f src/main/docker/app.yml up -d

On macOS Big Sur or later with Docker Desktop, enable "Use the new Virtualization framework" for better processing performance.

See Using Docker and Docker-Compose for more information.

7. JHipster Control Center

Start a local JHipster Control Center (accessible at http://localhost:7419):

docker compose -f src/main/docker/jhipster-control-center.yml up

8. Continuous Integration

Configure CI using the JHipster ci-cd sub-generator:

jhipster ci-cd

See Setting up Continuous Integration for more information.

9. Multi-Tenant Development Testing

The Registration Portal supports multi-tenancy, where each tenant is identified by the domain name used to access the application. During development, you can test tenant resolution using custom hostnames.

9.1. How Tenant Resolution Works

The TenantResolutionFilter resolves tenants in the following priority order:

  1. Domain match - The full hostname is matched against the domain column in the tenant table

  2. X-TENANT-ID header - Falls back to the X-TENANT-ID HTTP header if no domain match is found

Localhost and IP addresses are excluded from domain resolution to allow standard development access.

9.2. Setting Up Custom Hostnames

To test tenant resolution locally, configure your system’s hosts file to map custom hostnames to localhost.

9.2.1. Windows

Edit C:\Windows\System32\drivers\etc\hosts (requires Administrator privileges):

127.0.0.1 reg1
127.0.0.1 reg2
127.0.0.1 runningclub

9.2.2. macOS / Linux

Edit /etc/hosts (requires sudo):

sudo nano /etc/hosts

Add entries:

127.0.0.1 reg1
127.0.0.1 reg2
127.0.0.1 runningclub

9.3. Configuring Tenants in the Database

Insert or update records in the tenant table to match your custom hostnames:

-- Example: Create a tenant for hostname 'reg1'
INSERT INTO tenant (name, domain, registration_system_id)
VALUES ('Test Registration Site 1', 'reg1', 1);

-- Example: Create a tenant for hostname 'runningclub'
INSERT INTO tenant (name, domain, registration_system_id)
VALUES ('Running Club Portal', 'runningclub', 2);

The domain column must contain the exact hostname (without port) that will be used to access the application.

9.4. Accessing the Application

With the hosts file configured and tenants in the database, access the application using the custom hostname:

http://reg1:9000/membership/register/1
http://runningclub:9000/membership/register/1

The tenant context will be automatically resolved based on the hostname, and the TenantContext will be populated with the corresponding tenantId and registrationSystemId.

9.5. Verifying Tenant Resolution

Check the application logs for tenant resolution messages:

TenantResolutionFilter : Attempting to resolve tenant by domain: reg1
TenantResolutionFilter : Resolved tenant by domain: tenantId=1, registrationSystemId=1

If no tenant is found, you will see:

TenantResolutionFilter : No tenant resolved for request to: /membership/register/1 (this may be intentional for public endpoints)

9.6. Troubleshooting

Hostname not resolving

Verify the hosts file entry is correct and flush DNS cache if needed (ipconfig /flushdns on Windows)

"Invalid Host header" error

Ensure the webpack dev server is configured with allowedHosts: 'all' in webpack/webpack.custom.js

Tenant not found

Verify the domain column in the tenant table exactly matches the hostname (case-sensitive)

BrowserSync not accessible

Ensure BrowserSync is configured with host: '0.0.0.0' to listen on all interfaces