Adding properties to JHipster Cloud application.yml causes registry configuration to fail - java

I want to add a custom property to the application.yml of my Cloud Config. The comments in the file say it is for all shared configuration. However, when I do so, it causes the binding of the properties to JHipsters own ApplicationProperties to fail at the class does not have the correct writable property.
application.yml
application:
clients:
- Foo
Stacktrace:
Caused by: org.springframework.boot.bind.RelaxedBindingNotWritablePropertyException: Failed to bind 'application.clients[0]' from 'file:central-config/localhost-config/application.yml' to 'clients[0]' property on 'io.github.jhipster.registry.config.ApplicationProperties'

From JHipster's documentation:
Application-specific properties Your generated application can also
have its own Spring Boot properties. This is highly recommended, as it
allows type-safe configuration of the application, as well as
auto-completion and documentation within an IDE.
JHipster has generated a ApplicationProperties class in the config
package, which is already preconfigured, and it is already documented
at the bottom the application.yml, application-dev.yml and
application-prod.yml files. All you need to do is code your own
specific properties. (emphasis mine)
Have you done that step and added your own properties to ApplicationProperties.java? It looks like you should have a property of type List<String> clients. If you haven't that's why it's failing, because it's attempting to bind a configuration property to the ApplicationProperties class, but the class doesn't contain a property to store it.

Custom Spring boot properties should always be defined in a #ConfigurationProperties class within the app so that their value can be setup in the yml file. This is thoroughly documented in the spring boot documentation:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Related

Property in IntelliJ: driver-class-name or driverClassName?

