TUMApply is a modern, inclusive, and efficient application portal for doctoral programs at the Technical University of Munich. It streamlines application management, improves usability for applicants and faculty, and supports scalable, secure, and transparent recruitment processes
Node is required for generation and recommended for development. package.json
is always generated for a better
development experience with prettier, commit hooks, scripts and so on.
In the project root, JHipster generates configuration files for tools like git, prettier, eslint, husky, and others that are well known and you can find references in the web.
/src/*
structure follows default Java structure.
-
.yo-rc.json
- Yeoman configuration file JHipster configuration is stored in this file atgenerator-jhipster
key. You may findgenerator-jhipster-*
for specific blueprints configuration. -
.yo-resolve
(optional) - Yeoman conflict resolver Allows to use a specific action when conflicts are found skipping prompts for files that matches a pattern. Each line should match[pattern] [action]
with pattern been a Minimatch pattern and action been one of skip (default if omitted) or force. Lines starting with#
are considered comments and are ignored. -
.jhipster/*.json
- JHipster entity configuration files -
npmw
- wrapper to use locally installed npm. JHipster installs Node and npm locally using the build tool by default. This wrapper makes sure npm is installed locally and uses it avoiding some differences different versions can cause. By using./npmw
instead of the traditionalnpm
you can configure a Node-less environment to develop or test your application. -
/src/main/docker
- Docker configurations for the application and services that the application depends on
This project uses MySQL as a relational database. Follow the steps below to get started with the local setup:
- Docker & Docker Compose:
- MySQL Client (
mysql
CLI) installed and available inPATH
:- macOS:
brew install mysql-client echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zprofile source ~/.zprofile
- Windows: Download via MySQL Installer and ensure the
bin
directory is added to your PATH.
- macOS:
docker compose -f src/main/docker/mysql.yml up -d
This starts a local MySQL instance with the database tumapply
.
./gradlew liquibaseUpdate
If you encounter errors, ensure the MySQL container is running and reachable.
This script automatically imports all SQL files from the src/main/resources/testdata/
folder, sorted alphabetically.
bash ./src/main/resources/testdata/import-testdata.sh
π‘ Platform Notes:
- macOS: Requires MySQL CLI to be installed via Homebrew (
brew install mysql-client
) and available in yourPATH
. - Linux: Requires
mysql
CLI to be installed (sudo apt install mysql-client
or equivalent). - Windows: Use Git Bash to run this script. Make sure the MySQL CLI is installed (via MySQL Installer) and the
bin
folder is added to yourPATH
.
- Update Liquibase changelog files under
config/liquibase/changelog
- Add new files to
master.xml
- Re-run the update with
./gradlew liquibaseUpdate
- β
mysql CLI not found
: Make sure MySQL client is installed and available in your PATH. - β
Public Key Retrieval is not allowed
: AddallowPublicKeyRetrieval=true
to the JDBC URL. - β
Access denied
: Useroot
with an empty password (""
) unless configured otherwise.
Congratulations! You've selected an excellent way to secure your JHipster application. If you're not sure what OAuth and OpenID Connect (OIDC) are, please see What the Heck is OAuth?
To log in to your app, you'll need to have Keycloak up and running. TUMApply provides a preconfigured setup including default users and roles, and supports convenient token-based login testing with Bruno.
docker compose -f src/main/docker/keycloak.yml up
You can also use the provided docs/TUMapply API
folder to test the login flow via OAuth 2.0 in Bruno. The request is
already preconfigured to obtain an access token using the password grant type. For more information see [AUTH.md](.
/docs/AUTH.md).
The security settings in src/main/resources/config/application.yml
are configured for this image.
spring:
...
security:
oauth2:
client:
provider:
oidc:
issuer-uri: http://localhost:9080/realms/jhipster
registration:
oidc:
client-id: web_app
client-secret: web_app
scope: openid,profile,email
Some of Keycloak configuration is now done in build time and the other part before running the app, here is the list of all build and configuration options.
Before moving to production, please make sure to follow this guide for better security and performance.
Also, you should never use start-dev
nor KC_DB=dev-file
in production.
When using Kubernetes, importing should be done using init-containers (with a volume when using db=dev-file
).
Bruno is an open-source API client, similar to Postman, but focused on a local-first and Git-friendly workflow.
- Bruno stores collections as plain folder and text files in the git repository.
- You can send requests with environment variables, use OAuth2 flows, and inspect responses.
- The folder
docs/TUMapply API
contains all relevant requests for testing authentication and the TUMApply API.
π [TUMApply API β Bruno Collection Overview (Confluence)](https://confluence.aet.cit.tum. de/spaces/AP/pages/257785953/TUMApply+API+%E2%80%93+Postman+Collection+Overview)
If you'd like to use Okta instead of Keycloak, it's pretty quick using the Okta CLI. After you've installed it, run:
okta register
Then, in your JHipster app's directory, run okta apps create
and select JHipster. This will set up an Okta app for
you, create ROLE_ADMIN
and ROLE_USER
groups, create a .okta.env
file with your Okta settings, and configure a
groups
claim in your ID token.
Run source .okta.env
and start your app with Maven or Gradle. You should be able to sign in with the credentials you
registered with.
If you're on Windows, you should install WSL so the
source
command will work.
If you'd like to configure things manually through the Okta developer console, see the instructions below.
First, you'll need to create a free developer account at https://developer.okta.com/signup/. After doing so, you'll
get your own Okta domain, that has a name like https://dev-123456.okta.com
.
Modify src/main/resources/config/application.yml
to use your Okta settings.
spring:
...
security:
oauth2:
client:
provider:
oidc:
issuer-uri: https://{yourOktaDomain}/oauth2/default
registration:
oidc:
client-id: { clientId }
client-secret: { clientSecret }
security:
Create an OIDC App in Okta to get a {clientId}
and {clientSecret}
. To do this, log in to your Okta Developer account
and navigate to Applications > Add Application. Click Web and click the Next button. Give the app a name
youβll remember, specify http://localhost:8080
as a Base URI, and http://localhost:8080/login/oauth2/code/oidc
as a
Login Redirect URI. Click Done, then Edit and add http://localhost:8080
as a Logout redirect URI. Copy and paste
the client ID and secret into your application.yml
file.
Create a ROLE_ADMIN
and ROLE_USER
group and add users into them. Modify e2e tests to use this account when running
integration tests. You'll need to change credentials in src/test/javascript/e2e/account/account.spec.ts
and
src/test/javascript/e2e/admin/administration.spec.ts
.
Navigate to API > Authorization Servers, click the Authorization Servers tab and edit the default one. Click
the Claims tab and Add Claim. Name it "groups", and include it in the ID Token. Set the value type to "Groups"
and set the filter to be a Regex of .*
.
After making these changes, you should be good to go! If you have any issues, please post them to Stack Overflow. Make sure to tag your question with "jhipster" and "okta".
If you'd like to use Auth0 instead of Keycloak, follow the configuration steps below:
- Create a free developer account at https://auth0.com/signup. After successful sign-up, your account will be
associated with a unique domain like
dev-xxx.us.auth0.com
- Create a new application of type
Regular Web Applications
. Switch to theSettings
tab, and configure your application settings like:- Allowed Callback URLs:
http://localhost:8080/login/oauth2/code/oidc
- Allowed Logout URLs:
http://localhost:8080/
- Allowed Callback URLs:
- Navigate to User Management > Roles and create new roles named
ROLE_ADMIN
, andROLE_USER
. - Navigate to User Management > Users and create a new user account. Click on the Role tab to assign roles to the newly created user account.
- Navigate to Auth Pipeline > Rules and create a new Rule. Choose
Empty rule
template. Provide a meaningful name likeJHipster claims
and replaceScript
content with the following and Save.
function (user, context, callback) {
user.preferred_username = user.email;
const roles = (context.authorization || {}).roles;
function prepareCustomClaimKey(claim) {
return `https://www.jhipster.tech/${claim}`;
}
const rolesClaim = prepareCustomClaimKey('roles');
if (context.idToken) {
context.idToken[rolesClaim] = roles;
}
if (context.accessToken) {
context.accessToken[rolesClaim] = roles;
}
callback(null, user, context);
}
- In your
JHipster
application, modifysrc/main/resources/config/application.yml
to use your Auth0 application settings:
spring:
...
security:
oauth2:
client:
provider:
oidc:
# make sure to include the ending slash!
issuer-uri: https://{your-auth0-domain}/
registration:
oidc:
client-id: { clientId }
client-secret: { clientSecret }
scope: openid,profile,email
jhipster:
...
security:
oauth2:
audience:
- https://{your-auth0-domain}/api/v2/
OpenAPI-Generator is configured for this application. You can generate API code from the
openapi/openapi.yml
definition file by running:
./gradlew openApiGenerate
Then implements the generated delegate classes with @Service
classes.
To generate the openapi.yml
definition file, you can use the following command:
./gradlew generateApiDocs -x webapp
The build system will install automatically the recommended version of Node and npm.
We provide a wrapper to launch npm. You will only need to run this command when dependencies change in package.json.
./npmw install
We use npm scripts and Angular CLI with Webpack as our build system.
Run the following commands in two separate terminals to create a blissful development experience where your browser auto-refreshes when files change on your hard drive.
./gradlew -x webapp
./npmw start
Npm is also used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by
specifying a newer version in package.json. You can also run ./npmw update
and ./npmw install
to
manage dependencies.
Add the help
flag on any command to see how you can use it. For example, ./npmw help update
.
The ./npmw run
command will list all the scripts available to run for this project.
TUMApply uses a scalable and customizable theming system that's built on PrimeNG Themes and Tailwind CSS. It supports both light and dark mode through a centralized theme management.
The theming system is structured as follows:
src/main/webapp/content/theming/tumapplypreset.ts
: defines the custom PrimeNG theme with TUMApply-specific colors- CSS variables are provided by PrimeNG's theming system and are available globally
- Tailwind CSS is used for additional styling options and is aligned with the PrimeNG theme
Theme switching is controlled through the toggleTheme()
method in the NavbarComponent:
- The selected theme preference is stored in
sessionStorage
- The theme is toggled by adding/removing the
dark-theme
class to the<html>
element - PrimeNG components automatically respond to theme changes
For consistent designs:
/* Using PrimeNG variables */
color:
var
(
--text-color
)
;
background-color:
var
(
--surface-ground
)
;
/* Using Tailwind classes */
<
div class
=
"text-primary bg-surface-200 dark:bg-surface-700"
> ...<
/
div >
Avoid hard-coded hex values. Instead, use the CSS variables provided by PrimeNG or Tailwind classes.
To customize the theme, edit the color definitions in src/main/webapp/content/theming/tumapplypreset.ts
JHipster ships with PWA (Progressive Web App) support, and it's turned off by default. One of the main components of a PWA is a service worker.
The service worker initialization code is disabled by default. To enable it, uncomment the following code in
src/main/webapp/app/app.config.ts
:
ServiceWorkerModule.register('ngsw-worker.js', {enabled: false}),
For example, to add Leaflet library as a runtime dependency of your application, you would run following command:
./npmw install --save --save-exact leaflet
To benefit from TypeScript type definitions from DefinitelyTyped repository in development, you would run following command:
./npmw install --save-dev --save-exact @types/leaflet
Then you would import the JS and CSS files specified in library's installation instructions so that Webpack knows about them: Edit src/main/webapp/app/app.config.ts file:
import 'leaflet/dist/leaflet.js';
Edit src/main/webapp/content/scss/vendor.scss file:
@import 'leaflet/dist/leaflet.css';
Note: There are still a few other things remaining to do for Leaflet that we won't detail here.
For further instructions on how to develop with JHipster, have a look at Using JHipster in development.
You can also use Angular CLI to generate some custom client code.
For example, the following command:
ng generate component my-component
will generate few files:
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.config.ts
To build the final jar and optimize the TUMApply application for production, run:
./gradlew -Pprod clean bootJar
This will concatenate and minify the client CSS and JavaScript files. It will also modify index.html
so it references
these new files.
To ensure everything worked, run:
java -jar build/libs/*.jar
Then navigate to http://localhost:8080 in your browser.
Refer to Using JHipster in production for more details.
To package your application as a war in order to deploy it to an application server, run:
./gradlew -Pprod -Pwar clean bootWar
JHipster Control Center can help you manage and control your application(s). You can start a local control center server (accessible on http://localhost:7419) with:
docker compose -f src/main/docker/jhipster-control-center.yml up
To launch your application's tests, run:
./gradlew test integrationTest jacocoTestReport
Unit tests are run by Jest. They're located near components and can be run with:
./npmw test
Sonar is used to analyse code quality. You can start a local Sonar server (accessible on http://localhost:9001) with:
docker compose -f src/main/docker/sonar.yml up -d
Note: we have turned off forced authentication redirect for UI in src/main/docker/sonar.yml for out of the box experience while trying out SonarQube, for real use cases turn it back on.
You can run a Sonar analysis with using the sonar-scanner or by using the gradle plugin.
Then, run a Sonar analysis:
./gradlew -Pprod clean check jacocoTestReport sonarqube -Dsonar.login=admin -Dsonar.password=admin
Additionally, Instead of passing sonar.password
and sonar.login
as CLI arguments, these parameters can be configured
from sonar-project.properties as shown below:
sonar.login=admin
sonar.password=admin
For more information, refer to the Code quality page.
JHipster generates a number of Docker Compose configuration files in the src/main/docker/ folder to launch required third party services.
For example, to start required services in Docker containers, run:
docker compose -f src/main/docker/services.yml up -d
- If you encounter a "Public Key Retrieval is not allowed" error when connecting to MySQL, you can fix it by either:
- Adding
allowPublicKeyRetrieval=true
to your JDBC URL (e.g.,jdbc:mysql://localhost:3306/dbname?allowPublicKeyRetrieval=true&useSSL=false
) - Or, if you're using IntelliJ, open the Database tool window, navigate to your MySQL data source, open the driver
properties, and set
allowPublicKeyRetrieval
totrue
manually.
- Adding
To stop and remove the containers, run:
docker compose -f src/main/docker/services.yml down
Spring Docker Compose Integration is enabled by default. It's possible to disable it in application.yml:
spring:
...
docker:
compose:
enabled: false
You can also fully dockerize your application and all the services that it depends on. To achieve this, first build a Docker image of your app by running:
npm run java:docker
Or build a arm64 Docker image when using an arm64 processor os like MacOS with M1 processor family running:
npm run java:docker:arm64
Then run:
docker compose -f src/main/docker/app.yml up -d
For more information refer to Using Docker and Docker-Compose, this page also contains information on the Docker
Compose sub-generator (jhipster docker-compose
), which is able to generate Docker configurations for one or several
JHipster applications.
To configure CI for your project, run the ci-cd sub-generator (jhipster ci-cd
), this will let you generate
configuration files for a number of Continuous Integration systems. Consult the Setting up Continuous Integration
page for more information.