while building a war file i am copying a set of jars from a location to a folder inside the war. While the files do get copied , however i think they get corrupted because the same class files of the jar when taken outside the war opens with a debugger while it does not open after taking from war file .
This is a part of my war pom.xml where i copy the jars
<execution>
<id>copy-jars</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/${project.artifactId}-${buildNumber}/somefolder</outputDirectory>
<resources>
<resource>
<directory>SomeSourceDirectory</directory>
<filtering>true</filtering>
<includes>
<include>**/**</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
SomeSourceDirectory has some jars and some other files
The result is:
myWar/somefolder/a.jar but when i open the classes inside this jar in a debugger..i get error in WinZip that
Invalid compressed data to extract.
Severe Error: Compressed data is invalid
However the same class file can be viewed when i view it in original folder i.e outside the war.
So is there a mistake while copying the jars?
Thanks.
Remove <filtering>true</filtering>, it corrupts the jar files.
Also, you can continue benefit to use maven filtering without corrupting jars inside.
We choose to exclude jar from filtered extensions.
In th pluginManagement section of the parent pom we put this configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>jar</nonFilteredFileExtension>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
<nonFilteredFileExtension>zip</nonFilteredFileExtension>
<nonFilteredFileExtension>bz2</nonFilteredFileExtension>
<nonFilteredFileExtension>gz</nonFilteredFileExtension>
<nonFilteredFileExtension>acp</nonFilteredFileExtension>
<nonFilteredFileExtension>bin</nonFilteredFileExtension>
<nonFilteredFileExtension>odt</nonFilteredFileExtension>
<nonFilteredFileExtension>doc</nonFilteredFileExtension>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
Note we added jar extensions as well as default maven excluded filetypes (its a zip after all).
Besides avoiding corruption of the archive it also speeds up the process as it does not have to filter large files.
Try Maven Assembly Plugin. It's my favourite plugin to add custom resources to a *.war file. See also Pre-defined Descriptor Files.
I had a similar error when I've added
<copy ...>
<fileset ... />
<filterchain>
<tokenfilter>
<replacestring from="..." to="..." />
</tokenfilter>
</filterchain>
</copy>
to my copy task in ANT. It corrupted the jar files when copying them.
I've solved this by applying the filter ONLY on the targeted text files and not on jar files.
Just as addition to the other answers, the other option is to enable the filtering only for the resources that require filtering:
<build>
...
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
<includes>
<include>core.properties</include>
</includes>
</resource>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
<includes>
<include>pdf/color_profile/sRGB.icc</include>
</includes>
</resource>
</resources>
</build>
Related
I'd like to synchronize log4j and logback config files across multiple projects. I have one project (Project A) that contains the log4j and logback dependencies, along with the config files.
Project A
src/test/resources
log4j2.xml
logback-test.xml
Project B has a dependency on Project A. I would like to include the log config files in Project A's JAR and have them automatically put in a specific target folder in Project B when resolving Maven dependencies for Project B.
I have tried maven-jar-plugin in Project A but it doesn't seem to work for my purpose.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<includes>
<include>src/test/resources/log4j2.xml</include>
<include>src/test/resources/logback-test.xml</include>
</includes>
</configuration>
</plugin>
Any help would be appreciated.
Thanks!
UPDATE:
While Eugene's answer was accepted, I needed to add a <resources> entry so the log config files would be included in the packaged JAR.
<build>
<resources>
<resource>
<directory>src/test/resources</directory>
<includes>
<include>log4j2.xml</include>
<include>logback-test.xml</include>
</includes>
</resource>
</resources>
</build>
Executing mvn clean compile assembly:single deploy from Project A created and deployed the JAR with the log files included.
[INFO] --- maven-remote-resources-plugin:1.7.0:bundle (default) # project-a ---
[INFO] Writing META-INF/maven/remote-resources.xml descriptor with 2 entries
Executing mvn clean compile from Project B copied the files into the output directory
[INFO] --- maven-remote-resources-plugin:1.7.0:process (default) # project-b ---
[INFO] Preparing remote bundle com.my.projects:project-a:1.0-SNAPSHOT
[INFO] Copying 2 resources from 1 bundle.
You can use Apache Maven Remote Resources Plugin
This plugin is used to retrieve JARs of resources from remote
repositories, process those resources, and incorporate them into JARs
you build with Maven.
A very common use-case is the need to package certain resources in a
consistent way across your organization. For example at Apache, it is
required that every JAR produced contains a copy of the Apache license
and a notice file that references all used software in a given project
Define in Project A which resources you want to share or better create separate project for shared resources
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<resourcesDirectory>src/test/resources/</resourcesDirectory>
<includes>
<include>log4j2.xml</include>
<include>logback-test.xml</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
Maven will create resources bundle file for sharing resources
${basedir}/target/classes/META-INF/maven/remote-resources.xml
<remoteResourcesBundle xsi:schemaLocation="http://maven.apache.org/remote-resources/1.1.0 https://maven.apache.org/xsd/remote-resources-1.1.0.xsd"
xmlns="http://maven.apache.org/remote-resources/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<remoteResources>
<remoteResource>log4j2.xml</remoteResource>
<remoteResource>logback-test.xml</remoteResource>
</remoteResources>
<sourceEncoding>UTF-8</sourceEncoding>
</remoteResourcesBundle>
See documentation
Configure other modules to use the shared resources
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<configuration>
<outputDirectory>[your output directory]</outputDirectory>
<resourceBundles>
<!--The resource bundles that will be retrieved and processed. For example: org.test:shared-resources:${project.version}-->
<resourceBundle>groupId:artifactId:version[:type[:classifier]]</resourceBundle>
</resourceBundles>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
See documentation
Alternative solution:
Apache Maven Dependency Plugin It can copy and/or unpack artifacts from local or remote repositories to a specified location.
It was described there Maven: Extract dependency resources before test
and there Use a dependency's resources?
UPDATE:
Example how to add resources:
<project>
...
<build>
...
<resources>
<resource>
<directory>[your folder 1 here]</directory>
</resource>
<resource>
<directory>[your folder 2 here]</directory>
</resource>
</resources>
...
</build>
...
</project>
See documentation
Please don't put logging configuration files into JARs, if someone depends on your JAR, your configuration may overwrite theirs. That depends on which JAR is loaded first
If you want, like this. And package them into JAR
src/main/resources
log4j2.xml
logback.xml
I'm trying to package a Spring Project with Maven, but the Beans.xml file is missing.
A lot of people suggest to put the Bean.xml file in the main/resources, but it does not work for me. I think that only works for Eclipse user and I'm just compiling in the terminal using 'mvn clean install'.
Stupid mistake, inside my pom file the directory was like the following:
<build>
<resources>
<resource>
<directory>src/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<excludes>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.gif</exclude>
</excludes>
</resource>
My resources folder was not inside src/main/resources, but src/resources.
And when I open my jar file the Beans.xml file this there and the code runs without error.
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>
I have a JEE6 web application project.The project structure is according to maven convention.
Now I have introduced additional web.xml files for this project.
So they are now stored in WEB-INF as below:
WEB-INF/
|__ A/web.xml
|__ B/web.xml
What is the maven way to build a war to include proper xml depending upon the property.
I know the how to add custom properties in maven.But I cannot find how to configure the maven plugin such that during the war file building it chooses the appropriate file.
Any hints/suggestions/maven best practices in such cases are most welcome.
Thanks!!
maven war plugin could be configured to add and filter some external resources. See http://maven.apache.org/plugins/maven-war-plugin/examples/adding-filtering-webresources.html.
So I would make 2 maven profiles with 2 war plugin configuration like this :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>src/main/webapp/WEB-INF/__A</directory>
<includes>
<include>web.xml</include>
</includes>
<targetPath>WEB-INF</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
<!-- repeat for your second profile -->
BUT I think a better solution (and if your project permits it) would be to keep only one web.xml file with some filtered properties inside. In this case, you should just configure your war plugin to enable some filtering like this :
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<filteringDeploymentDescriptors>true</filteringDeploymentDescriptors>
</configuration>
</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/>