Maven overlays and Eclipse - java

I have 2 Maven web projects A and B. B contains some common parts and A depends on B.
In A's pom.xml I have:
<dependencies>
<dependency>
<groupId>com.mygroup</groupId>
<artifactId>B</artifactId>
<version>1.0-SNAPSHOT</version>
<type>war</type>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
</plugin>
</plugins>
</build>
I have 2 problems:
When making some changes in B, if I run a maven build on A I don't see the changes in the resulting exploded archive.
Trying to deploy A from Eclipse does not work - the contents of B are not included in the resulting war/exploded archive.
Thanks for your help.

Well, if you changes stuff in B, you have to re-install it into your local maven repo (mvn install) for other local projects that have it as dependency to receive the latest modifications.
When building a maven project it's best if you build it using Maven (like with commands such as mvn package) and not using some other building tool (such as Eclipse). If you wanna build it a la Maven but from the comfort of your Eclipse GUI, you can istall m2_eclipse plugin from :
http://m2eclipse.sonatype.org/installing-m2eclipse.html
which integrates Maven with Eclipse. Then, when you rigth click on your project in Eclipse, under the "Run..." options you'll have the one that allows your to Maven build it, redirecting all console output to the Eclipse console window.
And as a final note, in a setup such as the one aboce, ideally you'd create a parent Maven project (packaged as "pom") which has as child projects B and A (in that order). This way if you've modified stuff in both projects and you want everything to be build with the latest modifs, you can just do a maven install on the parent pom and Maven will take care of everything.

Amplifying #AndreiBodnarescu's point, you may not be seeing the changes you made to project-B when you build project-A because the changes aren't available in the Maven repository.
If project-B is being built on the same machine can you ensure that you used mvn install to install to your local repository? If project-B is being derived from a build on a different machine then use mvn deploy to deploy project-B to a common shared repository. In this case you may still not pick up project-B if you aren't using SNAPSHOTted versioning or you don't increment project-B's version number.
I see that B is of type war. What is the packaging of A? Is it an EAR? If so using the maven-war-plugin with project-A is not going to be of help.

Related

maven: execute without actually building anything

I have a project with finalised version in pom files , lets say 12.3.45 .
I have built the code for this version some time ago already, all the built jars are in the local maven repo.
Then at some point I have run mvn clean, so all the target folders are being removed.
And now I want to execute some code, as quickly as possible, using mvn exec:java. Preferably without building anything, because why not? all the jars at some point were already built, and I know there were no code changes after that. How can I force maven to execute the code as fast as possible , not recompile anything, and just reuse the jars from the local repo?
Thanks.
If your artifacts are in a local or remote repository you can use them as dependencies.
You can use exec-maven-plugin's options includeProjectDependencies or includePluginDependencies to use them in java execution
https://www.mojohaus.org/exec-maven-plugin/java-mojo.html#includePluginDependencies. includeProjectDependencies option is enabled (true) by default.
You can execute exec-maven-plugin without building anything with mvn exec:java command
Instructions:
To run exec-maven-plugin you would need a main class to run. I assume you have one in your project. If you don't - you need to make a separate project with a main class.
Create a blank maven project.
In the project add exec-maven-plugin configuration. Set the mainClass
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>pack.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>
Include you artifacts as dependencies to the project
<dependencies>
<dependency>
<groupId>my.group</groupId>
<artifactId>myartifact</artifactId>
<version>12.3.45</version>
</dependency>
</dependencies>
Run mvn exec:java to execute com.my.package.MyMainClass main class from my.group.myartifact artifact
Edits:
includeProjectDependencies option is enabled (true) by default

not importing class from name-sources.jar

