Does Maven remember its state so I can easily rerun last command? - java

I am using Maven multi module project. When I run maven and one of the modules fails I get the error messages and then the following line
After correcting the problems, you can resume the build with the command
mvn <goals> -rf :my.module.name
Does Maven hold any state? Is it possible to run
mvn <goal> `start from where we left off`
The reason I ask is that some of my module names are quite long. I can copy from the cmd prompt but I'd just like a quicker / shorter command. Often saving a couple of seconds may not seem much but over the course of my maven usage it could save me a lot.
The question is
does maven hold state?
if so can I quickly rerun from where I left off?
Thanks

You can use Maven Shell to execute maven goals/phases in a pre-loaded shell environment, significantly reducing the build time.

No, but you could go into the individual modules and build them - this is in essence what maven does, you just need to go through them in the correct order otherwise you might get confusing results (i.e old dependent-module builds etc). The reactor build summary shows you the module build order that maven will run through and is displayed at the start of the build.
In the end though you will always need to do a full build from the parent module in order to build your final artifact. And it's often easiest just to run from the top anyway.

No - at least in my experience, Maven does not hold its state. This is especially important if you are running mvn package. Whereas running mvn package on a multi-module project will work fine (all modules will be able to use the produced artifact of a previous module), if the build is interrupted, resuming from your build mid-way will cause artifact not found errors when referring to previously successfully built modules.
Two ways around this. Rebuild everything, or use mvn install to require maven to install to your local repo (if you are not ready to deploy). In such a case, resuming your build will not fail as it will find the previously built modules in your local repo.
Just as a personal pet peeve, you need to know the module artifact name when using the -rf flag. Maven will show you the display name, which may or may not be the artifact name. -rf requires the artifact name.

Related

Is it possible to run sonar analysis on all children but NOT parent of a multimodule Maven project?

I'm curious if it's possible to build and analyze the submodules of my multi-module maven project with a single command.
For the time being I have a single maven project with 3 separate services underneath it. Think of it like a small-scale monorepo.
Currently when I build them I can run a single mvn clean install from the top-most project and get a full build of everything with distinct JaCoCo analysis of all 3 services. In other maven projects where I already only have a single service I can simply run mvn clean install sonar:sonar but when I run it in my multi-module project it only executes at the top most level and analyses all 3 services as a single project in Sonar/SonarQube.
This answer seems to indicate it's impossible to do the same thing for a multi-module build with a single command but it's also a very old answer and things may have changed since then but with codehaus shutdown I don't think I can find that jira issue easily.
Also trying to implement the answer to that question using pluginManagement and enabling/disabling skip in parent/child modules doesn't seem to be working since sonar sees the parent as being skipped and then skips all children. It may work for exec but sonar seems to aggregate/iterate submodules differently.
The next obvious solution indicated by these questions, and to a degree the Sonar documentation itself since the deprecation of sonar.includeModules/sonar.excludeModules in 4.3 is to use Maven's advanced reactor options however that doesn't work for skipping the parent project. Trying to run mvn sonar:sonar -pl one,two,three, or the opposite mvn sonar:sonar -pl !. throws the error:
Maven session does not declare a top level project
Maven does seem to constrain itself to the correct list of modules but sonar itself seems incompatible with the approach and throws the error at the first module.
So now the answer seems to be that I need to run mvn sonar:sonar individually once per module in each module's directory, which is just a bit obnoxious.

Maven: Finding out if tests passed or failed after using maven.test.failure.ignore=true

I'm trying to run a complete Maven build of multiple projects for an automated build tool. If unit tests fail, but the project itself builds correctly, I want to be able to continue the build and detect this after the build completes. I tried doing this:
mvn clean package -Dmaven.test.failure.ignore=true -Dmaven.test.error.ignore=true -Dmaven.test.reportsDirectory=/Users/bfraser/misc/reports
The "maven.test.failure.ignore" and "maven.test.error.ignore" properties work fine. However, surefire seems to ignore the "maven.test.reportsDirectory" completely (in fact, if you look at the documentation for the test goal, the reportsDirectory property is not documented to be tied to the system variable). This may be because I'm building a multi-module project? All reports seem to go in the target/ folder of the subprojects.
It is very difficult for me to be able to edit the POMs in an automated way since many of them have parent POMs that might be on a Nexus repo somewhere, etc. -- I need to be able to do this externally to the project (preferable via command line switches, but if I need to create some files so be it... as long as I don't have to edit the project POM it's all good).
I just need to know if any test failed. I'm not particularly fussy about what/how many tests failed.

Using cached artifacts in Maven to avoid redundant builds?

