Maven: packaging & module dependencies - java

I have a maven project that consists of a couple of modules. The main structure and setup is this:
/project/pom.xml: packaging=pom, lists all sub-modules, version: TRUNK-SNAPSHOT
/project/core-module/pom.xml: packaging=jar
/project/war-module/pom.xml: packaging=war, depends on core-module with ${project.version}
I use IntelliJ for development if that somehow matters.
When I now develop/run/debug the war-module and meanwhile I change code in the core-module things get out of hand. The running war-module application (running via jetty:run-exploded) uses the core-module which is "installed" in my local ~/.m2/ repository instead of the current build. It doesen't matter if I do a "rebuild project" in IntelliJ or a mvn clean before running.
My question is: do I have to mvn install each time, can I circumvent the installed packages or do I have to change packaging options?

Making a long story short, the answer is: YES, in a multi-module project you have to run mvn install every time so the dependencies of your war-module get compiled and installed in your local repository.
However, for local testing I usually recommend to make use of the IDE features to test our local changes. With IntelliJ is really easy to configure and it supports a lot of different application servers.
The reason for this is: Imagine working on a large team, using an enterprise shared repository to hold your common dependencies without the need to publish them to Maven central. If any of your colleagues has made changes to core-module, committed them and make them available through your internal shared repo then Maven will download that dependency and then use to run the Jetty plugin.
The good side of this is that you'll be testing with last version of those dependencies, the bad side of it is that the code of those dependencies is not the same as the one in your working copy.

Related

How to discard a local dependency in a maven project?