I have created a maven war project, and want to call it from another module (war). When I searched found that name-sources.jar file is used as dependency to another module. I am adding dependency of name-sources but import is not working.
name-SNAPSHOT.war
name-SNAPSHOT-sources.jar
are the files generated on building of maven project.
Below is the dependency added into another module.
<dependency>
<groupId>uniqueid</groupId>
<artifactId>name</artifactId>
<version>8.9-SNAPSHOT</version>
<classifier>sources</classifier>
<scope>system</scope>
<systemPath>{Path}/name-8.9-SNAPSHOT-sources.jar</systemPath>
</dependency>
Any help is highly appreciated.
I understand this: you have 2 web projects A and B, both with maven packaging = war. In A, there are classes you want to use in B.
Forget about adding a *-sources.jar as dependency.
So, do this:
generate a new maven project C as a library with project packaging "jar"
Move the classes you want to share from A to C
Install this artifact C in your local maven repository (mvn install)
Then, add a dependency to C in the pom.xmls of A and B:
<dependency>
<groupId>your.group</groupId>
<artifactId>yourLibrary</artifactId>
<version>0.1.0-SNAPSHOT</version>
<scope>compile</compile> <!-- this is default, so this line is optional-->
</dependency>
Created *-classes.jar file. Use below code under pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
And added this new jar as dependency wherever want to use.
<dependency>
<groupId>com.honeywell.dras.sensibo</groupId>
<artifactId>sensibo-client</artifactId>
<version>{*}</version>
<classifier>classes</classifier>
</dependency>
So advantage with this is we can generate both war and jar files and make use of both based on need.

Increment version in every Jenkin's build and update dependencies

I have a number of Maven projects being built my Jenkins server. These projects have dependencies on each other, e.g.
service-base -> java-base -> pom-base
In other words, the Maven project service-base depends on the Maven project java-base. Naturally, my POM files look like this:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>my.com</groupId>
<artifactId>service-base</artifactId>
<dependencies>
<dependency>
<groupId>my.com</groupId>
<artifactId>java-base</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
The issue is that none of my Maven projects have "releases" per-se, since I'm using continuous integration to release my changes. Currently, I allow artifact overwriting in my Maven repo and keep all of my versions at 1.0.0. This is because I release my packages many times a day and changing the versions in all the POM files each time I submit a new package version.
Ideally, what I would like is for Jenkins to generate a new version, e.g. 1.0.{BUILD_NUMBER} and then for it update the dependencies all the way up the dependency tree.
Question: Is this possible? Or does anyone have any other solutions to versioning?
Here is how I achieved the same, using Maven profiles, Maven classifiers and Jenkins parametrized builds.
You can define a jenkins profile (or whatever name you prefer) in the pom of the concerned projects. This profile will not be active by default, so your local builds will keep on working as usual. However, this profile will be activated on the Jenkins builds (via the -Pjenkins option on the Maven execution).
How this profile look like in the project at the top of the hierarchy:
<profiles>
<profile>
<id>jenkins</id>
<properties>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>${project.packaging}</packaging>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>generate-default-version</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>${BUILD_NUMBER}</classifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>install-default-version</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}/${project.build.finalName}-${BUILD_NUMBER}.${project.packaging}</file>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
What is the profile doing?
We are using the Maven Jar Plugin to generate on the package phase yet another artefact for the same project, so the project will create the normal jar plus another jar having as classifier the BUILD_NUMBER (i.e. myproject-1.0.jar and myproject-1.0-4567.jar)
We are also using the Maven Install Plugin to install the additional artefact (the myproject-1.0-4567.jar) into the local Maven cache (so it will be visible to other dependent projects)
We need to define some properties for the Install Plugin, otherwise the install-file will not work
Hence, when on your Jenkins build you will execute the following:
mvn clean install -Pjenkins -DBUILD_NUMBER=${BUILD_NUMBER}
Jenkins will actually pass its BUILD_NUMBER to Maven, which will use it as defined in the jenkins profile and create (and install) an additional artefact for us using it as classifier.
Fine, now we have a dynamically created artefact using the Jenkins build number and available for other projects/builds.
But how other projects can use it?
We define in the dependent projects another profile (or again called jenkins for coherency) and re-define the dependency we now need at runtime:
<profiles>
<profile>
<id>jenkins</id>
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>test</artifactId>
<version>1.1.0</version>
<classifier>${BUILD_NUMBER}</classifier>
</dependency>
</dependencies>
</profile>
</profiles>
Note: we are actually overriding as part of the profile a dependency and saying we want that specific classifier for it. Which classifier? The BUILD_NUMBER classifier, which will be available in the local Maven cache of the Jenkins server because installed by the previous build.
But how can the dependent build know which build number and as such which classifier to use, dynamically?
Using Jenkins parametrized builds and the Jenkins Parametrized Trigger plugin.
So, to summarize:
Provider project defines the profile to create additional classifier
Consumer project defines the profile to use as dependency a specific classifier
If a project is Provider for others and Consumer of others, it can then merge the two approaches above in the same profile
The first Jenkins build activates this specific profile and pass to Maven its build number
The downstream Jenkins builds are triggered by the first, which is passing them its build number via the Parametrized Plugin
Each downstream build would then resolve the classifier specified by the parameter and, if required, also create yet another classifier for its own build (according to its profile)
Using this approach, you local builds will keep on working as usual and no classifier would be used, while Jenkins builds would use an additional classifier used across them.

