could the first ever maven build be made offline? - java

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 ...).

Related

Is it possible to package a portable maven in the project (and some general direction on how)?

The solution which needs bootstrapping is supplied as java code. Absolutely sure that this is necessary.
Receivers of the solution are guaranteed to have a suitable JDK
However, receivers of the solution are unable to install Maven (they don't know how to and cannot be taught)
My idea is to include some sort of Maven with the project, such that can be set up in a script like so:
set up maven repo as a folder under the solution folder (using relative reference)
set up anything else maven needs (don't know what, exactly)
call /path/to/maven/mvn compile -f /path/to/oneAndOnly/pom.xml
java /target/MySolutionClas
I am aware of: https://dzone.com/articles/embedding-maven but it gets confusing when he talks about configuring the portable maven into the pom.xml - wait, how is that pom.xml going to mean anything if maven is not configured yet?
(PS: I mean no disrespect to the author. I probably got it all wrong)
One could include a shell script that would setup maven if it is not already present.
The same for building and packaging encapsulating the complexities of the setup to just runing a couple of scripts.
Maven Wrapper aims to do just that, similar to the gradle wrapper seen in many gradle projects.
Running the wrapper goal of the maven wrapper plugin will generate a mvnw script in your project that can be run in place of a globally installed mvn command.
It's part of the maven 3.7.0 release, and documented more fully here: https://maven.apache.org/plugins/maven-wrapper-plugin/index.html
See https://github.com/takari/maven-wrapper for maven < 3.7.0

Maven Release Without Tagging or Compiling

I am trying to use maven to build a JNI project and I am running into some difficulty creating a GA release. The project's native code needs to be compiled on at least 3 systems (Linux, OSX, Windows) due to the native code requirements. I would also like GitHub Actions to produce a release build when I create a tag on GitHub. Because of this, I am facing a number of issues with the maven release plugin. It seems like maven's release process involves compiling and testing the code as well as screwing around with SCM before I can create a GA version and release. This simply isn't possible for this JNI project. I have already gone down the cross compiler route with Ant and I would really like to move away from that for any number of reasons, mostly Apple related. I also thought about releasing each JNI target individually, but I would really like to bundle the native code inside of the JAR and things start getting complicated when I need to share a .m2 folder across different build environments. Is it possible to release a maven project without all the compiling, testing and SCM nonsense? Maybe a different 3rd party plugin? Is there a better way I should be doing this? For reference, the pom can be found here.
Dont use the release plugin, I had a lot more success with the maven version plugin.
All the maven release plugin is doing is taking the version off the snapshot, creating a new commit and then upping the version to a new incremented SNAPSHOT. You can mimic this process without maven needing to know anything about your SCM using versions.
One way to do it is to not SNAPSHOTS and instead build with the git short hash as part of the version:
So while developing, the version looks pretty normal
<groupId>org.example</groupId>
<artifactId>my-app</artifactId>
<version>1.1.0</version>
The do a "release" build based on a tag. My flow was
commit and push
build - mvn clean install, results in my-app-1.1.0.jar
deploy to a test env and run regression tests, if they succeed, we tag the commit with a "passed_tests" tag
CI fires on tags that match "passed_tests" - this needed to be the same commit that resulted in the jar under test
runs mvn -f ./pom.xml versions:set -DnewVersion=${gitProps['git.build.version']}_${gitProps['git.commit.id.abbrev']}
On the disk, our maven version is now:
<groupId>org.example</groupId>
<artifactId>my-app</artifactId>
<version>1.1.0-abcdef</version>
then runs mvn deploy. This is the artifact that gets deployed to the repo and now we have a jar file (or whatever) that has a version matching the git commit.
You could use the same process for all your target architectures.

Building a Maven project offline

I am trying to install OreKit (an orbital mechanics toolkit) to validate some code i've written. Orekit is a maven project and thus it tries to download all its dependencies from the maven repo.
Unfortunately my company has pretty strict internet security measures and the maven repo is not whitelisted. The only way to access non-whitelisted websites is through a secure browser (tightGate) which is basically a video-feed of the browser running on a server. Files downloaded in this browser can then be transfered to my computer using a separate program.
This of course means that the build fails. I have been trying to download all the dependencies manually and put them in the local repository.
example:
eclipse error: "Missing artifact junit:junit:jar:4.12"
I downloaded the corresponding jar and pom files (junit-4.12.jar and junit-4.12.pom) and put them into my local repository (C:/Users//.m2/repository/junit/junit/4.12/)
I did this for every error eclipse reported but nothing changes and the same errors are still there.
Am i doing something wrong here? Is it even possible to build a project this way or should i just give up already?
In principle, this could work, but it would be easier to use mvn install:install-file for the separate jars.
Be aware that the number of artifacts that Maven usually requires is > 100.
We also have strict regulations, but managed to get an extra server with a Nexus that proxies MavenCentral, so we can reach the artifacts through there.
to put jar file in your local maven repository, you must install it.
mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> \
-DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging>
get more info from https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

Apache Maven: where do dependencies and libraries installed locally up?

I'm building a Java project that has a dependency on a library. mvn.bat clean install produced the target subdirectories as expected, and the project built fine with mvn.bat clean install as well.
What's not expected is that when I deleted the entire directory of the library, the outer project still built fine, although the library it depends on was gone.
How does this work?
UPDATE: Turns out Maven makes some sort of cache in %USERPROFILE\.m2.
You are most likely thinking of your local repository where everything you install locally (and maven downloads for you from the central repository) is put for later usage.
The behavior you describe is intentional, and allows for building A once and then let B reference it whenever needed, without having to recompile A every time. This is usually very desirable, especially in teams or with large code bases.
Note, that for changing code you should be using -SNAPSHOT artifacts. They are treated slightly differently.
Your dependencies are always downloaded into .m2/repository.
If you want to have some predictability on downloaded libraries in your team, you can put in place a repository manager like Nexus : https://repository.apache.org/index.html#welcome
Instead of downloading dependencies from Maven central, your developers will download their dependencies from this repository manager.

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

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.

Categories