2017-11-27 5 views
2

Ich habe eine verteilte Anwendung, ein Teil davon Vermächtnis ist somit unter Java läuft 7.Compile Paketklassen mit verschiedenen Java-Versionen

Ein weiterer Teil läuft unter Java (und natürlich zusammengestellt) 8.

so ruft Dienst der zweiten VM aus dem ersten Teil der App endet mit:

Exception in thread "main" java.lang.UnsupportedClassVersionError: Unsupported major.minor version 52.0

I deci ded kompilieren benötigten Service mit Java 7 Quelle/Ziel mit Maven Compiler-Plugin.

So stellen wir uns ein Paket mit zwei Klassen:

com/example/A.java 
com/example/B.java 

Wie Maven Compiler-Plugin zu konfigurieren, oder gibt es einen anderen Weg? Kompilieren Sie A.java mit Java 7 und anderen (B.java) mit Java 8.

+0

Verstehe ich Sie richtig: Sie möchten zwei Java-Anwendungen auf verschiedenen JVMs ausführen, eine auf Java 7 und eine auf Java 8? Warum gehören diese Klassen zum selben Projekt/Jar? –

+0

Ja, eine App läuft unter java7 vm, eine andere unter java8 vm. Die Java7 vm-Anwendung hat eine Abhängigkeit vom Paket, die auch für die java8 vm-App verwendet und unter java8 kompiliert wird. Also diese Abhängigkeit (vereinfacht) lassen Sie 2 Dienste, A für java7 vm App und andere für die java8 vm App. – andymur

+0

Machen Sie ein anderes Projekt für Java 8 eins für Java 7 und trennen Sie die Dinge ... – khmarbaise

Antwort

7

Sie gehen hier das falsche Kaninchenloch.

Denken Sie nicht an Ihr Produkt/Bereitstellungseinheit/Lieferung in Bezug auf Paket Grenzen. Pakete sind wirklich etwas, das Ihnen hilft, Quellcode zu organisieren. Nichts anderes.

Das Nachdenken über verschiedene Versionen für verschiedene Pakete ist einfach: Zeit mit der falschen Frage verbringen.

Stattdessen: verstehen Sie Ihre Lieferungen und dann, von dort aus entscheiden, welches Produkt in welcher Version kompiliert werden sollte.

Darüber hinaus: mit einem Service kann viel mehr als nur eine andere Klasse aufrufen. Wenn Sie wirklich verschiedene Komponenten haben, die unabhängig voneinander laufen, die sich aber gegenseitig nutzen müssen: dann definieren Sie diese Dienste, und verwenden Sie definierte Protokolle, um sie miteinander zu verbinden. Beispiel: JVM A stellt eine REST-API bereit und JVM B verwendet diese, um einen von JVM A bereitgestellten Dienst aufzurufen. Dann müssen Sie nicht länger über Java-Versionen nachdenken, sondern konzentrieren sich stattdessen auf die klare Definition Ihrer Schnittstellen und die Möglichkeiten, sie zu benutzen. Oder benutze eine Art Nachrichtenbus. Es gibt viele Optionen zur Auswahl. Wie gesagt: Verwenden Sie Ihre Zeit und Energie, um darüber nachzudenken, anstatt Java-Versionen auf Paketgrenzen zu kontrollieren.

Meine Vorschläge klingen nach Overkill: aber allein die Tatsache, dass JVMs unterschiedliche Versionen haben, deutet darauf hin, dass Sie bereits ein komplexeres "reales" Szenario betrachten. Und in komplexen realen Szenarien sollten Sie sich lieber echten Lösungen (wie Service-Definitionen) zuwenden, anstatt sich um sie herum zu hacken.

3

Haftungsausschluss: @GhostCat answer provides proper guidance, das eigentliche Problem ist in der Lieferung und Verpackung Prozess nicht in der Zusammenstellung. Obwohl stark nicht empfohlen, ist es möglich zu tun, was gefragt wird.Für den Sport, ich werde versuchen, speziell eine Antwort auf die Frage zu finden:

Wie Maven Compiler-Plugin konfigurieren A.java mit Java7 und anderen (B.java) mit Java8 zu kompilieren .