How can I change libraries?

How can I change libraries on Eclipse with Maven builder?
When I change my JRE library by the project properties and then rebuild a project JRE returns to previous version.
How can I add a new library?
A library is just a dependency. You can add dependencies to you pom-file:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
</dependency>
This add the junit-library.
When I change my JRE library by the project properties and then rebuild a project JRE returns to previous version.
This is the case with m2eclipse/m2e, as the Eclipse plugin will revert any changes made to the project properties. In most cases, you're better off specifying the version of the source code, and the target version of the bytecode, via the maven-compiler-plugin configuration:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin<artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
M2Eclipse/M2E uses these values in the project POM to determine the Java runtime to use for building the project. Considering that it never makes sense (or is impossible) to have multiple Java runtimes for an Eclipse project, you ought to specify the source and target values for the project, either in the project POM or in a parent POM.
If you are using Maven, then you control all your dependencies via the pom.xml file. You can either use the maven eclipse plugin to generate the eclipse artifacts, or my preferred approach which is to use the m2eclipse plugin. This plugin makes it easy to keep maven and the eclipse workspace in sync.

Maven: best way of linking custom external JAR to my project?

It's my first couple of days learning Maven and I'm still struggling with the basics. I have an external .jar file (not available in the public repos) that I need to reference in my project and I'm trying to figure out what my best option is.
It's a small scale project without a central repository for libraries, so it has to be either a local repository (somehow added to source control, don't know if it's supposed to work that way?) or the .jar needs to be stored on disk outside of any formal repository.
1) What's my best option for adding the .jar file to my project's references with maven given that I want both the project and the library to be in source control?
2) I still can't seem to have Eclipse see the dependency. I manually added it to the section of the pom, and it shows up fine in the Dependencies list in m2eclipse. mvn compile and mvn package both succeed, but running the program results in:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
LibraryStuff cannot be resolved to a type
This is after editing the POM as:
<dependency>
<groupId>stuff</groupId>
<artifactId>library</artifactId>
<version>1.0</version>
<systemPath>${lib.location}/MyLibrary.jar</systemPath>
<scope>system</scope>
</dependency>
Should I be executing mvn install:install-file even thought I already have the pom.xml edited as above?
Thanks!
You can create an In Project Repository, so you don't have to run mvn install:install-file every time you work on a new computer
<repository>
<id>in-project</id>
<name>In Project Repo</name>
<url>file://${project.basedir}/libs</url>
</repository>
<dependency>
<groupId>dropbox</groupId>
<artifactId>dropbox-sdk</artifactId>
<version>1.3.1</version>
</dependency>
/groupId/artifactId/version/artifactId-verion.jar
detail read this blog post
https://web.archive.org/web/20121026021311/charlie.cu.cc/2012/06/how-add-external-libraries-maven
I think you should use mvn install:install-file to populate your local repository with the library jars then you should change the scope from system to compile.
If you are starting with maven I suggest to use maven directly not IDE plugins as it adds an extra layer of complexity.
As for the error, do you put the required jars on your classpath? If you are using types from the library, you need to have access to it in the runtime as well. This has nothing to do with maven itself.
I don't understand why you want to put the library to source control - it is for sources code not binary jars.
This can be easily achieved by using the <scope> element nested inside <dependency> element.
For example:
<dependencies>
<dependency>
<groupId>ldapjdk</groupId>
<artifactId>ldapjdk</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${basedir}\src\lib\ldapjdk.jar</systemPath>
</dependency>
</dependencies>
Reference: http://www.tutorialspoint.com/maven/maven_external_dependencies.htm
The Maven manual says to do this:
mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
update We have since just installed our own Nexus server, much easier and cleaner.
At our company we had some jars that we some jars that were common but were not hosted in any maven repositories, nor did we want to have them in local storage.
We created a very simple mvn (public) repo on Github (but you can host it on any server or locally):
note that this is only ideal for managing a few rarely chaning jar files
Create repo on GitHub:
https://github.com/<user_name>/mvn-repo/
Add Repository in pom.xml
(Make note that the full path raw file will be a bit different than the repo name)
<repository>
<id>project-common</id>
<name>Project Common</name>
<url>https://github.com/<user_name>/mvn-repo/raw/master/</url>
</repository>
Add dependency to host (Github or private server)
a. All you need to know is that files are stored in the pattern mentioned by #glitch
/groupId/artifactId/version/artifactId-version.jar
b. On your host create the folders to match this pattern.
i.e if you have a jar file named service-sdk-0.0.1.jar, create the folder service-sdk/service-sdk/0.0.1/ and place the jar file service-sdk-0.0.1.jar into it.
c. Test it by trying to download the jar from a browser (in our case: https://github.com/<user_name>/mvn-repo/raw/master/service-sdk/service-sdk/0.0.1/service-sdk-0.0.1.jar
Add dependency to your pom.xml file:
<dependency>
<groupId>service-sdk</groupId>
<artifactId>service-sdk</artifactId>
<version>0.0.1</version>
</dependency>
Enjoy
Don't use systemPath. Contrary to what people have said here, you can put an external jar in a folder under your checked-out project directory and haven Maven find it like other dependencies. Here are two crucial steps:
Use "mvn install:install-file" with -DlocalRepositoryPath.
Configure a repository to point to that path in your POM.
It is fairly straightforward and you can find a step-by-step example here:
http://randomizedsort.blogspot.com/2011/10/configuring-maven-to-use-local-library.html
If you meet the same problem and you are using spring-boot v1.4+, you can do it in this way.
There is an includeSystemScope that you can use to add system-scope dependencies to the jar.
e.g.
I'm using oracle driver into my project.
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.3.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/extra-jars/ojdbc14-10.2.0.3.0.jar</systemPath>
</dependency>
then make includeSystemScope=true to include the jar into path /BOOT-INF/lib/**
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
and exclude from resource to avoid duplicated include, the jar is fat enought~
<build>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.jar</exclude>
</excludes>
</resource>
</resources>
</build>
Good luck!
Maven way to add non maven jars to maven project
Maven Project and non maven jars
Add the maven install plugins in your build section
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>${version.maven-install-plugin}</version>
<executions>
<execution>
<id>install-external-non-maven1-jar</id>
<phase>clean</phase>
<configuration>
<repositoryLayout>default</repositoryLayout>
<groupId>jar1.group</groupId>
<artifactId>non-maven1</artifactId>
<version>${version.non-maven1}</version>
<file>${project.basedir}/libs/non-maven1.jar</file>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
<execution>
<id>install-external-non-maven2-jar</id>
<phase>clean</phase>
<configuration>
<repositoryLayout>default</repositoryLayout>
<groupId>jar2.group</groupId>
<artifactId>non-maven2</artifactId>
<version>${version.non-maven2}</version>
<file>${project.basedir}/libs/non-maven2.jar</file>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
<execution>
<id>install-external-non-maven3-jar</id>
<phase>clean</phase>
<configuration>
<repositoryLayout>default</repositoryLayout>
<groupId>jar3.group</groupId>
<artifactId>non-maven3</artifactId>
<version>${version.non-maven3}</version>
<file>${project.basedir}/libs/non-maven3.jar</file>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
<goals>
<goal>install-file</goal>
</goals>
</execution>
</executions>
</plugin>
Add the dependency
<dependencies>
<dependency>
<groupId>jar1.group</groupId>
<artifactId>non-maven1</artifactId>
<version>${version.non-maven1}</version>
</dependency>
<dependency>
<groupId>jar2.group</groupId>
<artifactId>non-maven2</artifactId>
<version>${version.non-maven2}</version>
</dependency>
<dependency>
<groupId>jar3.group</groupId>
<artifactId>non-maven3</artifactId>
<version>${version.non-maven3}</version>
</dependency>
</dependencies>
References Note I am the owner of the blog
Change your systemPath.
<dependency>
<groupId>stuff</groupId>
<artifactId>library</artifactId>
<version>1.0</version>
<systemPath>${project.basedir}/MyLibrary.jar</systemPath>
<scope>system</scope>
</dependency>
The pom.xml is going to look at your local repository to try and find the dependency that matches your artifact.
Also you shouldn't really be using the system scope or systemPath attributes, these are normally reserved for things that are in the JDK and not the JRE
See this question for how to install maven artifacts.
Note that all of the example that use
<repository>...</respository>
require outer
<repositories>...</repositories>
enclosing tags. It's not clear from some of the examples.
The best solution here is to install a repository: Nexus or Artifactory. If gives you a place to put things like this, and further it speeds things up by caching your stuff from the outside.
If the thing you are dealing with is open source, you might also consider putting in into central.
See the guide.
With Eclipse Oxygen you can do the below things:
Place your libraries in WEB-INF/lib
Project -> Configure Build Path -> Add Library -> Web App Library
Maven will take them when installing the project.
If the external jar is created by a Maven project only then you can copy the entire project on your system and run a
mvn install
in the project directory. This will add the jar into .m2 directory which is local maven repository.
Now you can add the
<dependency>
<groupId>copy-from-the=maven-pom-of-existing-project</groupId>
<artifactId>copy-from-the=maven-pom-of-existing-project</artifactId>
<version>copy-from-the=maven-pom-of-existing-project</version>
</dependency>
This will ensure that you
mvn exec:java
works. If you use suggested here
<scope>system</scope>
Then you will have to add classes individually while using executing through command line.
You can add the external jars by the following command described here
mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> \
-DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging>
The most efficient and cleanest way I have found to deal with this problem is by using Github Packages
Create a simple empty public/private repository on GitHub as per your requirement whether you want your external jar to be publicly hosted or not.
Run below maven command to deploy you external jar in above created github repository
mvn deploy:deploy-file \
-DgroupId= your-group-id \
-DartifactId= your-artifact-id \
-Dversion= 1.0.0 -Dpackaging= jar -Dfile= path-to-file \
-DrepositoryId= id-to-map-on-server-section-of-settings.xml \
-Durl=https://maven.pkg.github.com/github-username/github-reponame-created-in-above-step
Above command will deploy you external jar in GitHub repository mentioned in -Durl=.
You can refer this link on How to deploy dependencies as GitHub Packages GitHub
Package Deployment Tutorial
After that you can add the dependency using groupId,artifactId and version mentioned in above step in maven pom.xml and run mvn install
Maven will fetch the dependency of external jar from GitHub Packages registry and provide in your maven project.
For this to work you will also need to configure you maven's settings.xml to fetch from GitHub Package registry.

Categories

Resources