I'm trying to have my resources copied into a classpath depending on which profile was selected using maven. My resources folder structure is as following:
src/main/resources:
config
production
development
staging
My current not-working config is
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>envtype</name>
<value>dev</value>
</property>
</activation>
<build>
<finalName>Corelay</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<excludes>
<exclude>**/production/**</exclude>
<exclude>**/staging/**</exclude>
</excludes>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<excludes>
<exclude>**/production/**</exclude>
<exclude>**/staging/**</exclude>
</excludes>
</testResource>
</testResources>
</build>
</profile>
In hibernate configuration file under config/hibernate/hibernate-config.xml i request some properties from same package
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:**/jdbc.properties</value>
<value>classpath*:**/hibernate.properties</value>
</list>
</property>
</bean>
but there is an error:
Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"
this property is defined in that file. What's wrong? And another question is how to make resources copied from those profile folders appear in exactly same output classpath structure? I mean there should be no /production, /development or /staging : just /env
I know I could just put them into separate in but then if there are shared ones (like config in the presented structure) how could I include it too?
Create a folder src/main/config at the same level as src/main/resources. Inside create 3 sub-folders common, dev and production:
|__common
| |__common.properties
|__dev
| |__dev.properties
|__prod
| |__prod.properties
Then configure two profiles, dev and production:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<resources>
<resource>
<directory>src/main/config/common</directory>
</resource>
<resource>
<directory>src/main/config/dev</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>prod</id>
<build>
<resources>
<resource>
<directory>src/main/config/common</directory>
</resource>
<resource>
<directory>src/main/config/prod</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
With this, mvn clean install copies common.properties and dev.properties to the root of the classpath, as the dev profile is active by default.
mvn clean install -Pprod will then install common.properties and production.properties, but no dev.properties, and also to the root of the classpath.
Related
I try to ask the question in simpler form.
I have a multitier SpringBoot 2.2.6 using maven 3.6, Spring Tool Suite 4 as follows:
main-project
- common-layer (packaging jar)
- service-layer (packaging jar)
- web-layer (packaging war)
- src/main/resources
- application.properties
- application-dev.properties
- application-customer1.properties
- config.properties
parentpom.xml
In my parentpom.xml I have several profile depending on customer I building for:
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profile>[some spring profile]</spring.profile>
<active.profile>dev</active.profile>
</properties>
</profile>
<profile>
<id>customer1</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<spring.profile>[some spring profile]</spring.profile>
<active.profile>customer1</active.profile>
</properties>
</profile>
</profiles>
I also have a resource loader in my build section of web-layer pom.xml because for the 90% of profile this is the required configuration:
<build>
<finalName>${war.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>application-${active.profile}.properties</include>
<include>application.properties</include>
</includes>
</resource>
</resources>
</build>
Now suppose that for the customer X I don't want to bring inside my package no properties file, can I do it in parent.pom?
I'll try with something like:
<profile>
<id>X</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- <spring.profile>[some spring profile]</spring.profile> passing it from command line -->
<active.profile></active.profile>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>application.properties</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
But doesn't work.
This is my properties file where i have added this variable
databaseEnabled=${db.activedb}
Path of my properties file
src/main/resources/application-dev.properties
This is my pom.xml where I have added this code
<build>
<finalName>spring-boot</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>dynamo</id>
<activation>
<property>
<name>env</name>
<value>dynamo</value>
</property>
</activation>
<properties>
<db.activedb>dynamodb</db.activedb>
</properties>
</profile>
<profile>
<id>mongo</id>
<activation>
<property>
<name>env</name>
<value>mongo</value>
</property>
</activation>
<properties>
<db.activedb>mongodb</db.activedb>
</properties>
</profile>
</profiles>
Add includes tag:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>/application-dev.properties</include>
</includes>
</resource>
</resource>
To set profile using -P option:
mvn package -P mongo
To check result open target/classes/application.properties file.
I'm trying to run the build of a project, which has as dependence, a jar of my own.
Code dependency:
<profile>
<id>local-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>ambient</name>
<value>local</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>com.enterprise</groupId>
<artifactId>enterpriseUtil</artifactId>
<version>[0.0.1,)</version>
</dependency>
</dependencies>
<build>
<finalName>${finalName}</finalName>
<resources>
<resource>
<directory>src/main/resources_local</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin-version}</version><!--$NO-MVN-MAN-VER$ -->
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin-version}</version><!--$NO-MVN-MAN-VER$ -->
<configuration>
<attachClasses>true</attachClasses>
<warSourceExcludes>META-INF/context.xml</warSourceExcludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
The strangest thing is that a local build succeeds, even if I exclude the dependency from my .m2, and download from my nexus
The error:
No versions available for com.enterprise:enterpriseUtil:jar:[0.0.1,) within specified range -> [Help 1]
I have a multiple module Maven project where one of the module's POM defined several profiles which copy some configuration file to the target/classes dir:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- Copy common resources that are shared in all environments -->
<phase>validate</phase>
<goals>
<goal>resources</goal>
<goal>testResources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>conf/</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- Copy environment specific resources according to profile used -->
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<testResources>
<testResource>
<directory>src/main/resources/conf/dev</directory>
</testResource>
</testResources>
<resources>
<resource>
<directory>src/main/resources/conf/dev</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>rct</id>
<build>
<testResources>
<testResource>
<directory>src/main/resources/conf/rct</directory>
</testResource>
</testResources>
<resources>
<resource>
<directory>src/main/resources/conf/rct</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>prd</id>
<build>
<testResources>
<testResource>
<directory>src/main/resources/conf/prd</directory>
</testResource>
</testResources>
<resources>
<resource>
<directory>src/main/resources/conf/prd</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
The directory src/main/resources in this module contains the following files :
02/06/2016 11:15 <DIR> com
02/06/2016 11:07 <DIR> conf
02/06/2016 11:19 857 mybatis-config.xml
The conf directory contains some environment separated files. The thing bizarre is that the result of command mvn clean validate -Pdev (executed from the root project) is different while executed on Maven 3.3.9 and Maven 3.2.5:
Result after executed on local machine with Maven 3.3.9:
02/06/2016 18:01 <DIR> com
02/06/2016 18:01 857 mybatis-config.xml
Result after executed on Jenkins (don't have other version of Maven installed on local, I believe this doesn't affect the result since Maven 3.3.9 on Jenkins works gives the same result as on local) with Maven 3.2.5:
02/06/2016 11:08 144 database.properties
02/06/2016 12:38 1 062 log4j.xml
As you see, with Maven 3.3.9, the resource filtering in the validate phase worked and tasks in profile was not executed, while on Maven 3.2.5 it just did the inverse. I wonder how would this happen. Is there a bug in Maven concerning this issue?
I'm trying to build project through maven using different profiles.
I store data to connect to database in file jdbc.properties:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseurl=jdbc:mysql://${db.connectionURL}/shopsstore?useUnicode=yes&characterEncoding=UTF-8
jdbc.username=${db.username}
jdbc.password=${db.password}
And here is my mvc-dispatcher.xml
<bean id="propertyConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="WEB-INF/jdbc.properties" />
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
p:password="${jdbc.password}" />
And pom.xml
<profiles>
<profile>
<id>dev</id>
<properties>
<db.username>root</db.username>
<db.password>root</db.password>
<db.connectionURL>localhost:3306</db.connectionURL>
<db.driverClass>com.mysql.jdbc.Driver</db.driverClass>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<db.username>prod-root</db.username>
<db.password>prod-admin</db.password>
<db.connectionURL>localhost:3306</db.connectionURL>
<db.driverClass>com.mysql.jdbc.Driver</db.driverClass>
</properties>
</profile>
</profiles>
And when i run build i get following exception:
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Could not resolve placeholder 'db.password' in string value "${db.password}"
Seems like properties are not available. Any ideas what's going on?
P.S I'm using Intellij IDEA
EDITED
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
<configuration>
<!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Enabling and configuring web resources filtering -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<webResources>
<resource>
<filtering>true</filtering>
<directory>src/main/webapp/WEB-INF/</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/webapp/WEB-INF/</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
You will have to use the maven-resources-plugin to automatically update the jdbc.properties during build based on the properties set in the profile.
Refer
http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
You have to set <filtering>true</filtering> to enable property replacement in the resources files
As you are using web resources,try changing the maven-war-plugin configuration to
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<targetPath>WEB-INF</targetPath>
<includes>
<include>**/jdbc.properties</include>
</includes>
</resource>
</webResources>
</configuration>