From Jigsaw Project:
Make it easier for developers to construct and maintain libraries and
large applications, for both the Java SE and EE Platforms.
I'm trying to learn what project Jigsaw is and till now it seems that the goal of Project Jigsaw somewhat overlaps with what we did using Maven (or Gradle) dependency management:
Is it a threat to build tools like Maven?
Or my understanding is wrong and project Jigsaw is going to complement these build tools in some way?
Very simplified answer
After Jigsaw, public will be public only within the JAR scope. To see the class outside the JAR it must be exported.
Java will force modularization because any inter module interaction will have to be specified in the module-info file.
For example, if you produce a WAR it will remain almost unchanged but all JARs packages in the WAR must define a module-info (or not define it and be treated as automatic or unnamed modules).
Maven has 2 main features: dependency management and building:
Dependency management means Maven can determine versions of libraries
and download them from repositiories.
Building means Maven can compile code and package it into artifacts.
To conclude: Maven will still be responsible for building, but one must learn how to compile and package using Jigsaw modules.
Modules are not in any way a threat to build tools. Modules complement build tools because build tools construct a dependency graph of artifacts and their versions at build time while modules enforce dependencies of artifacts/modules (not including versions) at build time and run time.
From the State of the Module System:
"A module’s declaration does not include a version string, nor
constraints upon the version strings of the modules upon which it
depends. This is intentional: It is not a goal of the module system
to solve the version-selection problem, which is best left to build
tools and container applications."
Related
I'm trying to understand the difference(s) between structuring a project with the Java Platform Module System (JPMS) versus structuring a project using multi-poms.
Is the main difference that the JPMS encapsulates the code while a multi-pom project separates project dependencies?
I've searched on google but I haven't found a good explanation on the differences, but rather I see the word module getting used interchangably.
The computing industry often recycles terms. Context is everything.
The two kinds of “module” you present are unrelated, orthogonal issues.
The Java Platform Module System (JPMS) is a way to identify to the Java compiler namespaces amongst all the classes and methods available at runtime.
Multi-module in Apache Maven is a way to conjoin into one project what could be handled as separate projects. Each module in the project has its own POM with its own dependency and build settings, yet all can be managed as one super-project when combined as a Maven multi-module. Each module results in producing an artifact, such as a JAR or WAR file.
Very simple apps in Java may use neither.
Ideally new Java apps would use the JPMS, but it is still technically optional. In a perfect world, JPMS would have been included in the original Java, but was in fact added only recently, in Java 9. JPMS is quite handy if your app will run as a standalone, with a JVM bundled, because you can include a JVM that has been stripped down to only the parts actually used by your particular app (see jlink, jpackage, and related tools enabled by JPMS).
Maven multi-module projects are generally only used for complicated projects such as an app that includes a piece of functionality which may be spun-off for use in other projects. Or a multi-module Maven project may be good for an app that combines both a frontend user-interface module along with a backend business-logic module where we want to manage each part separately yet combine them into a single deliverable, such as a Vaadin Flow web app.
I can see how you could become confused, as both have to do with arranging classes. To oversimplify, Maven modules are about compile-time (dependency management and build automation) while Java Platform Module System is about runtime.
I’ve read that Gradle is more adept at managing a multi-module project. You might consider switching from Maven to Gradle for your multi-module projects. Gradle obtains your dependencies from Maven repositories.
The app consists of modules and each module is particular maven project with one parent. These modules are used as jars in main app.
Each module uses third party SDK via maven.
These SDKs have many dependencies and these dependencies can be with the same group and artifact but with different versions. It is hard to manage them and we have problems with 'NoSuchMethodError's. As for me the simplest way to fix problem is to get sources of problematic dependencies and source of SDK, change the package (add some prefix) and imports and put it inside sdk jar.
But this approach requires: one more git repository for forked SDK's jars and private maven repository to publish them and a lot of time.
Is there maven plugin that can help with this problem, for example plugin that can build jar (our module jar) with all dependencies included inside it but can change package of all dependencies?
You can try to use the Maven shade plugin which allows you to relocate classes
https://maven.apache.org/plugins/maven-shade-plugin/examples/class-relocation.html
but I have never tried this myself.
In most cases it is better to try to align the dependencies so that you use the same versions in most places and also to reduce dependencies to a minimum.
Congratulations, you are confronted with a classpath problem called "jar hell". The only safely working solution i know is the use of different classloaders for each version of the same class (if it's not backward compatible).
A class is identified by its qualified name (package and class name) and by the classloader it has been loaded. If the application uses the default system classloader and there is the same class in different versions in the classpath only one version will be loaded by the classloader. In the oracle JDK/JRE it is the one which occurred first in the classpath. If you are lucky you can bring the classpath (order and excluding dependencies) in a special order in which your application will run, but i wouldn't recommend it since it relies heavy on the JDK/JRE implementation.
OSGI is a technology which might be helpful for this since it provides a module based framework for using different classloaders.
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.
I have a simple problem but being a novice with Maven it's unclear which is the best practice to solve this problem.
A project I'm working has a dependency to manage archives which is the following: net.sf.sevenzipjbindings.
This dependency is made by two artifacts: a pure Java one, which provides the Java interface and another one which is the native underlying code which has many flavours according to the operating system.
At the moment I'm packaging the jar built by maven with all the natives for all the platforms but I'd like to be able to do something like:
when working (so compile goal if I understand correctly) on the project use the all-platforms artifact (so that I can work seamlessly from multiple operating systems
when packaging build 3 different JAR with dependencies composed by the Java interface + a specific platform artifact
This sounds rather simple from my point of view but I'm struggling to understand what I should do and what are the best practices in general. Since here there is no different or modular functionality (like isolating part of the code into a separated module), just a replacement for underlying dynamic libraries.
It sounds like you want a multi-module Maven build:
- myapp
- myapp-engine
- myapp-windows
- myapp-linux
The myapp-engine module should depend on external-library-api, and the myapp-windows module should depend on myapp-engine and external-library-windows. Since you're actually only running the application on a specific OS for any given launch (even in development), there's no reason not to launch the OS-specific module. Modern IDEs should have no trouble debugging into a separate module in a multi-module build.
What are the main possible reasons of breaking down a Maven project to sub-modules?
Are you looking something more than the benefits of Modularization? The sub-modules should ideally be representing a single concept/feature so that they are functionally cohesive.
Pom file inheritence
You can use the and sections of the root poms to keep consistent version numbers and configurations across all child projects. So if I have an aggregator project that lists 300 projects, all that use apache commons-io and I want to upgrade them all the the latest version of commons-io, I can just change the version in the dependencyManagement section of the root pom. None of the child projects need specify a version.
build profiles
In the above example, if I have 300 sub projects, an individual developer is probably not regularly working on all (or even many) of the 300 sub-projects. You can create a build profile that specifies only the modules you work on regularly, and if you have a continuous integration server that deploys artifacts to an artifact repository, you'll get all the changes the developers on your team make too, without having to build all 300 modules.
General organization/clarity
While waiting for an answer to my comment.
A reason to split a Java EE based maven project into sub modules is so you can build the JAR/RAR/WAR/EAR/whatever independently of eachother.
For regular Java apps, you might split out the functionality into separate JARs, again each of these could be a sub-module under the overall project and again you can build them independently, run separate goals/phases/reports etc.