Module Eclipse Java 9

LeNkUeP

Mitglied
Ich muss zur Zeit mit dem neuen Feature der Modularisierung in Eclipse arbeiten und soll vorhandenen Code "modularisieren" :/

Dieser ganze Modularisierungsprozess erwies sich derweil als ziemlich kompliziert und im Internet gibt es zu speziellen Problemen kaum Hilfe (speziell in Eclipse).
Bis jetzt habe ich mir die Grundlagen der Modularisierung schon aneignen können, jedoch besteht folgendes Problem:

Ich habe zwei Projekte: "module4711" und "module4712" welche jeweils ein gleichnamiges Modul enthalten.
In beiden Projekten gibt es das Package "com.itsg.deuv.kernpruefung" (genau das Gleiche) und in beiden Projekten gibt es in diesem Package eine Klasse "a"... also gleiches Package und doppelte Klasse "a".
Diese Klasse a hat jedoch in beiden Projekten eine unterscheidbare Methode getInfo()...die eine gibt ganz einfach "4711" aus und die andere "4712".
Die Module "exportieren" beide jeweils das Package!

Dann gibt es noch die Projekte "XYVersion4711" und "XYVersion4712".
Diese besitzen jeweils ein, dem Projektnamen entsprechendes, Package und in diesem Package gibt es die Klassen v4711 (XYVersion4711) und v4712 (XYVersion4712), welche beide eine Methode besitzen, welche a.getInfo() aufrufen, also die in den Modulen genannte Methode welche sich trotz gleichen Packages unterscheiden soll!
Damit die Klassen überhaut zugreifen dürfen, müssen ja auch diese Projekte ein Modul enthalten was die oberen Module "required".
Also habe ich die Module "module4711_2" und "module4712_2", welche logischerweise die oberen Module "requiren", erstellt.
Auch diese Module "exportieren" jeweils das Package im jeweiligen Projekt!
Über den Modulpfad ist Projekt "module4711_2" logischerweise mit "module4711" verknüpft, genauso bei "module4712_2" und "module4712", da die Module sonst nicht gefunden werden würden!

Zu guter Letzt gibt es noch das Projekt "Main Project", welches über ein Modul "mainProject" Zugriff auf die Module von XYVersion(...) erhält.
Auch hier wurde der Modulpfad verwendet.
In einer Main-Methode soll jetzt v4711.getInfo() und v4712.getInfo() ausgeführt werden, und das erwartete Ergebnis soll eigentlich einmal "4711" und einmal "4712", quasi dass über die vorhandenen Abhängigkeiten zwischen den gleichen Klassen "a" die verschiedenen Inhalte ausgeführt werden.
Leider wird ein Fehler ausgegeben:
Code:
Error occurred during initialization of boot layer
java.lang.LayerInstantiationException: Package com.itsg.deuv.kernpruefung in both module module4712 and module module4711

In jeder Klasse wurden logischerweise auch die benötigten Importe gemacht und es gibt an sich keinen Fehler...

Wenn ich die gleichnamigen Packages unterscheidbar mache, sprich einen Namen änder dann funktioniert es gut.
Problem liegt also darin dass das Package zweimal verwendet wird...

Habt ihr eine Idee wie ich es schaffe bei gleichem Package und gleichnamiger Klasse mit verschiedenen Inhalten andere Ausgaben erziele?
Im Folgenden werde ich auch noch ein paar Bilder hochladen^^

Danke im Vorraus

PS: Habe Java 9 installiert, also Compiler = 9 usw.
 

Anhänge

  • Gesamte Struktur mit gleichnamigen Package.png
    Gesamte Struktur mit gleichnamigen Package.png
    94,5 KB · Aufrufe: 59
  • Gesamte Struktur mit unterschiedlichen Packages.png
    Gesamte Struktur mit unterschiedlichen Packages.png
    91,4 KB · Aufrufe: 52
Zuletzt bearbeitet:
Afaik ist‘s nicht möglich, verschiedene Versionen einer Klasse zu laden, zumindest nicht ohne rumbasteln mir Classloadern

(Dein Problem ist aber auch schon extrem konstruiert, das ist doch kein echter vorhandener Code?)
 
Nene das war jetzt speziell um das zu testen 🙂
Den Eindruck habe ich mittlerweile auch...hättest du denn eine Idee zum Punkt: "Mit Classloadern rumbasteln"?
Aber danke schonmal.
 
