how to include specific applicaction.properties in spring boot war - java

I need to create different application properties for a spring boot project and include the proper one in the generated war. I'm able to generate a war, but no to include the proper file in it. I have different profiles created, and different application.properties following the pattern application-env.properties where env is (dev, cert...), all of then placed in src/main/resources but I'm not able to pick the proper one and include in the generated war, even including "-Dspring.profiles.active=cert" to define the profile active. The war is generated with all of them. Any idea?
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
<packaging.type>jar</packaging.type>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>cert</id>
<properties>
<build.profile.id>cert</build.profile.id>
<spring.profiles.active>cert</spring.profiles.active>
<packaging.type>war</packaging.type>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>

Related

Maven dependency only for testing purposes

I have a maven dependency like this:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${version}</version>
</dependency>
And the thing is that the ${version} property should be replaced by 1.8.1.RELEASE or 1.9.0.RELEASE depending on the profile I choose when installing, but for testing purposes only the 1.9.0.RELEASE should be used, even if I'm using the 1.8.1 profile. Is there a way to do this? I tried using the test scope but it didn't work as I think it would.
Would something like this work for you?
<profiles>
<profile>
<id>defaultProfile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<magicVersion>1.9.0.RELEASE</magicVersion>
</properties>
</profile>
<profile>
<id>Release181</id>
<properties>
<magicVersion>1.8.1.RELEASE</magicVersion>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<magicVersion>1.9.0.RELEASE</magicVersion>
</properties>
</profile>
</profiles>
The idea being is activating the test profile will overwrite the version even if it's been set already by your 1.8.1 profile. Use case would be;
mvn -P Release181,test test

How to specify packaging in a Maven profile?

I have a project which can be packaged and deployed two different ways, it's either a WAR for Tomcat, or a shaded JAR for AWS Lambda. Currently this isn't working very well, I have to keep changing the pom.xml back and forth when doing a release. Is there a way to accomplish this with Maven profiles?
e.g., I'd like to do
mvn install -Pwar
to generate the WAR, and
mvn install -Plambda
to generate the shaded JAR.
Is this possible?
You can try to include the following in your pom.xml
<packaging>${packaging.type}</packaging>
<profiles>
<profile>
<id>lambda</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<packaging.type>jar</packaging.type>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
</profile>
</profiles>

How to parameterize a Maven file (pom.xml)?

I have a spring boot application where I want to package it according to the profile I am building with, for example when I issue profile x, I want maven to build as a jar; but when building with profile y, I want maven to build as a war.
I want something like:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<package>${buildMethod}</package>
</project>
Where ${buildMethod} is the type of packaging.
This would be decided by executing a command i.e. mvn package -P buildProfile.
Maybe this would help:
<profiles>
<profile>
<id>war</id>
<properties>
<deploy.type>war</deploy.type>
</properties>
</profile>
<profile>
<id>jar</id>
<properties>
<deploy.type>jar</deploy.type>
</properties>
</profile>
</profiles>
And then just use this property placeholder ${deploy.type}.
You can easily add profiles, with a list of properties, to your pom file.
Build using:
mvn package - Builds a WAR by default (implicit)
mvn package -P deployWar - Builds a WAR
mvn package -P deployJar - Builds a JAR
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0</version>
<package>${deployment.type}</package>
<profiles>
<!-- This profile deploys the application as a WAR (default) -->
<profile>
<id>deployWar</id>
<properties>
<deployment.type>war</deployment.type>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- This profile deploys the application as a JAR -->
<profile>
<id>deployJar</id>
<properties>
<deployment.type>jar</deployment.type>
</properties>
</profile>
</profiles>
</project>

How to set spring active profiles with maven profiles