I have a Maven 3 multi-module project (~50 modules) which is stored in Git. Multiple developers are working on this code and building it, and we also have automated build machines that run cold builds on every push.
Most individual changelogs alter code in a fairly small number of modules, so it's a waste of time to rebuild the entire source tree with every change. However, I still want the final result of running the parent project build to be the same as if it had built the entire codebase. And I don't want to start manually versioning modules, as this would become a nightmare of criss-crossing version updates.
What I would like to do is add a plugin which intercepts some step in build or install, and takes a hash of the module contents (ideally pulled from Git), then looks in a shared binary repository for an artifact stored under that hash. If one is found, it uses that artifact and doesn't even execute the full build. If it finds nothing in the cache it performs the build as normal, then stores its artifact in the cache. It would also be good to rebuild any modules which have dependencies (direct or transient) which themselves had a cache miss.
Is there anything out there which does anything like this already? If not, what would be the cleanest way to go about adding it to Maven? It seems like plugins might be able to accomplish it, but for a couple pieces I'm having trouble finding the right way to attach to Maven. Specifically:
How can you intercept the "install" goal to check the cache, and only invoke the module's 'native' install goal on a cache miss?
How should a plugin pass state from one module to another regarding which cache misses have occurred in order to force rebuilds of dependencies with changes?
I'm also open to completely different ways to achieve the same end result (fewer redundant builds) although the more drastic the solution the less value it has for me in the near term.
I have previously implemented a more complicated solution with artifact version manipulation and deployment to private Maven repository. However, I think this will fit your needs better and is somewhat more simple:
Split your build into multiple builds (e.g., with a single build per module using maven -pl argument).
Setup parent-child relationships between these builds. (Bamboo even has additional support for figuring out Maven dependencies, but I'm not sure how it works.)
Configure Maven settings.xml to use a different local repository location - specify a new directory inside your build working directory. See docs: https://maven.apache.org/guides/mini/guide-configuring-maven.html
Use mvn install goal to ensure newly built artifacts are added to local repository
Use Bamboo artifact sharing to expose built artifacts from local repository - you should probably filter this to include only the package(s) you're interested in
Set dependent builds to download all artifacts from parent builds and put them into proper subdirectory of local repository (which is customized to be in working directory)
This should even work for feature branch builds thanks to the way Bamboo handles parent-child relations for branch builds.
Note that this implies that Maven will redownload all other dependencies, so you should use a proxy private Maven repository on local network, such as Artifactory or Nexus.
If you want, I can also describe the more complicated scenario I've already implemented that involves modifying artifact versions and deploying to private Maven repository.
The Jenkins plugin allows you to manage/minimize dependent builds
whenever a SNAPSHOT dependency is built (determined by Maven)
after other projects are built (manually via Jenkins jobs)
And if you do a 'mvn deploy' to save the build into your corporate Maven repo then you don't have to worry about dependencies when builds run on slave Jenkins machines. The result is that no module is ever built unless it or one of its dependencies has changed.
Hopefully you can apply these principles to a solution with Bamboo.

Deploying a maven sub-module to a repository for other projects to use (without parent)

The problem is, in our company we have a project with multiple sub-modules, however one of the sub-modules is just a collection of API declarations and is meant for other (3rd praty) projects to use. I want to keep it as a sub-module because is easier to maintain and build (dependency and property inheritance). Other sub-modules in this project are also dependant on it.
The question I have is, if there exist a good practice or a nice way to execute a deploy phase that will upload just this sub-module to a different repository (can be duplicated too) without it having a dependency to parent pom.
What I have already tried:
I have already checked the deploy:deploy-file, but the problem is when it comes to SNAPSHOT builds. We wish to be able to publish SNAPSHOTS and release builds, and snapshots have different repository than release ones, but deploy-file goal can only have one url parameter. I do not wish to use different profile for snapshot deploy. Than I tried to use maven build-helper and its regex-property to be able to change the repository url if the version is a SNAPSHOT, but was unable to do so because of the plugin and regex limitations.
The last option is I can make a plugin for this, but I wish to know if there is a more elegant way to solve this the "maven way".
You can deploy this module separately but only for SNAPSHOT's for a release it does not make sense. The deployment of a module can be done via:
mvn -pl TheModuleYouWouldLikeToDeploy deploy
may be you need to add the option -am (also make dependencies) like:
mvn -am -pl TheModuleYouWouldLikeToDeploy deploy
Apart from that your approach sounds wrong cause if you are using a multi-module build why not deploying the whole build via mvn deploy ? May be it would be better to let do the job via a CI tool like Jenkins.

could the first ever maven build be made offline?

The problem: you have a zipped java project distribution, which depends on several libraries like spring-core, spring-context, jacskon, testng and slf4j. The task is to make the thing buildable offline. It's okay to create project-scope local repo with all required library jars.
I've tried to do that. Looks like even as the project contains the jars it requires for javac and runtime, the build would still require internet access. Maven would still lurk into network to fetch most of its own plugins it requires for the build. I assume that maven is run with empty .m2 directory (as this may be the first launch of the build, which may be an offline build). No, I am not okay with distributing full maven repo snapshot along the project itself, as this looks like an utter mess for me.
A bit of backround: the broader task is to create windows portable-style JDK/IntelliJ Idea distribution which goes along the project and allows for some minimal java coding/running inside IDE with minimal configuration and minimal internet access. The project is targeted towards students in a computer class, with little or no control over system configuration. It is desirable to keep console build system intact for the offline mode, but I guess that maven is overly dependent on the network, so I have to ditch it in favor of good old ant.
So, what's your opinion, could we move first maven build in offline mode completely? My gut feeling is that initial maven distribution just contains the bare minimum required to pull essential plugins off the main repo and is not fully functional without seeing the main repo at least once.
Maven has a '-o' switch which allows you to build offline:
-o,--offline Work offline
Of course, you will need to have your dependencies already cached into your $HOME/.m2/repository for this to build without errors. You can load the dependencies with:
mvn dependency:go-offline
I tried this process and it doesn't seem to fully work. I did a:
rm -rf $HOME/.m2/repository
mvn dependency:go-offline # lot of stuff downloaded
# unplugged my network
# develop stuff
mvn install # errors from missing plugins
What did work however is:
rm -rf $HOME/.m2/repository
mvn install # while still online
# unplugged my network
# develop stuff
mvn install
You could run maven dependency:go-offline on a brand new .m2 repo for the concerned project. This should download everything that maven needs to be able to run offline. If these are then put into a project-scope local repo, you should be able to achieve what you want. I haven't tried this though
Specify a local repository location, either within settings.xml file with <localRepository>...</localRepository> or by running mvn with -Dmaven.repo.local=... parameter.
After initial project build, all necessary artifacts should be cached locally, and you can reference this repository location the same ways, while running other Maven builds in offline mode (mvn -o ...).

Categories