I am building an executable jar file with maven, meaning that you run it with "java -jar file.jar".
I want to rely on user defined properties (just a file containing keys/values), during developpement phase I was putting my "user.properties" file in maven /src/main/resources/ folder.
My property file is loaded with:
final Properties p = new Properties();
final InputStream resource = IOParametres.class.getResourceAsStream("/user.properties");
p.load(resource);
Now, I want to keep that file outside of the JAR and have something like this :
- execution_folder
|_ file.jar
|_ config
|_ user.properties
I tried many things with maven plugins like maven-jar-plugin, maven-surefire-plugin and maven-resources-plugin but I can't get it working...
Thanks in advance for your help!
I found what I needed using only maven configuration.
First I add config folder to the classpath:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifestEntries>
<Class-Path>config/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
I load resources the same way as before:
final InputStream resource = IOParametres.class.getResourceAsStream("/user.properties");
p.load(resource);
And if you want to keep your example resource files in your repo and remove them from your build:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>user.properties</exclude>
<exclude>conf/hibernate.cfg.xml</exclude>
</excludes>
</resource>
</resources>
</build>
Next to the jar file, I add a config folder holding all the resource files I need.
The result is:
user.properties can be loaded using getResourceAsStream
other libraries relying on specific resources (I won't argue, but I find it... not that good) can load their resources without any issue.
Thanks for the help, and I hope it may help somebody someday!
As I mentioned in the comment - it looks like you want to use user.properties file simply as a text file that lies besides your jar. If that's the case, than using it is rather simple - directory containing your jar file is the current directory when checked during runtime. That means that all you need is:
properties.load(new FileInputStream("config/user.properties"));
without trying to put in on the project classpath.
And if anything else is there to be done, it would just by copying your properties from resources directory to target to avoid the hussle of doing it by hand. That can be achieved by maven-antrun-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<mkdir dir="${project.build.directory}" />
<copy file="${basedir}/src/main/resources/user.properties" tofile="${project.build.directory}/config/user.properties" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
Related
I create an artifact with maven and I want to add some content files to the target consumer beside the jar file. (I want to add some Jenkins scripts, but I want these scripts to get updated when the consumer upgrades into newer version of the artifact).
This is similar to .net nuget, where you can add a content library to the consumer project.
According to #tashkhisi suggestion I'm trying Maven assembly plugin.
The project structure:
> pipline (folder)
>>> file1.groovy (file)
>>> file2.groovy (file)
>>> file3.groovy (file)
> src (folder)
>>> ...
> assembly (folder)
>>> distribution.xml (file)
> pom (file)
In the pom file:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<descriptors>
<descriptor>assembly/distribution.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>trigger-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
The assembly/distribution.xml looes like that:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.4.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.4.1">
<id>distribution</id>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>${basedir}/pipeline</directory>
<includes>
<include>*.groovy</include>
</includes>
<excludes>
<exclude>file2.groovy</exclude>
</excludes>
</fileSet>
</fileSets>
<files>
<file>
<source>pipeline/file2.groovy</source>
<outputDirectory></outputDirectory>
<filtered>true</filtered>
</file>
</files>
</assembly>
I can see in the target folder that two jar files are created:
target/myLib-1.1.0-SNAPSHOT.jar
target/myLib-1.1.0-SNAPSHOT-distribution.jar
But when I try to consume it from another project the pipeline folder with the groovy files is not getting created...
In your configuration you said pipeline is beside src and in your pom.xml you define outputDirectory as <outputDirectory>${basedir}/pipeline</outputDirectory> which is exactly beside src(pipeline is already there!) so if you want to put this pipeline directory beside target jar file in target directory you should modify this configuration to something like this:
<outputDirectory>${basedir}/target/pipeline</outputDirectory>
By the way creating a zip file which contains all the thing that you need in your deployment using assembly plugin is better approach, read the following link:
https://maven.apache.org/plugins/maven-assembly-plugin/
This is not possible.
Adding something as dependency will not add or create any folders in your project.
The consumer will need to add logic to the project to extract files from the dependency and copy them to the right place (probably possible with the Maven dependency plugin).
I have a multimodule maven application that has the following structure:
main-project
->submodule1
->src->main
->java
->MainClass.java
->resource
->php
index11.php
file12.php
file13.php
->submodule2
->src->main
->java
MainClass.java
->resource
->php
index21.php
file22.php
file23.php
->submodule3
->src->main
->java
MainClass.java
->resource
->php
index31.php
file32.php
file33.php
->web-app
->src->main
->webapp
Java classes from submodules should access the php files in their resource directories and execute it using Quercus Resin. However, when the project is packed in war, submodules are packed into jar file that are stored in web-app/WEB-INF/lib, which makes it impossible to execute php files. As workaround for this problem, I found solution to copy all php files from the submodules into the web-app, so when it's extracted in Tomcat, it's not inside jar file and could be executed. For that purpose, I'm using maven-remote-resources-plugin, and all php files are stored to web-app/src/main/webapp/php.
The problem I have now is how to properly provide path to these php files from java classes inside submodules.These java classes are inside jar files when application is deployed to Tomcat, but during development I'm using embedded Jetty server, so I need solution that would work in both cases.
If I use class loader to get resource,e.g. getClass().getClassLoader().getResource("/php/index11.php").getPath() it returns absolute path to the submodule1.jar file.
Any idea how to solve this issue?
I managed to solve this problem, so I will post solution here if it might help someone else.
In each submodule I have a maven-remote-resources-plugin bundle to collect all resources I need
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*.php</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
Then, in web-app submodule I'm using maven-remote-resources-plugin process to copy these php files to resource directories called WEB-INF/php/submodule-name
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<configuration>
<resourceBundles>
<resourceBundle>org.au.morph.offline:morph-sample:${project.version}</resourceBundle>
<resourceBundle>org.au.morph.offline:morph-project:${project.version}</resourceBundle>
</resourceBundles>
<outputDirectory>src/main/webapp/WEB-INF</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
Finally, I created a utility method that resolves the correct path to this directory both when I run application from IDE or in the Tomcat:
public static String getWebContentPath(String contextPath) throws UnsupportedEncodingException {
String path = PathUtils.class.getClassLoader().getResource("").getPath();
String fullPath = URLDecoder.decode(path, "UTF-8");
if(fullPath.contains("/WEB-INF/classes")){
String pathArr[] = fullPath.split("/classes/");
fullPath=pathArr[0];
}
String reponsePath = "";
reponsePath = new File(fullPath).getPath() + File.separatorChar + "php"+File.separatorChar+contextPath;
return reponsePath;
}
I am developing a web application using Spring Boot, and want to generate war instead of jar.
It works very fine using the conversion from jar to war described here : http://spring.io/guides/gs/convert-jar-to-war/
But I want to exclude the application.properties from the war, because I use #PropertySource(value = "file:${OPENSHIFT_DATA_DIR}/application.properties") to get the file path on production environment.
This method works when generating my war, but in eclipse I can't run my application because application.properties not copied at all to target/classes :
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>application.properties</exclude>
</excludes>
</resource>
</resources>
</build>
This method doesn't work at all, I think that spring-boot-maven-plugin doesn't support packagingExcludes :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/classes/application.properties</packagingExcludes>
</configuration>
</plugin>
</plugins>
</build>
Have you another suggestion?
Thanks
Try using the solution below. This will work:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
If you are using the above solution , while running the project in Eclipse IDE you may get error that the properties file is not found. To get rid of this you need to add the resources folder in Run as configuration.(Run configurations... -> Classpath -> User Entries -> Advanced... -> Add Folders)
When running in Eclipse, at your Run Configuration, you need to specify the path of the propeties to Spring Boot:
--spring.config.location=${workspace_loc:/YOURPROYECTNAME}/src/main/resources/
The solution I added is to unzip my packaged war, delete the file application.properties and create a new war named ROOT.war using maven-antrun-plugin and run some ant tasks.
this is what i added to my plugins in pom.xml :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>package</id>
<phase>package</phase>
<configuration>
<target>
<unzip src="target/${artifactId}-${version}.${packaging}" dest="target/ROOT/" />
<delete file="target/ROOT/WEB-INF/classes/application.properties"/>
<zip destfile="target/ROOT.war" basedir="target/ROOT" encoding="UTF-8"/>
<delete dir="target/ROOT"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
I named my target war as ROOT.war because I am using tomcat on openshift PaaS, so I just copy my ROOT.war and push to my openshift repo. That's it
What I understand from your question is, you want to use application.properties for your development. But you dont want to use it for production.
I would suggest using Spring profiles to achieve this.
In your properties file
Create a profile for development. Put all your development properties under it.
Do not create a profile for production in your properties file.
When you are developing, set active profile to development, so that the properties are loaded from your application.properties file.
When you run it in production, set active profile to Production. Though application.properties will be loaded into your WAR, since there is no profile for production, none of the properties will be loaded.
I have done something similar using YML. I am sure there must be a way to do the same thing using .properties file too.
spring:
profiles.active: development
--
spring:
profiles: development
something:
location: USA
unit1: Test1
unit2: Test2
You could change the profile in run time using
-Dspring.profiles.active=production
Try to using this solution:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.version}</version>
<configuration>
<addResources>false</addResources>
</configuration>
</plugin>
<addResources>false</addResources> will keep properties when you run mvn spring-boot:run
Hi all!!
Sorry if this is a dumb question, but I'm new to Maven and have reached an impasse!
I have a project which uses MyTest.properties, MoreMyTest.properties.
I use the Maven Shade plugin to build this project into a .jar file, which is working fine! Unfortunately, the shade plugin is packaging MyTest.properties inside my jar file.
Then, I get this error when I try to execute the jar.
java.io.FileNotFoundException: Unable to locate: properties/MyTest.properties at file:\C:\Dev\test.jar!\properties\MyTest.properties
at ...
I'm wanting to access my properties both inside my IDE, and by running the jar from the command line when I deploy. I was thinking of having my properties files in a relative folder ../lib/ above the location of my jar file.
Inside my program I want to access the properties like so:
File testProperties = new File(
ClassLoader.getSystemResource("properties/MyTest.properties").getFile()
);
I tried adding this to my POM.xml
<transformer
implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
<resource>*.properties</resource>
<file>../*properties</file>
</transformer>
(Sorry the formatting got messed on the above code snippet!)
But, it's not working. I'd really appreciate any help in this. I've not posted all code as the code is really big, but I hope you can get an idea of what I'm trying to achieve.
Many thanks,
Paul
Ok, I have a solution. Always the way, just after posting! But thanks for your reply.
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>../lib</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Where should I put the log4j.properties file when using the conventional Maven directories?
src/main/resources is the "standard placement" for this.
Update: The above answers the question, but its not the best solution. Check out the other answers and the comments on this ... you would probably not shipping your own logging properties with the jar but instead leave it to the client (for example app-server, stage environment, etc) to configure the desired logging. Thus, putting it in src/test/resources is my preferred solution.
Note: Speaking of leaving the concrete log config to the client/user, you should consider replacing log4j with slf4j in your app.
Just putting it in src/main/resources will bundle it inside the artifact. E.g. if your artifact is a JAR, you will have the log4j.properties file inside it, losing its initial point of making logging configurable.
I usually put it in src/main/resources, and set it to be output to target like so:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.directory}</targetPath>
<includes>
<include>log4j.properties</include>
</includes>
</resource>
</resources>
</build>
Additionally, in order for log4j to actually see it, you have to add the output directory to the class path.
If your artifact is an executable JAR, you probably used the maven-assembly-plugin to create it. Inside that plugin, you can add the current folder of the JAR to the class path by adding a Class-Path manifest entry like so:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.your-package.Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Now the log4j.properties file will be right next to your JAR file, independently configurable.
To run your application directly from Eclipse, add the resources directory to your classpath in your run configuration: Run->Run Configurations...->Java Application->New select the Classpath tab, select Advanced and browse to your src/resources directory.
Some "data mining" accounts for that src/main/resources is the typical place.
Results on Google Code Search:
src/main/resources/log4j.properties: 4877
src/main/java/log4j.properties: 215
The resources used for initializing the project are preferably put in src/main/resources folder. To enable loading of these resources during the build, one can simply add entries in the pom.xml in maven project as a build resource
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Other .properties files can also be kept in this folder used for initialization.
Filtering is set true if you want to have some variables in the properties files of resources folder and populate them from the profile filters properties files, which are kept in src/main/filters which is set as profiles but it is a different use case altogether. For now, you can ignore them.
This is a great resource maven resource plugins, it's useful, just browse through other sections too.
When putting resource files in another location is not the best solution you can use:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<build>
For example when resources files (e.g. jaxb.properties) goes deep inside packages along with Java classes.
If your log4j.properties or log4j.xml file not found under src/main/resources use this PropertyConfigurator.configure("log4j.xml");
PropertyConfigurator.configure("log4j.xml");
Logger logger = LoggerFactory.getLogger(MyClass.class);
logger.error(message);
Add the below code from the resources tags in your pom.xml inside build tags.
so it means resources tags must be inside of build tags in your pom.xml
<build>
<resources>
<resource>
<directory>src/main/java/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<build/>