I have an application with maven as a build tool.
I am using maven profiles to set up different properties from different profiles.
What i would like to do is that all active profiles in maven will be ported to spring active profiles as well so i can reference them in bean signature (#profile). but i am not sure how to do it.
for example: consider the following maven setup
<profiles>
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
</properties>
</profile>
<profile>
<id>profile2</id>
<properties>
</properties>
</profile>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
</properties>
</profile>
</profiles>
assuming i run maven with out specifying any other profiles i would like for spring to have profile1 and development as active profiles.
There is a more elegant way to switch between 2 maven+spring profiles simultaneously.
First, add profiles to POM (pay attention - maven+spring profile is activated by single system variable):
<profiles>
<profile>
<id>postgres</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>spring.profiles.active</name>
<value>postgres</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>h2</id>
<activation>
<property>
<name>spring.profiles.active</name>
<value>h2</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.191</version>
</dependency>
</dependencies>
</profile>
</profiles>
Second, set default profile for spring (for maven it is already set in POM). For web application, I inserted following lines to web.xml:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>postgres</param-value>
</context-param>
Third, add profile-dependent beans to your config. In my case (XML config), it is:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mainDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties" ref="hibProps"/>
<property name="packagesToScan">
<list>
<value>my.test.model</value>
</list>
</property>
</bean>
...
<beans profile="postgres">
<bean name="mainDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://127.0.0.1:5432/webchat" />
<property name="username" value="postgres" />
<property name="password" value="postgres" />
</bean>
</beans>
<beans profile="h2">
<bean name="mainDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:file:./newsdb;INIT=RUNSCRIPT FROM 'classpath:init.sql';TRACE_LEVEL_FILE=0" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
</beans>
Now it is possible to:
Run my web-app on Postgres DB with mvn jetty:run or mvn jetty:run -Dspring.profiles.active=postgres commands
Run my web-app on H2 DB with mvn clean jetty:run -Dspring.profiles.active=h2
The first thing you need is two properties files for keeping your configurations. The names of the files should match with the pattern application-{custom_suffix}.properties. Create them in the src/main/resources directory of your Maven project, next to the main application.properties file, which you’re going to use later to activate one of the others and to hold values shared by both profiles.
Then it’s time to modify your pom.xml. You need to define a custom property in each of your Maven profiles and set their values to match with suffixes of corresponding properties files that you want to load with a particular profile. The following sample also marks the first profile to run by default, but it’s not mandatory.
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>release</id>
<properties>
<activatedProperties>release</activatedProperties>
</properties>
</profile>
Next, in the build section of the same file, configure filtering for the Resources Plugin. That will allow you to insert properties defined in the previous step into any file in the resources directory, which is the subsequent step.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
…
</build>
Finally, add the following line to the application.properties.
spring.profiles.active=#activatedProperties#
When the build is run, the Resources Plugin will replace the placeholder with the value of the property defined in the active Maven profile. After starting your application, the Spring framework will load the appropriate configuration file based on the name of the active Spring profile, which is described by the value of the spring.profiles.active property. Note that Spring Boot 1.3 replaced the default Resources Plugin syntax for filtered values and uses #activatedProperties# instead of ${activatedProperties} notation.
It worked to perfection. Hope this can help you.
You'll have to filter a resources of your application, for instance a property file, that holds the information of which profile to activate in spring.
For instance
spring.profile = ${mySpringProfile}
And for each profile, define a value for this variable (mySpringProfile).
During the build, this will be filtered accordingly to the value defined in the currently active profile.
Then during the bootstrap of your application you'll select the appropriated profile according to this file (can't help you more as you didn't gave us more information, but this is quite easy.
Note: I can't find a way to get the currently active profile in maven (something like project.profiles.active that holds your -P values), that's why you'll have to set a new variable for each profile.
Note 2: if you are running a web application, instead of using this intermediate file, filter this value in your web.xml
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>${mySpringProfile}</param-value>
</context-param>
Note 3: This is actually a bad practice, and you should set the profile at runtime with a system property
For a Spring Boot application, one can add a property in the Maven profile in pom.xml and then reference that property in application.properties.
Add Maven profiles to pom.xml with, for example, a property called spring.profile.from.maven:
<profiles>
<profile>
<id>postgres</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profile.from.maven>postgres</spring.profile.from.maven>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>noDb</id>
<properties>
<spring.profile.from.maven>noDb</spring.profile.from.maven>
</properties>
</profile>
</profiles>
Reference the Maven property in application.properties:
spring.profiles.include=#spring.profile.from.maven#
With this setup, running maven with the postgres Maven profile or with no profile adds the postgres Spring profile to the list of Spring's active profiles, while running maven with the noDb Maven profile adds the noDb Spring profile to the list of Spring's active profiles.
Add placeholder ${activeProfile} in web.xml:
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>${activeProfile}</param-value>
</context-param>
Set properties in pom.xml for each profile:
<profiles>
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<activeProfile>profile1</activeProfile>
</properties>
</profile>
<profile>
<id>profile2</id>
<properties>
<activeProfile>profile2</activeProfile>
</properties>
</profile>
</profiles>
Add maven-war-plugin and set <filteringDeploymentDescriptors>true</filteringDeploymentDescriptors> to replace the placeholder when running mvn package -Pprofile1 or mvn package -Pprofile2:
<build>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
</configuration>
</plugin>
</build>
I'm currently building a small webapp that (due to reasons beyond my control) has to be capable of running on an old server/container that only supports Servlet 2.5 and Java 6. There is also a requirement for the webapp configuration to be completely self-contained, so even system variables and/or JVM parameters cannot be used. The administrator just wants a .war file for each environment that can be dropped into the container for deployment.
I'm using Spring 4.x in my webapp. This is how I configured my application such that the active Maven profile is used to set the active Spring 4.x profile.
pom.xml file changes
I added the following bits to my POM file. My POM is using model version 4.0.0 and I'm running Maven 3.1.x when I do my builds.
<modelVersion>4.0.0</modelVersion>
...
<profiles>
<profile>
<id>dev</id>
<activation>
<!-- Default to dev so we avoid any accidents with prod! :) -->
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- This can be a single value, or a comma-separated list -->
<spring.profiles.to.activate>dev</spring.profiles.to.activate>
</properties>
</profile>
<profile>
<id>uat</id>
<properties>
<!-- This can be a single value, or a comma-separated list -->
<spring.profiles.to.activate>uat</spring.profiles.to.activate>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<!-- This can be a single value, or a comma-separated list -->
<spring.profiles.to.activate>prod</spring.profiles.to.activate>
</properties>
</profile>
</profiles>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<webResources>
<webResource>
<filtering>true</filtering>
<directory>src/main/webapp</directory>
<includes>
<include>**/web.xml</include>
</includes>
</webResource>
</webResources>
<failOnMissingWebXml>true</failOnMissingWebXml>
</configuration>
</plugin>
...
</plugins>
</build>
web.xml file changes
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Setup for root Spring context
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-core-config.xml</param-value>
</context-param>
<!--
Jim Tough - 2016-11-30
Per Spring Framework guide: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-environment
...profiles may also be activated declaratively through the spring.profiles.active
property which may be specified through system environment variables, JVM system
properties, servlet context parameters in web.xml, or even as an entry in JNDI.
-->
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>${spring.profiles.to.activate}</param-value>
</context-param>
<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
Now I can create Java-based configuration classes like the one below that will only be used when a particular Spring profile is active.
#Configuration
#Profile({"dev","default"})
#ComponentScan
#EnableTransactionManagement
#EnableSpringDataWebSupport
public class PersistenceContext {
// ...
}
spring boot plugin itself can help:
<profiles>
<profile>
<id>postgres</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jmxPort>9001</jmxPort>
<environmentVariables>
<SPRING_PROFILES_ACTIVE>postgres</SPRING_PROFILES_ACTIVE>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>h2</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jmxPort>9002</jmxPort>
<environmentVariables>
<SPRING_PROFILES_ACTIVE>h2</SPRING_PROFILES_ACTIVE>
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
In the spring boot application, there are several ways to set profiles (dev, uat, prod, etc.)
For exmaple : You can add this in your property file:
spring.profiles.active=dev
Programmatically:
SpringApplication.setAdditionalProfiles("dev");
To specify what profiles are active, use this line
#ActiveProfiles("dev")
In a Unix environment
export spring_profiles_active=dev
Running the jar file with the dev profile.
java -jar -Dspring.profiles.active=dev JARNAME.jar
here JARNAME.jar means your application's jar