I have a question about the integration the eclipse and maven.
I have a project A with dependencies in project B which is itself just a container for a bunch of projects B-i.
Project B is imported in Eclipse but most of the B-i are not imported in eclipse. Sometimes, I want to work on a patch in B-n. So I import the B-n project and dependency resolving usually works well, that is, project A uses the project B-n and recompiles.
Problem happens often when I want to discard the local dependency, close the local project, and make sure that the remote B-n from our repository is used by A (let's say that the other team patched project B).
What is the good and proper "way" to do that kind of patching/ensure that A is using the remote/server version of B-n and not the previously compiled local jar ?
Removing the local project ? Removing the dependency in the local project ? Will I always have to "clean install" project A when I do such a change ?
Thanks.
If I understand you correctly, you do the following:
You have a project B-n with a version (say 1.0.0-SNAPSHOT). It is built on some kind of build server.
Then you check it out, built it locally (still with version 1.0.0-SNAPSHOT). Now you want to discard your locally built version and refer again to the 1.0.0-SNAPSHOT from the repository (correct me if you did not understand you correctly).
For that, you can purge the local repository by dependency:purge-local-repository. You can start this from Eclipse through "Run As -> Maven Build...". See also
https://maven.apache.org/plugins/maven-dependency-plugin/examples/purging-local-repository.html

IntelliJ with one Maven project depending on another Maven project: How to be efficient?

My team is regularly facing inconveniences when running a Maven project that depends on other Maven projects which were modified but not reinstalled to the local repository.
For the sake of simplification, let's say I have two Maven projects Business and Web. My Web project has in its dependencies the Business project, and a Jetty plugin which allows me to run a local web server for development.
In IntelliJ, both projects are opened on the same window using Maven Add project, so that I can navigate through the code easily between the two projects.
Currently, I have set up a Run Configuration in IntelliJ so that mvn clean install -DskipTests will run on the Business project, and then mvn clean jetty:run on Web. This allows me to run Web with the latest modifications made in Business. If I don't run clean install on the Business project, then Web will run on an older version of the source code of Business. In addition this will mess up the IntelliJ debugger as the source code being debugged will not match the runtime class.
In a real application, a Dependency Injection Bootstrap project may depend on Web, Business, Some Database Adapter X, Some Database Adapter Y, Some API Client Adapter... therefore the clean install may become costly. In addition it is easy to forget to build the dependee project, which is the reason why the Maven goals are always run before running Jetty.
Is there a way to be more efficient during development, so that a modification on a dependee project will be active when running the dependant projects without having to run any/many Maven goals?
Create a tiny parent project pom.xml which references both Business and Web as modules. Then tell Intellj to open the parent project - this will let Web access Business (if properly referenced) without having to install the artifacts locally.

Quickest POM settings to turn an existing Eclipse web project in a Maven-managed project?

I'm converting an existing Eclipse-based web project to a Maven-managed one.
Since the project has lots of dependencies, many of which are custom (they're either internally made or they've been taken from sources that have no public repository), is there some 'magic' Maven POM setting that will let me load every jar from WebContent/WEB-INF/lib and make the project work as before right now, so that I can configure each dependency and do the necessary refactoring to turn it to a proper Maven project with a little more time and care?
I have already seen this question, but the project must continue to compile inside Eclipse, so - or at least I guess - it is not just a matter of using the Maven war plugin
What you want to do is called "installing" your non-mavenized JARs into your maven repository. This can be a local or remote repo that you host.
The command to install to your local repo is something like this: mvn install:install-file -Dfile=My-lib.jar -DgroupId=com.mycompany -DartifactId=My-lib -Dversion=1.2.3 -Dpackaging=jar
You'll want to review the various options for install to suit your project.
Once the non-mavenized dependencies are installed to your repo you can add them to your pom like any other maven dependency. They will be fetched from your local repo.
You will have to set up your own remote repo (like Artifactory) or install each plugin for every developer and CI server in your environment for others on your team to build the project. I strongly reccomend Artifactory, it makes it easy on your and your team to use maven and get dependencies.

Eclipse and maven dependency during development

I do have own developed Java library (MyLib), which I later publish on private Maven repository and have it as Maven dependency in another webapp project (MyWebapp). If I have both projects - MyLib and MyWebapp at the same time opened in Eclipse - is there a way somehow to configure MyWebapp so, that local changes made to MyLib would be directly added to MyWebapp while building/deploying it? The issue is that during development it is not really comfortable always to make some changes in MyLib, make a build, deploy to Maven repository and then make a MyWebapp build, deploy it and only then I can see how the changes are affecting the webapp project...
I would like to reduce the overhead while developing and willing to see how changes are working out. Of course when it comes to real releases the above described flow does really make sense and works great.
Thanks!
There is no simple "just tick this option" solution, unfortunately. You can chose between these options:
Convert MyLib into a Maven module and add it to the sources of MyWebapp. This, of course, will make it harder later to reuse the library alone.
Stop deploying the application. If you look at the classpath in Eclipse, m2e should have added the dependency as a project from the workspace (instead of depending on the JAR in the repository). If not: There is an option for this.
The next step is to create another project which depends on Jetty and MyWebapp. Create a Java application in there (i.e. a file with main()) which creates a Jetty server and configure it to use the current classpath. That way, you can start the webapp just like any other Java application without deploying - Jetty will simply load classes from the classpath that m2e assembled.

Releasing from development into production in maven

I'm confused about the use of maven in development and production environments - I'm sure it's something simple that I'm missing. Grateful for any help..
I set up maven inside eclipse on my local machine and wrote some software. I really like how it's made things like including dependent jars very easy.
So that's my development environment. But now I want to release the project to production on a remote server. I've searched the documentation, but I can't figure out how it's supposed to work or what the maven best practice is.. Are you supposed to:
a) Also be running maven on your production environment, and upload all your files to your production environment and rebuild your project there? (Something in me baulks at the idea of rebuilding 'released' code on the production server, so I'm fairly sure this isn't right..)
b) use mvn:package to create your jar file and then copy that up to production? (But then what of all those nice dependencies? Isn't there a danger that your tested code is now going to be running against different versions of the dependent jars in the production environment, possibly breaking your code? Or missing a jar..?)
c) Something else that I'm not figuring out..
Thanks in advance for any help!
You're supposed to have your code under version control (and you never "upload" files to another machine, you "download" them from the Version Control System if required).
You're supposed to package your code in a format (a WAR, an EAR, another kind of bundle) that can be deployed on the production environment for execution. Such bundles typically include the dependencies. To build more complex bundles, the Maven Assembly Plugin can help.
Maven generated artifacts (JARs, WARs, whatever) should be shared via a remote repository (and thus deployed - I mean mvn deploy here - to this remote repository). A remote repository can be a simple file system served via a web server or a more advanced solution like Nexus.
Development is usually done using SNAPSHOT dependencies (e.g. 1.0-SNAPSHOT). At release time, you're supposed to change the version into a "fixed" version (e.g. 1.0) and some other bits from your pom.xml, run the build to check that everything is ok, commit the modified pom.xml, create a tag in the VCS, promote the versions to a new SNAPSHOT (e.g. 1.1-SNAPSHOT) in the pom.xml, commit the new pom.xml in the VCS. The entire process require some work but this can be automated using the Maven Release Plugin.
On the production environment, get the artifacts to be deployed from the remote repository and deploy them (some projects automate the deployment to the production server using Maven but that's another story).
Of course, there are variations around this (deployment to production is most of time company specific) but the general idea is there.
You need to look into the Maven Assembly Plugin and the Maven Release Plugin.
When building artifact you usually state what scope the dependency has. In default scope it should be packaged in your archive. If you do not want it, use scope "provided" - in such case you have to prepare runtime environment providing the dependency. It's generaaly a bad idea to rebuild a package only for deployment.
As for deploying, you can use maven's antrun plugin to copy files locally or via scp .

Categories

Resources