Spring Boot embedded jar and application.properties location - spring-boot

I thought I had this working because in my IDE the correct environment properties file was being used, and a local application.properties was being correctly used. I am trying to use profile specific properties to determine various values throughout my Spring-Boot 1.3.5 app.
My src/main/resources/application.properties is:
spring.profiles.active=test
server.port=8080
deploy.server=http://localhost
liquibase.change-log:classpath:/db/changelog/db.changelog-master.xml
liquibase.check-change-log-location=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
logging.file=myapp.log
spring.jackson.serialization.write_dates_as_timestamps=false
And I have a src/main/resources/application-test.properties:
server.port=8081
deploy.server=https://test.myapp.com
logging.level.liquibase:TRACE
logging.level.org.springframework.security:DEBUG
Now I apparently have two problems:
After I run "gradle clean build" I get my jar and trying to run via:
java -jar build/libs/app.jar -Dspring.profiles.active=local
I see the message:
The following profiles are active: test
So it picking that up from the application.properties file and I can't seem to override it, which I think is causing my second problem:
My Jenkins build fails when I try to use a parameterized build with the values:
spring.profiles.active set to "test".
The error I get is Tomcat in a failed state. If I take that parameter out of the build, it works. But that build will not run from the command line unless I copy the application-{env}.properties to the run directory (which might be best practice anyway?).
I am not sure if the problem is the location of the properties files or the way I am trying to build them.

Related

Profile Specific application.properties Not Applied During Unit Test

I'm writing integration tests, and I'd like to use Spring profiles to configure properties for each environment. However I'm finding profile specific application properties (e.g. application-dev.yml, application-prod.yml) in my src/test/resources directory aren't activated the same way they are in src/main/resources. It appears running tests with -Dspring.profiles.active=prod has no effect. Is it possible to activate a profile from the command line for tests?
Note: #ActiveProfiles isn't sufficient because I want to run the same tests against multiple environments.
I don't know if you have copied the file names from your workspace but 'applicaiton-prod.yml' has a typo in it. That could be the reason.
I found a similar issue reported in GitHub and the solution was applicable to my problem. The JVM system property spring.profiles.active wasn't getting picked-up in Gradle. So I modified my task as follows
integrationTest {
systemProperties = System.properties
}

Specifying application config file by name when Spring Boot starts up

Currently I can build my Gradle-based Spring Boot app like so:
./gradlew build && java -Dspring.config=. -jar build/libs/myapp.jar
And this works fine provided I have an application.yml in the root of my project directory.
However, I would now like to have both an application-local.yml as well as an application-dev.yml, and to specify which one to use when I build + run myapp.jar.
How can I specify either file at startup?
You can use Spring boot's capability of using Profile Specific property file.
You can specify the application yml inline with your profile name
application-[profile].yml. In your case, it would be
application-dev.yml
application-local.yml
Specify the profile you would want to use as a command line argument
-Dspring.profiles.active=dev

In Spring Boot, how do you build a JAR file for a different profile even if proper environment variables have not been set?

I'm new to Spring Boot, so bear with me. Currently, I'm working on a small app just for the purposes of learning Spring Boot. My goal is to deploy it using AWS (elastic beanstalk).
So far, I've created three application properties files:
application.properties: Properties which apply to all profiles.
application-dev.properties: Properties only for development. This includes localhost connection to DB, path to self signed key store, etc.
application-prod.properties: Properties used only for prod. This includes the prod DB details, etc.
Everything works fine when running the app locally using the dev profile since everything has been hard coded in the application-dev.properties.
However, the application-prod.properties file contains references which will be resolved through OS environment variables, such as:
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
I currently do not have the variables DB_USERNAME and DB_PASSWORD set up in my local OS, and I do not wish to do so. But when I run the following command, it obviously fails:
mvn package spring-boot:repackage -Dspring.profiles.active=prod
It fails because it's unable to find the above environment variables.
Is there any way to delay this check until I actually execute the JAR? My plan is to build the JAR locally and then copy it over to my prod server, and run it there. The prod server will definitely have these environment variables.
The workaround I found is this:
mvn package spring-boot:repackage -Dspring.profiles.active=dev
java -jar -Dspring.profiles.active=prod [jar-file-name].jar
However, this feels like a hack. And it may cause issues in the future that I can't think of right now.
You can use any value you want in those properties for prod profile. If the env varieble exists, Spring will take the value from there instead of the properties.
As explained here:
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
[...]
OS environment variables.
[...]
Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
So your application-prod.properties can look like this:
spring.datasource.username=willBeOverridenByEnvValue
spring.datasource.password=willBeOverridenByEnvValue
You have to make sure though that you set both SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD env values in your prod server

Build Spring project for run on another system

I Successfully create a spring boot project on my own local system. I want to build a jar file so I can install it on remote server. so I had to configure server address and mySql address of remote server but I can not Build and it have many errors, and they all right cause my system can not see the remote server address and database.
this is my .properties file:
spring.datasource.url=jdbc:mysql://localhost:8081/aths
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create
server.address=192.168.24.250
server.port=8080
how can handle it for running on another configurations? ( another IP, datasource, and ...)
Am I doing it right or not? thanks
You can use spring profiles here :
Create different property files for different profiles using application-{profile}.properties format, e.g. application-dev.properties for dev, and application-prod.properties for production put your profile specific configurations in them. Then when you're running the spring boot application, activate your intended profile using the SPRING_PROFILES_ACTIVE environment variable or spring.profiles.active system property.
and at the end, you will run your jar file with command
java -jar -Dspring.profiles.active=prod application.jar
You can have different application.properties within your resources folder and use spring profiles for example application-{profile}.properties and run the application with the specified profile. However this still limits the configuration items to what has been hard coded within the properties files. When running the application, if it was to be distributed to other people, where non of the profiles are supported you can provide a properties file at start up.
So in the same directory for example as the .jar file create a file named application.properties with empty place holders for all the variables required for the application so the admin can enter the details correct for them. Then they will be required to start the application with the following command
java -jar 'applicaitonname.jar -Dspring.config.name="file:/path/to/application.properties"
Or springboot will load properties from application.properties files in the following locations:
A /config subdirectory of the current directory.
The current directory
Failing that the default application.properties from the resources folder will be loaded.

Is there a way to tell gradle which profiles should be used for the tests?

I use the yml configuration files pattern application-{default,dev,production}.yml.
To define which configuration application will use, I fix the environment SPRING_PROFILES_ACTIVE=dev so when the spring app run, it choose the correct configuration.
I have now theses two issues:
The ./gradlew build command also run the test command, test need to have the correct configuration as the application does when it start.
My jenkins does not have access to the database and the units tests keep failing.
Which make make ask:
Does the build command tries all the datasource in order ? Is there a way to specify the spring boot active profile ?
Is there another different approach for deploying spring-boots app in production from jenkins ?
Does anyone has a workaround except
./gradlew -x test build
This is not what I want.
Neither adding #ActiveProfile("dev") to my tests because this require source code modification.
Simply Create multiple property files.For Example:
application.properties
application-test.properties
application-production.properties
Provide different properties based on profile and
Below you can specify
which profile to load in you gradle.build file
def profile = "test"
bootRun {
args = ["--spring.profiles.active="+profile]
}
Put below code in the end of gradle file

Resources