guide configuration - rfreier/oasp4j GitHub Wiki
An application needs to be configurable in order to allow internal setup (like CDI) but also to allow externalized configuration of a deployed package (e.g. integration into runtime environment). Using Spring Boot (must read: Spring Boot reference) we rely on a comprehensive configuration approach following a "convention over configuration" pattern. This guide adds on to this by detailed instructions and best-practices how to deal with configurations.
In general we distinguish the following kinds of configuration that are explained in the following sections:
-
Internal Application configuration maintained by developers
-
Externalized Environment configuration maintained by operators
-
Externalized Business configuration maintained by business administrators
The application configuration contains all internal settings and wirings of the application (bean wiring, database mappings, etc.) and is maintained by the application developers at development time. There usually is a main configuration registered with main Spring Boot App, but differing configurations to support automated test of the application can be defined using profiles (not detailed in this guide).
The OASP recommends using spring-boot to build web applications. For a complete documentation see the Spring Boot Reference Guide.
With spring-boot you provide a simple main class (also called starter class) like this:
@SpringBootApplication(exclude = { EndpointAutoConfiguration.class })
@EntityScan(basePackages = { "io.oasp.application.mtsj" }, basePackageClasses = { AdvancedRevisionEntity.class })
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@ComponentScan(basePackages = { "io.oasp.application.mtsj.general", "io.oasp.application.mtsj" })
public class SpringBootApp {
/**
* Entry point for spring-boot based app
*
* @param args - arguments
*/
public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
In an OASP application this main class is always located in the <basepackage>
of the application package namespace (see package-conventions). This is because a spring boot application will automatically do a classpath scan for components (spring-beans) and entities in the package where the application main class is located including all sub-packages. You can use the @ComponentScan
and @EntityScan
annotations to customize this behaviour.
For basic bean configuration we rely on spring boot using mainly configuration classes and only occasionally XML configuration files. Some key principle to understand Spring Boot auto-configuration features:
-
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies and annotated components found in your source code.
-
Auto-configuration is non-invasive, at any point you can start to define your own configuration to replace specific parts of the auto-configuration by redefining your identically named bean (see also
exclude
attribute of@SpringBootApplication
in example code above).
Beans are configured via annotations in your java code (see dependency-injection).
For technical configuration you will typically write additional spring config classes annotated with @Component
that provide bean implementations via methods annotated with @Bean
. See spring @Bean documentation for further details. Like in XML you can also use @Import
to make a @Configuration class include other configurations.
It is still possible and allowed to provide (bean-) configurations using XML, though not recommended. These configuration files are no more bundled via a main xml config file but loaded individually from their respective owners, e.g. for unit-tests:
@SpringApplicationConfiguration(classes = { SpringBootApp.class }, locations = { "classpath:/config/app/batch/beans-productimport.xml" })
public class ProductImportJobTest extends AbstractSpringBatchIntegrationTest {
...
Configuration XML-files reside in an adequately named subfolder of:
src/main/resources/app
In the directory src/main/resources/config/app/batch
we place the configuration for the batch jobs. Each file within this directory represents one batch job. See batch-layer for further details.
The abstract base class BaseWebSecurityConfig
should be extended to configure web application security thoroughly.
A basic and secure configuration is provided which can be overridden or extended by subclasses.
Subclasses must use the @Profile
annotation to further discriminate between beans used in production and testing scenarios. See the following example:
BaseWebSecurityConfig
for Production and Test@Configuration
@EnableWebSecurity
@Profile(SpringProfileConstants.JUNIT)
public class TestWebSecurityConfig extends BaseWebSecurityConfig {...}
@Configuration
@EnableWebSecurity
@Profile(SpringProfileConstants.NOT_JUNIT)
public class WebSecurityConfig extends BaseWebSecurityConfig {...}
See WebSecurityConfig.
A websocket endpoint is configured within the business package as a Spring configuration class. The annotation @EnableWebSocketMessageBroker
makes Spring Boot registering this endpoint.
package io.oasp.gastronomy.restaurant.salesmanagement.websocket.config;
...
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
...
Externalized configuration is a configuration that is provided separately to a deployment package and can be maintained undisturbed by redeployments.
The environment configuration contains configuration parameters (typically port numbers, host names, passwords, logins, timeouts, certificates, etc.) specific for the different environments. These are under the control of the operators responsible for the application.
The environment configuration is maintained in application.properties
files, defining various properties (see common application properties for a list of properties defined by the spring framework).
These properties are explained in the corresponding configuration sections of the guides for each topic:
For a general understanding how spring-boot is loading and boostrapping your application.properties
see spring-boot external configuration.
The following properties files are used in every OASP application:
-
src/main/resources/application.properties
providing a default configuration - bundled and deployed with the application package. It further acts as a template to derive a tailored minimal environment-specific configuration. -
src/main/resources/config/application.properties
providing additional properties only used at development time (for all local deployment scenarios). This property file is excluded from all packaging. -
src/test/resources/config/application.properties
providing additional properties only used for testing (JUnits based on spring test).
For other environments where the software gets deployed such as test
, acceptance
and production
you need to provide a tailored copy of application.properties
. The location depends on the deployment strategy:
-
standalone runnable Spring Boot App using embedded tomcat:
config/application.properties
under the installation directory of the spring boot application. -
dedicated tomcat (one tomcat per app):
$CATALINA_BASE/lib/config/application.properties
-
tomcat serving a number of apps (requires expanding the wars):
$CATALINA_BASE/webapps/<app>/WEB-INF/classes/config
In this application.properties
you only define the minimum properties that are environment specific and inherit everything else from the bundled src/main/resources/application.properties
. In any case, make very sure that the classloader will find the file.
Make sure your properties are thoroughly documented by providing a comment to each property. This inline documentation is most valuable for your operating department.
The business configuration contains all business configuration values of the application, which can be edited by administrators through the GUI. The business configuration values are stored in the database in key/value pairs.
The database table business_configuration
has the following columns:
-
ID
-
Property name
-
Property type (Boolean, Integer, String)
-
Property value
-
Description
According to the entries in this table, the administrative GUI shows a generic form to change business configuration. The hierachy of the properties determines the place in the GUI, so the GUI bundles properties from the same hierarchy level and name. Boolean values are shown as checkboxes, integer and string values as text fields. The properties are read and saved in a typed form, an error is raised if you try to save a string in an integer property for example.
We recommend the following base layout for the hierarchical business configuration:
component.[subcomponent].[subcomponent].propertyname