Sie können mehrere Maven Compiler Plugin Ausführungen definieren, von denen jeder mit oder die gewünschte Menge von Klassen ohne und verschiedene Quell-/Zielversion. Zum Beispiel über Profile:

<profiles> 
    <profile> 
     <id>compile-java7</id> 
     <build> 
      <plugins> 
       <plugin> 
        <groupId>org.apache.maven.plugins</groupId> 
        <artifactId>maven-compiler-plugin</artifactId> 
        <version>3.7.0</version> 
        <executions> 
         <execution> 
          <id>default-compile</id> 
          <goals> 
           <goal>compile</goal> 
          </goals> 
          <configuration> 
           <source>1.7</source> 
           <target>1.7</target> 
           <includes> 
            <include>**/*Java7.java</include> 
           </includes> 
          </configuration> 
         </execution> 
        </executions> 
       </plugin> 
      </plugins> 
     </build> 
    </profile> 
    <profile> 
     <id>compile-java8</id> 
     <build> 
      <!-- define similar execution for java 8 --> 
     </build> 
    </profile> 
</profiles> 

Profil verwenden Sie Ihren Build zweimal ausführen müssen (mit mvn ... -Pcompile-java7 und Sohn auf), einmal für jede Java-Version. Sie können auch eine ähnliche Konfiguration vornehmen, um den Build nur einmal ausführen zu können, z. B. die Ausführung mit einem Ausgabeordner für Java 7 und Java 8 usw. definieren. Die Idee besteht darin, unterschiedliche Ausführungen mit unterschiedlicher Quell- und Zielumgebung zu definieren.

Zum Beispiel kann jede Klassen-Versionen unter separaten Ordnern zur Ausgabe:

  • die Ausführung Standard-Compiler
  • Skip Java 7 und Java 8 Ausführung mit dem für das Ausgabeverzeichnis -d Flag definieren
  • Als javac Ordner kann nicht erstellt werden, Sie müssen sicherstellen, dass sie generiert werden (z. B. mit dem AntRun-Plugin)

Sie werden en d-up mit so etwas wie:

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <version>3.7.0</version> 
      <executions> 
       <execution> 
        <id>default-compile</id> 
        <phase>compile</phase> 
        <goals> 
         <goal>compile</goal> 
        </goals> 
        <configuration> 
         <skipMain>true</skipMain> 
        </configuration> 
       </execution> 
       <execution> 
        <id>compile-java7</id> 
        <phase>compile</phase> 
        <goals> 
         <goal>compile</goal> 
        </goals> 
        <configuration> 
         <source>1.7</source> 
         <target>1.7</target> 
         <compilerArgs> 
          <arg>-d</arg> 
          <arg>${build.outputDirectory}/java7</arg> 
         </compilerArgs> 
         <includes> 
          <include>**/*Java7.java</include> 
         </includes> 
        </configuration> 
       </execution> 
       <execution> 
        <id>compile-java8</id> 
        <phase>compile</phase> 
        <goals> 
         <goal>compile</goal> 
        </goals> 
        <configuration> 
         <source>1.8</source> 
         <target>1.8</target> 
         <compilerArgs> 
          <arg>-d</arg> 
          <arg>${build.outputDirectory}/java8</arg> 
         </compilerArgs> 
         <includes> 
          <include>**/*Java8.java</include> 
         </includes> 
        </configuration> 
       </execution> 
      </executions> 
     </plugin> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-antrun-plugin</artifactId> 
      <version>1.8</version> 
      <executions> 
       <execution> 
        <phase>validate</phase> 
        <configuration> 
         <tasks> 
          <echo message="Creating test output directory"/> 
          <mkdir dir="./target/classes/java7"/> 
          <mkdir dir="./target/classes/java8"/> 
         </tasks> 
        </configuration> 
        <goals> 
         <goal>run</goal> 
        </goals> 
       </execution> 
      </executions> 
     </plugin> 
    </plugins> 
</build> 

Beachten Sie, dass eine solche Praxis, wenn möglich, noch eine schlechte Idee:

  • Problem wird besser durch die Überprüfung der Liefermethoden und Architektur für Ihr Projekt beantwortet werden as pointed out by GhostCat
  • Sie complexify über Build (das ist schlicht Plugin-Konfiguration Folter, das ist!)
  • Sie überschreiben die meisten Maven Standardverhalten