How to build the environment specific war file for a spring boot application using maven.I have created 3 profile configuration files placed in src/main/resource/ folder.
application.prod.properties
application.dev.properties
application.test.properties
I am able to run application by specifying required profile type in the VM argument tab with the value "-Dspring.profiles.active=dev" while executing the project as spring boot application.
Here while running as spring boot application i am able to the specify the required profile. In the same way when I need to use for MAVEN install with different profile. Is it there any way to specify profile as part of VM argument list in Run Configuration for Maven Install goal.
I have limitation as not to touch the existing java code.
I am using STS IDE, Spring boot 1.5.2.RELEASE version, Java 1.8 and oracle db.
In the same way also help me in how to configure profiles in Jenkins.
My profile configuration has two requirements.
Run the application in STS IDE as spring boot app with the VM args.
Used the below VM ARGS
-Dspring.profiles.active=dev
Blockquote
(Here I am getting below exception while starting SpringBootApp locally in Dev Environment).
APPLICATION FAILED TO START
Description:
Cannot determine embedded database driver class for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (the profiles "dev" are currently active).
Blockquote
How to do the same thing using maven install by specifying profiles dynamically to generate war file.I am unable to find the solution.
In your main application.properties file, set spring.profiles.active to #myActiveProfile# (or any name you wish)
spring.profiles.active=#myActiveProfile#
Add your application.properties file as a filtered resource so that the placeholder myActiveProfile is replaced during build phase.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
…
</build>
Add a profiles section to your pom.xml
<profiles>
<profile>
<id>dev</id>
<properties>
<myActiveProfile>dev</myActiveProfile>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<myActiveProfile>prod</myActiveProfile>
</properties>
</profile>
</profiles>
Basically, you are able to specify maven profiles when executing a particular goal. E.g mvn install -P profileName. Within a profile, you can create a property which can be passed from the command line when running a goal like mvn install -DmyActiveProfile=foo
Hope this helps.
Helpful Links
How to set spring active profiles with maven profiles
https://maven.apache.org/guides/introduction/introduction-to-profiles.html
Here, first of all I would suggest to rename your properties files to application-prod.properties, application-dev.properties and application-test.properties.
Second, maven install goal is to compile and build your project.
If you also want to run your application, when you do install I suggest to use spring-boot-maven-plugin.
And you can use a maven command something like below
mvn clean install spring-boot:run
Some links below for you information
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-running-your-application.html
https://docs.spring.io/spring-boot/docs/current/maven-plugin/run-mojo.html
Related
This has been driving me crazy - I have a Spring Boot app which uses Maven as its build tool. In the POM there are various profiles set up, which point to resources in a corresponding directory within the project, so that if you build, for example, with
mvn clean install -PBrandADev
you get Brand A's Dev profile, with the corresponding application.properties and other config files, and if you build it with
mvn clean install -PBrandBProd
you get Brand B's production profile. This is important to me because it controls which CMS I'm connecting to, and thus I'm able by building as Brand B Prod to run an instance of the Prod environment in debug & see what's going wrong when there's a bug, or otherwise to build the Dev profile for the development work I'm doing, to plug into the Dev CMS.
As it's a Spring Boot app, in the resources directory for each profile we have a banner.txt file that says "Brand A - Dev" or "Brand A - QA" or whatever the brand & CMS is for that profile.
Just lately though, I'm building for a particular profile, e.g. I want Brand B's Preview-Prod environment, and I see when it starts up for its integration tests "Brand B - Preview-Prod", which is as should be expected, but then when I start it up using the Application config item in the Run/Debug configurations widget at the top of the screen, it starts up saying "Brand A - Dev"
I've tried cleaning & reinstalling the app. I've tried re-importing the maven dependencies. I've tried invalidating the cache and restarting the IDE. I've tried deselecting all the profiles and reselecting the one I need. No joy. Except, just earlier today, it worked, and then I tried to swap back to the Dev environment & it got stuck on Prod. Does anyone know what I can do to force it to use the profile it's built with? Is this a bug in IntelliJ or what?
You can use the spring-boot maven plugin instead.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
This allows you to use mvn spring-boot:run -PBrandADev and start the spring boot application with the correct maven profile.
A possible reason of such behaviour could be the Run Configuration used to start the application which builds it using default profile before starting the application. Verify Before Launch section of the configuration.
As a workaround, create a Run Configuration per profile you'd like to start, and specify -Dspring.profiles.active=<PROFILE-NAME> in the VM Options of the run configuration. Additionally, you could build the application using the same profile before starting it, adjust the Before Launch section accordingly.
I can make the Azure ops pipeline but my question is I have checkedin my code into repository where we should not checkin the application property file.
That means on the deployment time i should have to download the application property file from some secure place and build my spring boot app before i deploy into app engine right.
So, what i did so far is, I downloaded my application property file into azure agent at run time. I passed the property file into maven build command but it did not work out. [Note: I already searched a lot read a lot of answers and applied as well but nothing worked]
Command line I used:
mvn -f myapp-springboot-api/pom.xml
-Dspring-boot.run.jvmArguments="-Dspring.config.location=file:/home/username/application.properties"
clean package appengine:deploy
I also tried with
mvn -f myapp-springboot-api/pom.xml
--spring.config.location=file:/home/username/application.properties
clean package appengine:deploy
This also did not workout.
Also, I tried passing the whole property file location via pom.xml
pom.xml changes:
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>1.1.1.RELEASE</spring-cloud.version>
<property.file.location>${property.file.location}</property.file.location>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<configuration>
<files>
<file>${property.file.location}</file>
</files>
</configuration>
</plugins>
</build>
Than I tried to build with:
mvn -f myapp-springboot-api/pom.xml
-Dproperty.file.location="/home/username/application.properties" clean package appengine:deploy
Than also I was not able to load the define external property file.
Thanks in advance, please help your help is highly appreciated.
The commands you are using won't actually pass the external properties files to the application engine (As it exists on a different server) and would only be scoped to the running maven process that is packaging + deploying.
So if you have copied your property file onto the external agent before building I would just replace the default one you have checked into source control.
So your build steps would be for example:
Download property file
Overlay:
mv /home/username/application.properties myapp-springboot-api/src/main/resources/application.properties
Build + Deploy
mvn -f myapp-springboot-api/pom.xml clean package appengine:deploy
So now your compiled and deployed jar file would include your new properties file, an alternative that recently came out would be to use something like Azure App Configuration.
If you want to not have to do another command you could also use the Maven Resources Plugin to perform the copy for you.
I am running the spring boot app by passing the spring active profile like below:
spring-boot:run -Dspring.profiles.active=dev
But how do I pass the spring.profiles.active when creating the package using maven. Following is the maven command:
mvn clean install
In case someone have the same situation, you can achieve this with 2 steps with spring boot and maven:
First in spring properties or yaml file, add the spring.profiles.active with it's value as placeholder:
spring.profiles.active=#active.profile#
Second, pass the value with maven:
mvn clean install -Dactive.profile=dev
When the jar/war packaged, the value will be set to dev.
you can also leverage the use of maven profiles:
<profiles>
<profile>
<id>dev</id>
<properties>
<active.profile>dev</active.profile>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<active.profile>test</active.profile>
</properties>
</profile>
</profiles>
Then run:
mvn clean install -Pdev
Maven is a build-time tool, the only way to make it modify the eventual runtime behaviour of the built artifact is to use its (build-time) profiles. This must not be confused with Spring's runtime profiles which are parameters instructing the Spring container to bootstrap application in a specific way.
In other words, the spring.profiles.active parameter doesn't get "baked into" the war file by maven, you'll still need to pass it when starting the application up, be it via command-line parameters or configuration file or whatever mechanism your servlet container offers.
For package, you may replace install with package
mvn clean install -P dev
You can use environment variables.
export SPRING_PROFILES_ACTIVE=some,test,profiles
mvn spring-boot:run
I would like to have the following scenario:
Jenkins to grab my github repo (check!)
find a particular file in my project (persistence.xml let's say)
locate the parameter (for example PASSWORD_PLACEHOLDER)
swap it in with a password I've previously provided it before running my tests
Run my tests (via Maven) that depend on the DB connection the password is for
Question: Can this be done easily and if so, how? Should this be a MAVEN responsibility or a Jenkins one?
You could achieve it using Maven filtering on test resources (or on resources, if you prefer).
You can configure your POM as following:
<properties>
<secretPassword>xxxx</secretPassword>
</properties>
<build>
<testResources>
<testResource>
<filtering>true</filtering>
<directory>src/test/resources</directory>
</testResource>
</testResources>
</build>
And have your persistence.xml file under src/test/resources with the following sample content:
<test>
<password>${secretPassword}</password>
</test>
Then, from command line you can pass a value for this token as below:
mvn clean test -DsecretPasword="p4ssw0rd"
And Maven will automatically replace the token in the persistence.xml file with the provided value. As per Maven lifecycle, this replacement will occur before any test execution.
Once this mechanism is in place, you can then proceed with the Jenkins setup:
Jenkins check the code out from version control
Jenkins runs a Maven execution on the workspace passing to Maven the desired password value as on the example above
Maven will replace the token and execute the tests
A common and good practice is also to place this behavior in a dedicated maven profile, having id ci for example, and then activate it as part of the Jenkins build (via the -Pci option, in this case, passed to maven).
Hence, back to your questions:
Can this be done easily and if so, how?
Yes, as described above
Should this be a MAVEN responsibility or a Jenkins one?
Maven and Jenkins working together
Additionally, beware that the password you passed would be part of the Jenkins build output on the Jenkins server (it will print the Maven command executed and as part of it the value you passed for the password, in clear).
You can check the Mask Password Jenkins Plugin to mask the password from the build output.
Here is an example profile in my POM:
<profiles>
<profile>
<id>QA</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jdbc.url>jdbc:mysql://127.0.0.1:3306/SomeDB</jdbc.url>
<jdbc.username>webapp</jdbc.username>
<jdbc.password>somepassword</jdbc.password>
</properties>
</profile>
...
I then have a properties file in my resources folder like this:
jdbc.url = ${jdbc.url}
jdbc.username = ${jdbc.username}
jdbc.password = ${jdbc.password}
and finally I turn filtering on in my POM:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
This is actually a simplified example, but you get the idea. Basically when I run
mvn install -P QA
Maven will filter my app.properties file, replace all the placeholders with the values held in the profile, and deploy the populated properties file.
The problem with all of this is that I like to utilize the Servers mechanism in Eclipse, where I have Tomcat running within the IDE. My projects runs in this instance, and Eclipse takes care of updating, redeploying, etc. Maven is left out of the picture, however, during deployments within the IDE and this properties file never gets populated properly.
So, how can I continue running my project within the IDE, but have this properties file properly populated?
You can effectively run any Maven command (including ones with profiles) through the m2eclipse plugin. Also, m2eclipse works with WTP (which I believe is where the Servers tab comes from). I'm not certain on this part, but I've used it to deploy web apps to Tomcat within Eclipse for a Maven project.
Thanks Alex. I ended up installing Eclipse Integration for Apache Maven (Eclipse IAM), formerly Q for Eclipse
This plugin solved two problems: populating properties files during Publish to Server events in Eclipse and populating the WEB-INF/lib folder. Before, even though I was running mvn eclipse:eclipse to satisfy my Build Path in Eclipse, it was not publishing these dependencies to the embedded servers correctly. This plugin does that. Having solved these two issues, I don't see any other barriers to developing a Maven project in Eclipse using the embedded servers.