Wie @mrBrown sagte, solltest du solche Strukturen definitiv vermeiden. Doppelte Packages & Klassen sollte es so oder so nicht geben, sonst stimmt etwas mit deiner Software Architektur / Software Design nicht.
Ausnahme: Du supportest mehrere Versionen, dies unterstützt Jigsaw (so nennt sich das neue Modulsystem unter Java 9) aber derzeit noch nicht (soll evtl. im März mit Java 10 kommen), dann kannst du aber trotzdem immer nur eine von beiden Varianten einbinden.
 
Ah ja, die haben das wieder rausgenommen bzw. gar nicht auf Targeted gesetzt, weil es viele Unstimmigkeiten in der Expertengruppe war.
Danke!
Daran hatte ich jetzt ehrlich gesagt gar nicht mehr gedacht. Versionierung der Module war schon bei Java 9 eine heiß diskutierte Sache und bis jetzt gibt es noch keine Lösung, die allen Java EC Mitgliedern gefällt.
 
Leider war es nicht möglich beim Editieren von Beiträgen Bilder hochzuladen, deshalb hier ein neuer.
Hier der entscheidende Absatz des Java Expertengruppen-Meetings:

mn.PNG
 
Danke erstmal für die Antworten🙂
Habe jetzt die Modularisierung erstmal beiseite gelegt und mit URLClassLoader gearbeitet, mit welchem am Ende tatsächlich das gewünschte Ergebnis herauskam.
Durch verschiedene Jars und einen Umweg über ein Interface hats dann doch noch geklappt...Werde den Code auch noch mal hochladen für alle die es interessiert.
 
Hier der Code der Main Klasse (oberste Ebene):
Java:
package MainProject;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class versionsSwitcher {

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, IllegalArgumentException, InvocationTargetException {
        versionsSwitcher switcher = new versionsSwitcher();
        switcher.test();
    }
   
    public void test()
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, IllegalArgumentException, InvocationTargetException {
        URL[] urls = new URL[2];
        urls[0] = new URL("file:C:\\Users\\lku\\Desktop\\ModulesAndJars\\kernpruefung4711.jar");
        urls[1] = new URL("file:C:\\Users\\lku\\Desktop\\ModulesAndJars\\v4711Test.jar");
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
       
        Class<?> c1 = Class.forName("XYVersion4711.v4711", false, urlClassLoader);
       
        Method[] methods = c1.getMethods();
        Method method = methods[0];
        method.invoke(c1.newInstance());

        urlClassLoader.close();

        urls = new URL[2];
        urls[0] = new URL("file:C:\\Users\\lku\\Desktop\\ModulesAndJars\\kernpruefung4712.jar");
        urls[1] = new URL("file:C:\\Users\\lku\\Desktop\\ModulesAndJars\\v4712Test.jar");
        urlClassLoader = new URLClassLoader(urls);
        c1 = Class.forName("XYVersion4712.v4712", false, urlClassLoader);

        Method[] methods2 = c1.getMethods();
        Method method2 = methods2[0];
        method2.invoke(c1.newInstance());
       
        urlClassLoader.close();
    }

}

Hier der Code zu der zweiten Ebene (XYVersion4711 und -4712):
Java:
package XYVersion4711;

import com.itsg.deuv.kernpruefung.a;

public class v4711 {
   
    public void teste() {
        a klasse = new a();
        klasse.getInfo();
    }

}

--> Der Code von v4712 ist denkbar ähnlich^^

Hier der Code der untersten Ebene (doppelte Klasse a):
Java:
package com.itsg.deuv.kernpruefung;

public class a {
   
    public void getInfo() {
        System.out.println("4711");
    }
   
}

--> Auch hier ist der leichte Unterschied zu 4712 erkennbar (steht alles oben beschrieben)

Zu den Beziehungen: Nur die 2te Ebene (XYVersion4711.v4711 und (...)) ist über den Klassenpfad mit der jeweiligen Version von a verbunden, sonst nichts.
Denn wenn man in der Main Klasse (versionSwitcher) einen Klassenpfad zur 2ten Ebene angibt, ist dieser final und es wird unmöglich die beiden Versionen von a zu unterscheiden.
Daher die oben sichtbaren URLs...die gehören zu 4 Jar Dateien welche ich zu der 2ten ebene und zur 1ten Ebene erstellt (exportet) habe. Hier muss der Classloader die nur leicht unterschiedlichen Jars laden und kann so unterscheiden.

Dieses method.invoke (Reflection) kann man auch durch ein Interface umgehen, welches dafür sorgt dass man ein explizites Objekt erstellen kann...den Code kann ich auf Anfrage auch mal posten...
 
Ich hoffe von ganzem Herzen, dass die Problembeschreibung und dieser Code niemals was mit Produktivcode zu tun haben werden 😉
 

Neue Themen


Zurück
Oben