How do I use Maven as a sane build system? - java

Yes, this is a real question.
I want to cater for the following workflow in a multi module Maven based project:
Make a change in module X
Run a Java application in module Y
Module Y may directly or indirectly depend on module X, I need all modules affected by a change to another to be compiled, recursively. I do not want tests to be run.
How, in Maven, do I do this without having to compile and install everything every time?

Why do you have to make and install everytime? The easiest solution I've found is mvn install one time. Then you can go into individual projects and build them whenever you want. If you need to ensure the chain is picked up just do the build from the top and use mvn -amd -pl projectname
This says to build a specific project and it's dependencies.

Development stage
I don't think you could do it easily with the maven only. During development however you could skip tests adding -DskipTests.
The maven cannot do incremental compilation properly. The right way to do it is to use IDE which will import maven projects into IDE's projects and then you could have fast and easy development. IntelliJ IDEA works quite well with the maven.
Production stage
For release build you could use explicit versions in the target artifact. So after changes in module X if you building the final release artifact module Y you could add explicit dependency in it. In this case all modules between X and Y will have older version (but you should assume they will work with the new X which is always not true).

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

Installing a framework without maven or gradle

I try to install Javalin framework for creating an API on my Java project. (old java 8 project without maven, gradle, etc). I would like to install the framework with adding the jars to my build path.
But If I add the main jar file then it needs another dependencies jar , then another one another one another one.. etc.
Is there any simple way to add this to my project and all it's dependencies without any build tool like Maven,etc?
I have tried adding it manually , but each jar has many dependencies that it is almost impossible(?)
Well you could create a Maven project and use it to download the dependencies for you.
Maven dependency plugin might be useful. With it you could just call:
mvn dependency:copy-dependencies
and it will download all your dependencies into target/dependency.
I don't think there's a way, I'm afraid.  Dependency management is the exact problem that build tools like Maven and Gradle were created to solve!
The framework supplier could provide a ‘fat’ jar including all the dependencies; but I'm not aware of any that do, as everyone uses Maven or Gradle (or SBT or Ivy or Grape or Leiningen or Buildr).
I think the only real alternative is to do it manually — which, as you've discovered, can be a horrible and lengthy task if the dependency tree is big.  (And would need redoing with every update.)
So I'd suggest biting the bullet and using Maven if you can.

How to make maven use separate target folders for every version of program?

As example, i have program with version 0.0.1. Maven must create separate folder for it - "target/0.0.1/" instead of "target/". It must be done for version "0.0.2", "0.0.3", etc.
I use Eclipse & it's Maven:
Version: Oxygen.3a Release (4.7.3a)
Build id: 20180405-1200
JDK 1.8.0_172
Maven doesn't work that way, and trying to do something like that will lead to a path of suffering. Options I see include
Creating a separate assembly (and output Jar) for each version (see Maven Assembly Plugin)
Create a multi-project reactor with a separate output configuration for every project. Keep common code in one project that you link as dependency from the others. Possibly use the maven-shade-plugin to re-link the packages in your common project into the individual output projects
As you can see, both of these approaches are pretty hacky and require advanced Maven skills. It would be much easier to have parameterized builds where you pass in the output version. But that would make sense on a CI server like Jenkins.

Maven, m2e, not building local dependencies

We have a setup of Maven module like this:
Parent
common
webapp
Where webapp has declared a dependency to common.
In our Eclipse environment, using m2e, we made a change in common. Then ran maven package on webapp, deployed and tested the webservice. There was now a fault that indicated that the package we had done did not include the latest changes in common.
We are trying to figure out the best way to use Maven in our day-to-day development. So whats the best practice to handle situations like this?
The way to solve this issue would have been to; Make changes in common, save them, run maven install, make changes in webapp, run maven package, and use the war file for tests. But this contains a lot manual steps.
I guess another way would be to run maven package on the parent, but as the parent grows with more modules this will take longer.
How do you expect changes to common to be available unless you package and deploy it separately? Maven is not magic and it cannot make magic things happen. The solution in this case is to either manually deploy common or do as you suggest package and deploy the parent.
Parent 1.0-SNAPSHOT
+common 1.0-SNAPSHOT
+webapp 1.0-SNAPSHOT
You must use a snapshot version in the parent and reuse the same version in both module.
You must import every module in eclipse
You must run mvn clean install from the parent
If you do all this, Eclipse will recognize when there's a dependency 'webapp' project to 'common' project. Eclipse takes the 'common' project in the build-path of the 'webapp' project. Any change in 'common' is seen by 'webapp'.

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.

Categories