I use IntelliJ IDEA, the IntelliSense suggests the usage of assigning jdbc driver in application.properties file as
spring.datasource.driver-class-name=com.microsoft.jdbc.sqlserver.SQLServerDriver
See the image when I typing
But by the answer, that is wrong. It should be
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
However a web site related to JetBrains seems indicate that using driver-class-name might be correct.
https://youtrack.jetbrains.com/issue/IDEA-202820?_ga=2.207495315.1822682194.1613252382-718343134.1609267918
So I am confused. Which one is right? Is it a bug of IntelliJ IDEA?
Spring Boot supports both formats for properties, and they can be used interchangeably for properties defined by property binding (#ConfigurationProperties beans).
See also Relaxed Binding in the Spring Boot Features documentation:
Spring Boot uses some relaxed rules for binding Environment
properties to #ConfigurationProperties beans, so there does not need
to be an exact match between the Environment property name and the
bean property name. Common examples where this is useful include
dash-separated environment properties (for example, context-path
binds to contextPath), and capitalized environment properties (for
example, PORT binds to port).
In other words, given spring.datasource.driverClassName is defined through a #ConfigurationProperties bean, you can use both spring.datasource.driver-class-name and spring.datasource.driverClassName. The kebab-case form is the recommended form. The relaxed binding was - AFAIK - introduced in Spring Boot 2, so maybe the question you referenced was still at Spring Boot 1.x.
In any case, IntelliJ's autocomplete cannot be wrong in this case, because it uses information contained in the Spring Boot JAR files, generated by Spring Boot tools, specifically for spring.datasource.driver-class-name, this property name is obtained from META-INF/additional-spring-configuration-metadata.json in the spring-boot-autoconfigure JAR file. It is also the property listed in Common Application properties.
The Youtrack issue you listed seems to be an unrelated problem.

Hibernate/Spring framework: path of the database in a configuration file

I am trying to write a simple Hibernate application and I want the SQLite database location to be changed according to an application configuration file.
What I was trying to do was therefore retrieving the path of the database from a text file in the project and putting it inside dbLocation, then running the following piece of code:
Configuration config = new Configuration();
config.setProperty("hibernate.connection.url", "jdbc:sqlite:" + dbLocation);
Is there a better and more "standard" way to do so? I'm using Spring Boot for my application and I just realized there's afile called application.properties. May I use this one maybe? I'm pretty new to both Hibernate and the Spring framework.
In Spring Boot application properties you can externalize your application properties so they are configured/managed outside your application source code.
Once a property is defined in application.properties you can use SpringBoot built-in feature to access the values
#Configuration
public class ApplicationProperty {
#Value("${prop}")
private String prop;
With Spring Boot another way is to use #ConfigurationProperties.
Example from the documentation can be found here
A comparison between #ConfigurationProperties and #Value annotation from the documentation
Feature #ConfigurationProperties #Value
Relaxed binding Yes No
Meta-data support Yes No
SpEL evaluation No Yes

Spring Boot application.yml and application.properties

I was trying to understand if I have some properties in application.yml and a few in application.properties will my application read from both these files?
According to Spring documentation - Change the Location of External Properties of an Application:
No matter what you set in the environment, Spring Boot always loads application.properties as described above. By default, if YAML is used, then files with the ‘.yml’ extension are also added to the list.
In which order properties are considered is explained in the chapter Spring documentation - Externalized Configuration.
If in doubt what files have been loaded I recommend to set the log level to DEBUG which shows the loaded configuration files in the log.
There is a good article here, that describes how both of these can be read using the #ConfigurationProperties annotation.
#ConfigurationProperties supports both .properties and .yml files.
#ConfigurationProperties support JSR-303 bean validation – javax.validation
Hope this helps!

Externalizing configuration in Spring Boot with multiple applications running in the same container

I'm building multiple Spring Boot applications which will be deployed on the same servlet container. But I'm having difficulties getting Spring Boot to work with externalized configuration files the way I want, and not like the framework wants.
Situation:
multiple Spring Boot applications will be deployed on a single servlet container (WAR file)
the location of configuration files will be set via JVM property spring.config.location
embedded deployment is not an option
Problem:
As the applications are deployed on the same JVM, the property spring.config.location has the same value for all applications. I want our applications to all use the same configuration file naming (application.properties), so specifying spring.config.name is not an option.
What I would like:
no need to set spring.config.name as the configuration name should be standardized accross all our applications (constant)
the externalized configuration properties should override values from application.properties packaged inside my deployed WAR
profile specific configurations (application-{profile}) should be possible
no hardcoded config locations in code
organizing configuration files in a per-application directory layout:
${spring.config.location}/app1/application.properties
${spring.config.location}/app2/application.properties
${spring.config.location}/app3/application.properties
Questions:
Is there some mechanism to influence or override loading or resolving of external configuration files?
Are there other approaches to get the desired result?
You can achieve what you're trying by using #PropertySource. According to the official documentation (Externalized Configuration) you can use this annotation to externalize configuration files, e.g.:
#Configuration
#PropertySource("file:/path/to/application.properties")
public class AppConfig {
}
As stated in here, inside #PropertySource you can use placeholders that would be resolved against other property sources, for e.g. values declared in application.properties
Assuming that "my.placeholder" is present in one of the property sources already registered, e.g. system properties or environment variables, the placeholder will be resolved to the corresponding value. If not, then "default/path" will be used as a default. Expressing a default value (delimited by colon ":") is optional. If no default is specified and a property cannot be resolved, an IllegalArgumentException will be thrown.
You can declare properties_home as an environment variable and application_id inside your application.properties file.
#Configuration
#PropertySource("${properties_home}/${application_id}/application.properties")
public class AppConfig {
}
Don't forget to enable support for resolving the placeholders:
In order to resolve ${...} placeholders in bean definitions or #Value annotations using properties from a PropertySource, one must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using in XML, but must be explicitly registered using a static #Bean method when using #Configuration classes.
Update:
In order to override the properties from the external file you could use a spring profile. Inside the packaged application.properties you need to set:
spring.profiles.active=external
Declare all the properties that you want to take precedence as part of the external profile inside the file located in "${properties_home}/${application_id}/application.properties".
The suggestions of #Iulian Rosca to use a pattern like ${properties_home}/${application_id}/application.properties brought me to the idea of defining a custom JVM property like app.config.root and using this property to override spring.config.location very early in the application lifecycle.
My application class looks now like this and works for embedded and container deployments:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return configureApplication(builder);
}
public static void main(String[] args) {
configureApplication(new SpringApplicationBuilder()).run(args);
}
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
return builder
.sources(Application.class)
.properties("spring.config.location:${${app.config.root}/myapp1/:#{null}}");
}
}
Important notes to this solution:
app.config.root has to be set externally by JVM or JNDI property
app.config.root can only contain a single external configuration path (for my requirements this was sufficient) in contrast to spring.config.location where multiple comma-separated paths can be specified
SpringApplicationBuilder.properties(...) sets the application's default properties. Because of this, spring.config.location cannot be specified externally anymore, as JVM or JNDI Properties have priority over default properties and would therefore override spring.config.location again.

Does spring boot support using both properties and yml files at the same time?

I have a spring boot application and I want to use both a yml file for my application properties and also a plain application-${profile}.properties file set to configure my application.
So my question is can this be done and if so, how do you configure spring boot to look for both the yml file and the properties and merge them into one set per environment?
As to why I want/need to use both, it is because I like the flexibility and ease of use of yml files but an internal component (for encryption) requires using the properties file set.
I did see this point being made YAML files can’t be loaded via the #PropertySource annotation
but nothing stating whether both can be used together.
Please provide detailed configuration (XML or Java config) on how to get this working.
TIA,
Scott
I can answer my own question, as it just works as you would expect. The application.yml file and the appropriate application-${profile}.properties both get loaded and merged into the environment. Spring boot just makes this work naturally.
Yes You can use both at same time in same project.
When you use both YML and properties at same time, say for example
application.yml and application.properties at same time in same
project, first application.yml will be loaded, later
application.properties will be loaded.
Important point to be noted is that if application.yml and
application.properties have same keys for example in
application.yml has spring.app.name = testYML and
application.properties has spring.app.name = testProperties at same
time in same project, then application.yml value will be overwritten
by application.properties value since it is loading at last.
And the value in spring.app.name = testProperties.
Yes, you can run both without doing any configuration.
In Spring Boot, it picks .properties or .yaml files in the following sequences :
application-{profile}.{properties|yml}
application.{properties|yml}

Categories

Resources