Skip to content

Dynamic Project

A dynamic project is a Git repository with sources written in Java or Kotlin, containing definitions of Spring beans of a djig application, that you can redeploy dynamically, at runtime, without restarting the app.

Such beans are called dynamic beans.

Dynamic beans are injected into beans of the main part of the application via normal Spring dependency injection APIs like field injection, constructor injection, etc.

A djig application can use multiple dynamic projects. In the scope of a djig app every dynamic project is assigned a unique name.

Dynamic projects of a djig app are described in the Spring Boot configuration properties prefixed with djig..

The main properties of a dynamic project are the clone URL, username and password (for the djig runtime to access the project on the Git repository hosting) and the Java package containing interfaces to be implemented by the dynamic beans of the dynamic project.

Those configuration properties are loaded into the properties of the org.taruts.djig.configurationProperties.DjigConfigurationProperties bean via the standard Spring Boot mechanism called Type-safe Configuration Properties. This is a bean of the main context of the app. You can study all the djig. properties in the sources of DjigConfigurationProperties.

A dynamic project must contain a Gradle or Maven build configuration.

A dynamic project, as the main part of the application (the static part), must depend on an API JAR.

This dependency must be compileOnly in Gradle and provided in Maven.

Compile only dependencies and DynamicClassLoader

At runtime, when a new version of a dynamic project is deployed, the djig runtime uses a new DynamicClassLoader created exclusively for this version of this dynamic project.

This DynamicClassLoader instance is a child ClassLoader of the main ClassLoader of the application. It must load only classes that the dynamic project has but that are absent in the main part of the app. When loading a class for the dynamic project, if the class is known to the main part of the app (which means it's from the API JAR or from a dependency thereof) the loading must be delegated to the main ClassLoader.

Marking dependencies as compileOnly (Gradle) or provided (Maven) is what allows DynamicClassLoader to identify classes, loading of which must be delegated to the main ClassLoader.

Let's sum it up. In a dynamic project, dependencies, that the main part of the app does NOT depend on, are marked implementation (Gradle) или compile (Maven). They are dynamic dependencies. The dependency on API JAR is marked as compileOnly in Gradle and provided in Maven. Those are static dependencies.

Dynamic Project Configuration Properties

There are three levels at which dynamic project configuration properties can be specified.

  • Common properties
  • Per hosting properties
  • Individual properties of a dynamic project

Common properties

Common properties are applied to all dynamic projects of the app. Their names start with djig.common., e.g. djig.common.username=john-doe.

Per Hosting Properties

Per hosting properties are specified for a Git repository hosting and are applied only to dynamic projects that are on that hosting.

For example, you can specify a password for all dynamic projects on GitLab, and at the same time specify another password for all dynamic projects on GitHub.

The names of such properties start with djig.hostings.<hosting name>., where <hosting name> is composed of the host (the domain name or IP address) and the port (after a dash, if explicitly specified in the URL) with replacing all dots with dashes.

So, the name of gitlab.com is gitlab-com, and the name of 127.0.0.1:12345 is 127-0-0-1-12345.

For example: djig.hostings.gitlab-com.username=john-doe.

Individual Properties of a Dynamic Project

The names of such properties start with djig.dynamic-projects.<project name>., where <project name> is any string unique in the scope of the app containing latin letters, digits, dashes and underscores.

For example: djig.dynamic-projects.foo.username=john-doe.

Common Points About Dynamic Project Configuration Properties of All Levels

As you might guess, the point of common properties and per hosting properties is not to specify same values multiple times for all dynamic projects.

Here is the list of property name endings which you specify after the prefixes we discussed earlier:

  • url - The clone URL.
    It can be only used as an individual project property
  • username - The username used for authentication at the Git repository hosting.
    You can specify Personal Access Token (PAT) as username. In this case you should leave the password empty.
  • password - The user password used for authentication at the Git repository hosting.
  • branch - The branch name from which the dynamic project code must be taken
  • dynamic-interface-package - The name of the Java package in API JAR, containing dynamic bean interfaces of the dynamic project
  • build-type - The type of build of the project.
    Can be any of MAVEN, MAVEN_WRAPPER, GRADLE, GRADLE_WRAPPER. This property is optional, as the build type can be auto-detected by files required by specific build types.
  • hosting-type - GitHub or GitLab.
    This is the type of REST API served by the hosting. Can be auto-detected. The host name github.com in the project URL implies the REST API is that of GitHub, for other hostings djig assumes they serve the REST API of GitLab.

Security Warning

One should not store username and password values in the sources. At least this is not for production environments. Instead the Spring Boot externalized configuration mechanism should be used. It might be <working directory>/config/application.properties, environment variables, system properties, whatever suits you best.

More Full Property Name Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
djig.common.username=
djig.common.password=
djig.common.branch=
djig.common.dynamic-interface-package=
djig.common.build-type=
djig.common.hosting-type=

djig.hostings.gitlab-com.username=
djig.hostings.gitlab-com.password=
djig.hostings.gitlab-com.branch=
djig.hostings.gitlab-com.dynamic-interface-package=
djig.hostings.gitlab-com.build-type=
djig.hostings.gitlab-com.hosting-type=

djig.dynamic-projects.foo.url=
djig.dynamic-projects.foo.username=
djig.dynamic-projects.foo.password=
djig.dynamic-projects.foo.branch=
djig.dynamic-projects.foo.dynamic-interface-package=
djig.dynamic-projects.foo.build-type=
djig.dynamic-projects.foo.hosting-type=

An Example of Dynamic Project Configuration

This is taken from the project https://gitlab.com/pavel-taruts/djig/example/app

1
2
3
4
5
djig.common.branch=master
djig.common.dynamic-interface-package=org.taruts.djig.example.dynamicApi.dynamic

djig.dynamic-projects.1.url=https://gitlab.com/pavel-taruts/djig/example/dynamic-dev.git
djig.dynamic-projects.2.url=https://gitlab.com/pavel-taruts/djig/example/dynamic-dev-kotlin.git