JDK tools.jar as maven dependency

I would like to put JDK tools.jar as compile dependency. I found some examples that indicate to use the systemPath property like the following:
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
The problem is that the path is not correct for Mac Os X (however it is correct for Windows and Linux). For it, the correct path is ${java.home}/../Classes/classes.jar.
I am looking for a way in order to define a maven property such that if system is detected as Mac Os X, value is set to ${java.home}/../Classes/classes.jar, otherwise it is set to ${java.home}/../lib/tools.jar (like it is possible to do with ANT). Does someone has an idea ?
That's what profiles are for, extract the path to a property, setup profiles for windows, OSX, etc, and define the property values appropriately.
Here's the doc page that discussing profiles for OSes: Maven Local Settings Model
It should endup looking something like this:
<profiles>
<profile>
<id>windows_profile</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
<profile>
<id>osx_profile</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
</properties>
</profile>
</profiles>
Thank you for introducing me maven profiles.
I have used profile as mentioned above and by activating a profile based on the presence of the desired file :
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
<profile>
<id>mac-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<file>
<exists>${java.home}/../Classes/classes.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
</properties>
</profile>
</profiles>
I posted this answer to highlight a mistake in the previous post : the property section can only be used in activation section in order to activate a profile based on the existence of the specified property. In order to define a property, the properties section must be used like above.
Hi I know you guys are all smart, but it caused me couple of days to figure out the answer is not complete - both the profile and the dependency is necessary. I hope no one will waste time on this again. Please see my complete code below:
<profiles>
<profile>
<id>osx_profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
</properties>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.6.0</version>
<scope>system</scope>
<systemPath>${toolsjar}</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
I found a solution in Q: Declare maven dependency on tools.jar to work on JDK 9
As the actual maven wizardry is quite elaborate, surprising to newcomers and a subject of future improvements, it is better not co copy-paste it around. Hence this module exists so you do not have to know or care about the details. ~~ https://github.com/olivergondza/maven-jdk-tools-wrapper
<dependency>
<groupId>com.github.olivergondza</groupId>
<artifactId>maven-jdk-tools-wrapper</artifactId>
<version>0.1</version>
</dependency>
Somehow, the eclipse in windows fails to pick up {java.home}. So, I had to set JAVA_HOME instead of java.home. JAVA_HOME was set in Run->Run Configurations->Environment. This worked for me with standard JDK(not Apple JDK).
<profiles>
<profile>
<id>windows-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${JAVA_HOME}/lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${JAVA_HOME}/lib/tools.jar</toolsjar>
</properties>
</profile>
<profile>
<id>mac-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>jdk1.8.0</version>
<scope>system</scope>
<systemPath>${toolsjar}</systemPath>
</dependency>
</dependencies>
The comment of Edward is correct.
You need the profile AND you need the dependency outside of the profiles block.
The profile just determines which value ${toolsjar} is gonna get.
<dependencies>
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>jdk1.8.0</version>
<scope>system</scope>
<systemPath>${toolsjar}</systemPath>
</dependency>
</dependencies>
Proper instructions for beginners
First Add this profile to Pom.xml file above tag or somewhere else in it.
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
</properties>
</profile>
<profile>
<id>mac-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<file>
<exists>${java.home}/../Classes/classes.jar</exists>
</file>
</activation>
<properties>
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
</properties>
</profile>
</profiles>
then Correct JRE path
Goto :
Windows > Preferecnes > Installed JREs
selected intalled JRE and double click on it or from right menu click edit and then make sure JRE Home path is inside JDK something like:
C:\Program Files\Java\jdk1.8.0_181\jre
if you have installed JRE seperatly then eclipse would have picked standalone JRE like:
C:\Program Files\Java\jre1.8.0_181\
so change it to JRE which come with JDK:
C:\Program Files\Java\jdk1.8.0_181\jre
my solution:
put the Sun's tools.jar to the $JAVA_HOME/lib
make a symlink in the $JAVA_HOME/.. named lib where target will be $JAVA_HOME/lib

Categories