# Multi Module Maven Projekt und GitâSubmodul
## Maven Submodules
Neues Maven Submodule in Idea erstellen:
`-> File -> New -> Module -> Maven`
### Schritt 1
{width=900 height=333}
### Scrhit 2
{width=684 height=600}
{width=684 height=600}
Output geht đ
{width=900 height=436}
### Schritt 3
{width=681 height=600}
{width=852 height=286}
!!! warning "Warnung"
Default mĂ€ssig wird eine Java Klasse in Idea ohne package angabe gemacht dadruch hatte [Schritt 4](#schritt-4) probleme Oben folgendes hinzufĂŒgen:
`package ch.bbw.skm.multimodulemaven.greeter;`
### Schritt 4
{width=816 height=600}
### Schritt 5
{width=900 height=587}
{width=900 height=587}
### Schritt 6
{width=542 height=600}
!!! note "Hinweis"
Ausversehen `submodules` dir gelöscht zumglĂŒck in git gehabt.
{width=900 height=146}
### Fragen zum VerstÀndnis?
- Was ist ein Multi-Modul-Maven-Projekt?
Es ist ein Projekt wo aus mehreren Maven Subprojekten besteht.
- Was ist die Rolle des Parent Projektes?
Es Bundeled und Unified alle Subpackages
- Was ist die Rolle der Module?
Es entkapselt seinen relavanten Code in sich.
- Wie werden die Module in der pom.xml des Parent Projektes definiert?
Gar nicht
- Wie werden die gemeinsamen Einstellungen im Parent Projekt definiert?
Unter dem `properties` Key im `pom.xml`
- Wie wird das Parent Projekt in den Modulen referenziert?
```xml
ch.bbw.skm.multimodulemaven
multimoduleproject
1.0-SNAPSHOT
```
- Wie wird die AbhÀngigkeit von einem Modul zu einem anderen Modul definiert?
Mit einem `dependency` entry
```xml
ch.bbw.skm.multimodulemaven
greeter-lib
1.0-SNAPSHOT
```
- Was ist der Unterschied zwischen dem Modul `app-main` und dem Modul `greeter-lib`?
Das `app-main` kann ausgefĂŒhrt werden. WĂ€hrend dem `greeter-lib` nur Code ist.
## Git Submodule Maven Project
`greeter-lib` in ein eigenes Git-Repo verschieben.
### Schritt 1
{width=900 height=467}
### Schritt 2
{width=900 height=133}
!!! warning "Warnung"
Darauf achten, dass die Dateien des `greeter-lib` Moduls danach **nicht mehr doppelt** im Hauptprojekt-Repository getrackt sind (z.Bsp. noch unter `submodules/greeter-lib`). Falls der Ordner vorher schon eingecheckte Dateien enthielt, mĂŒssen diese mit `git rm` aus dem Hauptrepo entfernt werden, sonst existiert der Code parallel im Submodule und im Hauptrepo.
!!! warning "Warnung"
Git Submodule werden beim normalen `git clone` **nicht automatisch mitgeklont** â der `greeter-lib` Ordner bleibt dann leer. Nach dem Clonen zusĂ€tzlich ausfĂŒhren:
`git submodule update --init --recursive`
(oder direkt beim Clonen: `git clone --recurse-submodules `)
### Fragen zum VerstÀndnis
- Was ist ein Git-Submodule?
Ein git submodule ist ein Git Objekt welches von git gemanaged wird um Source Code zu externalisieren.
- Wie erstellt man ein Git-Submodule?
```sh
git submodule add Git-Repo dir-name
```
- In welcher Datei werden die Git-Submodule verwaltet?
In `.gitmodules`
- Wie clont man das Hauptprojekt mit all seinen Submodulen?
```sh
git clone --recursive Git-Repo
```
- Wie speichert man eine im Submodule 'greeter-lib` geÀnderte Datei im Git-Repository des Submodules?
```sh
cd greeter-lib
git add
git commit -m "..."
git push
```
- Wie speichert man eine im Hauptprojekt geÀnderte Datei im Git-Repository des Hauptprojektes?
```sh
git add
git commit -m "..."
git push
```
- Wie speichert man eine im Submodule 'app-main` geÀnderte Datei im Git-Repository des Hauptprojektes?
```sh
cd app-main
git add
git commit -m "..."
git push
```
Oder
```sh
git add app-main/
git commit -m "..."
git push
```
- Wie speichert das Hauptprojekt die Referenz auf die Version des Submodules greeter-lib?
1. .gitmodules â legt fest wo (Pfad) und woher (Remote-URL) das Submodule liegt:
```
[submodule "greeter-lib"]
path = greeter-lib
url = git@git.foobar.vip:.../greeter-lib-subrepo.git
```
2. Gitlink im Git-Tree â fĂŒr den Ordner greeter-lib legt Git im Hauptrepo einen speziellen Eintrag vom Typ 160000 an, der direkt auf einen bestimmten Commit-Hash im Submodule-Repo zeigt:
```sh
git ls-tree HEAD greeter-lib
# 160000 commit 6eddae0fc04b91fbd7f11782b32096f6b1fad018 greeter-lib
```
- Wie aktualisiert man diese Referenz im Hauptprojekt?
1. Im Submodule den gewĂŒnschten Stand auschecken/pullen (z.Bsp. neuesten Commit vom Remote holen):
```sh
cd greeter-lib
git pull origin main
cd ..
```
(oder, fĂŒr alle Submodule aufs Mal, vom Hauptprojekt aus: `git submodule update --remote greeter-lib`)
2. Den neuen Stand des Submodules im Hauptprojekt-Commit festhalten â Git erkennt, dass sich der Gitlink geĂ€ndert hat, sobald der Submodule-HEAD nicht mehr mit dem gespeicherten Commit-Hash ĂŒbereinstimmt (`git status` zeigt dann `modified: greeter-lib (new commits)`):
```sh
git add greeter-lib
git commit -m "update greeter-lib submodule reference"
git push
```
# IDEâAnsatz vs. Maven/Gradle
**IDE-Ansatz (IntelliJ Artifacts):** IntelliJ hat ein eigenes, Maven-unabhÀngiges Artefaktmanagement. Unter `File -> Project Structure -> Artifacts` definiert man Name, Typ (z.Bsp. JAR), Output-Verzeichnis und ob das Artefakt beim Project Build automatisch mitgebaut wird; gebaut wird via `Build -> Build Artifacts`. Einbinden eines fremden Artefakts ohne Maven/Gradle: `Project Structure -> Modules -> Dependencies -> + -> JARs or Directories` und die JAR-Datei manuell auswÀhlen. Die Konfiguration landet in den `.idea`/`.iml`-Dateien.
**Maven/Gradle-Ansatz:** Artefakt wird deklarativ in `pom.xml` (`` mit groupId/artifactId/version) bzw. `build.gradle` (`implementation '...'`) eingetragen. Das Tool lÀdt es automatisch aus einem Repository (Maven Central, lokal `~/.m2`) inkl. aller transitiven AbhÀngigkeiten. Build via `mvn package` / `gradle build`.
| | IDE-Ansatz | Maven/Gradle |
|---|---|---|
| â | Schnell per GUI, kein Setup, gut fĂŒr kleine Experimente | Portabel (CLI, CI/CD, jede IDE), Versionierung, transitive Dependencies, Repositories |
| â | ProprietĂ€r (an IntelliJ gebunden), nicht CI/CD-fĂ€hig, JARs manuell beschaffen/aktualisieren, keine transitiven Dependencies | Mehr Initialaufwand, XML/DSL lernen |
**Fazit:** IDE-Artefakte sind fĂŒr lokale Ausnahmen okay; fĂŒr alles TeamfĂ€hige und Automatisierte (DevOps!) sind Maven/Gradle der Standard, weil der Build reproduzierbar und toolunabhĂ€ngig ist.
# Refresher: Was ist ein MavenâArtefakt?
## Bedeutung von Begriffen
- **GroupId:** uniquely identifies a project group across all other groups. Each groupId should follow Java's package name rules. This means it starts with a reversed domain name you control.
_Examples:_
```
org.apache.maven
org.apache.commons
com.google.guava
```
- **ArtifactId:** is the name of the artifact. The identifiers should only consist of lowercase letters, digits, and hyphens.
_Examples:_
```
commons-math
maven-clean-plugin
```
- **Version:**` follow the rules of [Semantic Versioning 1.0.0](https://semver.org/spec/v1.0.0.html). It should start with the major version, followed by the minor version and the patch version. All three are numeric, separated by a dot. You can add labels for pre-releases or build metadata after the patch version. Avoid using dates in those labels, because they are usually associated with unstable versions.
_Examples:_
```
1.0.0
2.3.2
3.5.42
// Pre-releases
1.0.0-beta
1.0.0-M1
1.0.0-rc2
// Build metadata
1.2.3+dfc0c87
2.3.4+15433
```
- **Packaging:** give us a really complete what: that is the project's packaging (`JAR|WAR`)
- **Classifier:** The classifier distinguishes artifacts that were built from the same POM but differ in content. It is some optional and arbitrary string that - if present - is appended to the artifact name just after the version number.
As a motivation for this element, consider for example a project that offers an artifact targeting Java 11 but at the same time also an artifact that still supports Java 1.8. The first artifact could be equipped with the classifier `jdk11` and the second one with `jdk8` such that clients can choose which one to use.
## Aufbau eines Maven Artifakt
> Erarbeiten Sie den Aufbau eines MavenâArtefakts.Aufbau festhalten und erklĂ€ren.
Ein Maven-Artefakt ist eine Datei (meistens ein JAR), die in einem Maven-Repository abgelegt und ĂŒber ihre **Koordinaten** eindeutig identifiziert wird:
```
groupId:artifactId:packaging:classifier:version
```
_Beispiel:_ `org.apache.commons:commons-lang3:jar:3.12.0`
Nur `groupId:artifactId:version` (**GAV**) sind Pflicht â `packaging` (Default: `jar`) und `classifier` sind optional.
**Dateiname** nach Konvention:
```
-[-].
z.Bsp. greeter-lib-1.0-SNAPSHOT.jar
commons-lang3-3.12.0-sources.jar
```
**Ablage im Repository** â die Koordinaten bestimmen den Pfad:
```
/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar
âââ groupId (Punkte = Ordner) ââââ artifactId ââ version â
```
**Inhalt eines JAR-Artefakts:**
- kompilierte `.class`-Dateien (in der Package-Struktur)
- `META-INF/MANIFEST.MF` (Metadaten, ggf. Main-Class)
- `META-INF/maven///pom.xml` + `pom.properties` â das Artefakt trĂ€gt seine eigene Baubeschreibung mit
Daneben liegen im Repository zum selben Artefakt typischerweise die `.pom`-Datei (fĂŒr transitive Dependencies), Checksummen (`.sha1`) und optional `-sources.jar` / `-javadoc.jar` als Classifier-Varianten.
# Lokales MavenâRepository
- Path (Linux/*NIX): `~/.m2`
## Custom LocalRepo Config File
Add the following snippet to `~/.m2/settings.xml`:
```xml
/path/to/maven_repository
...
```
## Custom LocalRepo CLI
```sh
mvn -Dmaven.repo.local=/path/to/maven_repository clean install
```
!!! note "Hinweis"
Important argument is `-Dmaven.repo.local=/path/to/maven_repository`
# Artefakte zur VerfĂŒgung stellen
> Recherchiere Möglichkeiten, ein MavenâArtefakt zu veröffentlichen (Maven Central, Nexus/Artifactory, GitHub Packages, FileâSharing).
> Beschreiben kurz zu den jeweiligen Möglichkeiten, wie man vorgeht, um ein Artefakt zu veröffentlichen.
> Halten Sie Vorâ und Nachteile der jeweiligen Möglichkeit fest.
## GitLab Packages
**Vorgehen:** In `pom.xml` `` mit der GitLab-Registry-URL (`.../api/v4/projects//packages/maven`) eintragen, Auth-Token in `settings.xml`, dann `mvn deploy`.
- â Direkt beim Repo (CI/CD-Integration), private Packages gratis
- â Nur fĂŒr Nutzer mit GitLab-Zugang, Token-Handling nötig
## Maven Central
**Vorgehen:** Account beim Central Portal, groupId (Domain) verifizieren, Artefakt muss Sources + Javadoc + GPG-Signatur enthalten, dann via `maven-publish`/`central-publishing-maven-plugin` deployen.
- â Weltweit standardmĂ€ssig verfĂŒgbar, kein Repo-Eintrag beim Konsumenten nötig
- â AufwĂ€ndiges Setup, strenge Anforderungen, nur öffentlich, kein Löschen möglich
## Nexus/Artifactory
**Vorgehen:** Eigenen Repository-Server betreiben, Repo anlegen, URL in `` + Credentials in `settings.xml`, `mvn deploy`.
- â Volle Kontrolle, privat, Proxy/Cache fĂŒr Central
- â Server selbst betreiben und warten (Kosten, Aufwand)
## File-Sharing
**Vorgehen:** `mvn package`, JAR (+ pom) manuell verschicken/ablegen (Mail, Ordner, Cloud); EmpfÀnger installiert mit `mvn install:install-file -Dfile=... -DgroupId=... -DartifactId=... -Dversion=...`.
- â Null Infrastruktur, sofort
- â Keine Versionierung/transitive Dependencies, manuell, fehleranfĂ€llig â nicht teamtauglich
---
# Sources
- https://bbw-it.github.io/324_main_rupe/14_MavenArtefacts/14.1-JavaProjektUndArtefakte/
- https://bbw-it.github.io/324_main_rupe/50_KnowledgeBase/14_MavenArtefacts/MultiModuleMavenProject/
- https://bbw-it.github.io/324_main_rupe/50_KnowledgeBase/14_MavenArtefacts/GitSubmoduleMavenProject/
- https://www.jetbrains.com/help/idea/artifacts.html
- https://maven.apache.org/guides/mini/guide-naming-conventions.html
- https://maven.apache.org/pom.html#packaging
- https://www.baeldung.com/maven-local-repository
- https://maven.apache.org/settings.html