Copy resource files from submodule into main module in maven - java

In my java application, I am just wondering if it is possible to copy or just use resource files from under src/main/resources from a maven submodule into a main maven module (which has the submodule as a dependency) src/main/resources folder, so I don't need to copy manually all the resource files again into my workspace.

You can use the maven dependency plugin to do that.
Here is a configuration that you can include in your main module pom.xml in the build > plugins section.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>hepl.cecotepe.epick</groupId>
<artifactId>wsdl</artifactId>
<version>${wsdl.version}</version>
<type>jar</type>
</artifactItem>
</artifactItems>
<overWrite>true</overWrite>
<outputDirectory>${basedir}/src/main/resources/webservices</outputDirectory>
<includes>**/*.wsdl, **/*.xsd</includes>
<excludes>**/META*/**, **/Documentation/**</excludes>
</configuration>
</execution>
</executions>
</plugin>
The artifactItem is the module from which you want to copy the files into your module. In this case, you will fill the artifactItem fields with your submodule groupId, artifactId and version.
The plugin will take all .wsdl and .xsd files across all folders (including target, src and subfolders) except the Documentation and META* folders (and subfolders). The files will be copied each time in the main module /resources/webservices folder.
To make the whole thing work, you need to package the submodule as a jar (include jar in your submodule pom.xml) and install it in your local maven repository using mvn install. After, you can copy the files in the main module with mvn initialize
NOTE : The initialize phase is included in the default lifecycle and is the first phase executed. When you use the default lifecycle, the first thing maven will do will be to copy the files from the submodule to the main module.

Related

Maven package in-project repository dependencies inside jar

I am using the in-project repository dependency solution to include a third party jar as a dependency in my Maven project. I'm following the instructions on this blog for that.
Now, I want that when I package my Maven project into a jar, the jar that is created should have a lib folder with the third party jar in it. However, I do NOT want the other dependencies to be packaged in the jar. (I don't want a fat jar with ALL dependencies packaged inside it, I just want a jar with the one third party dependency jar packaged inside it).
I have been trying to play around with the maven-dependency-plugin and the maven-jar-plugin, but I've not been able to achieve what I want.
Can someone please help me out?
You can use maven-dependency-plugin (look here) as shown below, this plugin will provide lots of options to include jars which ArtifactId (i.e., <includeArtifactIds>) or groupId (<includeGroupIds>), etc...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/
classes/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<includeArtifactIds>YOUR_THIRDPARTY_JAR_NAME</includeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>
So, the above code will add YOUR_THIRDPARTY_JAR_NAME.jar into your final .jar file's lib folder.
Take a look at Maven Assembly Plugin. It allows filtering included dependencie, so you can choose what deps to include in the assembly

How to create runnable jar with dependencies in extra folder on mutimodule project?

I have a common library that is shared among different project. As the library is constantly extended (at least for now), it should just be picked up from eclipse workspace during build.
I'm trying to use the maven-dependency-plugin to copy all dependencies in a /lib folder next to the runnable jar. But it does not work:
<dependencies>
<!-- A jar that is opened as project in workspace, not installed into maven repo, and not a submodule. It should just be picked up and added as jar during package. -->
<dependency>
<groupId>my.domain</groupId>
<artifactId>project-commons</artifactId>
</dependency>
</dependencies>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/</outputDirectory>
<overWriteReleases>true</overWriteReleases>
</configuration>
</execution>
</executions>
</plugin>
[ERROR] Failed to execute goal
org.apache.maven.plugins:maven-dependency-plugin:2.8:copy-dependencies
(copy-dependencies) on project mydomain: Artifact has not been
packaged yet. When used on reactor artifact, copy should be executed
after packaging: see MDEP-187. -> [Help 1]
The error ocures when maven tries to copy the commons project that is open in the workspace. Did I miss anything?
I ran into this problem myself today, downloading the latest version of CTAKES (3.2) that integrates YTEX which would build on the command line but not in Eclipse. The error is a result of apparently a known issue with the plugin (https://jira.codehaus.org/browse/MDEP-187).
I eventually fixed it (and I think this will fix your problem) by changing the phase from package to prepare-package.
package
to
prepare-package
Try that and see if it works for you.

Trouble running exec-maven-plugin in a multi-module Maven project

I have a multi-module Maven project with a master pom and numerous sub-directories each containing projects (and pom.xml files) which refer to the master pom.
In projectA contains an invocation of exec-maven-plugin, which executes the java goal and successfully invokes a test class that resides somewhere in projectA (in projectA/test/com/mycompany/Testclass.java). The plugin is declared as follows:
org.codehaus.mojo
exec-maven-plugin
1.2.1
<execution>
<id>execute-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.mycompany.Testclass</mainClass>
<classpathScope>test</classpathScope>
</configuration>
</execution>
</executions>
</plugin>
I execute maven with the following command, and it works fine:
mvn verify -P <profile name> -pl projectA -am
I have a second project, projectB, which depends on projectA. I have configured an exec-maven-plugin section in projectB's pom.xml file that is identical to the one above. When I run maven with the same command as above (except with projectB in the -pl parameter), I get the exception java.lang.ClassNotFoundException: com.mycompany.Testclass.
Clearly this is happening because the classpath when I run maven for projectB does not include the directories in projectA, even though the pom.xml has a dependency on projectA (actually it depends on projectA.1, which in turn depends on projectA).
I have tried switching to use the exec goal rather than the java goal, in projectB, and then providing a classpath in the arguments, like this:
<execution>
<id>execute-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<argument>"../projectA/target/projectA-6.6.1-bSOURCE-tests.jar;../projectA/target/projectA-6.6.1-bSOURCE.jar"</argument>
<argument>com.mycompany.Testclass</argument>
</arguments>
<classpathScope>test</classpathScope>
</configuration>
</execution>
When I've done that I successfully load the class, but get a ClassNotFoundException on com.google.gson.JsonSyntaxException
That happens to be the same error I get if I run the class from the command line, as follows
java -classpath "projectA/target/projectA-6.6.1-bSOURCE-tests.jar;projectA/target/projectA-6.6.1-bSOURCE.jar" com.mycompany.Testclass
In projectB I think I want to use the java goal of the exec-maven-plugin rather than the exec goal, but one way or the other I have to be able to specify the classpath.
Any ideas how I can do that?
Thanks.
I figured this out myself, and am posting my answer in case anybody else needs it, or in case anybody wants to dispute it (or suggest something better).
What I did was add a dependency in the subordinate project, projectB, as follows:
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>projectA</artifactId>
<version>6.6-SNAPSHOT</version>
<scope>test</scope>
<classifier>tests</classifier>
</dependency>
I believe the clincher was the element, which directed maven to get the dependent classes from the jar file containing the test classes in projectA.

Is it best to Mavenize your project jar files or put them in WEB-INF/lib?

I've been doing this for all of the jar files that my Spring MVC project needs:
call mvn install:install-file -DgroupId=vegetables -DartifactId=potatoes -Dversion=1.0 -Dfile=vegetables-1.0.jar -Dpackaging=jar -DgeneratePom=true
Recently I must have exceeded some limit on how many dependencies you can list in your pom.xml file because I got an error that said:
Your command line is too long
So I removed some dependencies from the pom.xml that my project no longer uses and I was able to run the project with maven again.
My question is, should I put install all jar files into my Maven repository as I have been doing so far? Or should I put some of them into the WEB-INF/lib directory?
What's the best practice here?
I've been doing the same that you do with the command line, but by configuring maven-install-plugin in my POM (please read the note at the end):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-vegetables</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/vegetables-1.0.jar</file>
<groupId>vegetables</groupId>
<artifactId>potatoes</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
<execution>
<id>install-minerals</id>
<phase>initialize</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.basedir}/lib/minerals-1.0.jar</file>
<groupId>minerals</groupId>
<artifactId>rocks</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
It is much less efficient, because files get installed over and over, but it is much less annoying than making it manually. Anyway, I think you should give it a try.
All your dependencies should reside under the local repository. According to the Maven convention/best practices, you should not keep jar files in your project.
Convert your project to a fully war based Maven project. This will place all your dependencies (jar files) under your webapp's WEB-INF/lib directory. Thus you will not have to worry about long paths.
You just need to add the dependencies in your pom.xml file, no need to install them manually. Maven will download the libraries and put it in your local repository whenever needed. Only if you want to use third party(custom) libraries, you may go for installing it in your local repository.

Specify non-compile dependencies in Maven and package them as resources

I need to build a jar file that includes (other, external projects') Maven artefacts.
The artefacts are to be included just like stuff in src/main/resources, without any processing. Even though they happen to be jar files themselves, they are not compile time dependencies for my code and should not be added to the classpath, at neither the compile, the test, or the runtime stages.
I can get this done by downloading the files and placing them into src/main/resources, but I would rather have them resolved using the Maven repository.
Here's an example of what you can add to your pom-- it'll copy the artifact with the specified ID from the specified project into the location you specify.
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>id.of.the.project.group.to.include</groupId>
<artifactId>id-of-the-project's-artifact-to-include</artifactId>
<version>${pom.version}</version>
</artifactItem>
</artifactItems>
<includeArtifactIds>id-of-the-project's-artifact-to-include</includeArtifactIds>
<outputDirectory>${project.build.directory}/etc-whatever-you-want-to-store-the-dependencies</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
You could use the dependency plugin to download and put your required artefacts into the target/classes directory during the process-resources phase.
See the example usage for copying artefacts
Since you say you want to end up with a jar, the assembly plugin with a custom assembly descriptor would probably solve this.
Add a <dependencySet> and specify the <unpack> option to ensure those external artifacts get flattened out inside your jar.

Categories