2012-03-26 10 views
7

Ich schaute auf this question, aber es löste mein Problem nicht wirklich, also dachte ich mir, ich würde ein neues schreiben.Wie erstellt man ein gebündeltes lauffähiges Glas mit Ant

Ich brauche eine runnable Jar (runnable einfach durch Doppelklick) mit Ant. Ich habe den folgenden Java-Code und die build.xml-Datei, die den Code gut kompiliert und eine JAR-Datei erstellt, aber wenn ich versuche, das JAR durch Doppelklick auszuführen, erhalte ich die Meldung "Konnte Hauptklasse nicht finden: HttpController. Java."

Ich habe den Verdacht, dass mein Problem mit dem Laden der externen Apache Http.jar zu tun hat, wie ich erfolgreich ein Glas für ein Projekt gebaut und ausgeführt habe, die identisch ist, außer dass es keine externen Gläser referenziert.

ist hier mein Code:

HttpController.java:

package pack; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpHost; 
import org.apache.http.HttpMessage; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 

public class HttpController { 
     public static void main(String[] args) { 

     DefaultHttpClient client = new DefaultHttpClient(); 
     HttpHost httphost = new HttpHost("localhost", 80); 

     try { 

      HttpMessage req = new HttpGet("/test.html"); 
      HttpResponse resp = client.execute(httphost, (HttpGet) req); 
      HttpEntity entity = resp.getEntity(); 

      BufferedReader in = new BufferedReader(new InputStreamReader(
        entity.getContent())); 

      String line = null; 
      while ((line = in.readLine()) != null) { 
       System.out.println(line); 
      } 

     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      // shutdown the connection 
      client.getConnectionManager().shutdown(); 
     } 
    } 
} 

build.xml:

<?xml version="1.0" encoding="ISO-8859-1"?> 
    <project name="Test" basedir="." default="jar"> 
    <property name="source.dir"  value="src"/> 
    <property name="lib.dir"  value="lib"/> 
    <property name="class.dir"  value="bin"/> 
    <property name="jar.dir"  value="dist"/> 
    <property name="main-class"  value="pack.HttpController"/> 

    <path id="libraries.path">  
     <fileset dir="${lib.dir}"> 
      <include name="*.jar"/> 
     </fileset> 
    </path> 

    <target name="clean" description="delete old files"> 
     <delete dir="${class.dir}"/> 
     <delete dir="${jar.dir}"/> 
    </target> 

    <target name="compile" description="build class files" depends="clean"> 
     <mkdir dir="${class.dir}"/> 
     <javac srcdir="${source.dir}" destdir="${class.dir}"> 
      <classpath refid="libraries.path"/> 
     </javac> 
    </target> 

    <target name="jar" depends="compile"> 
     <mkdir dir="${jar.dir}"/> 
     <mkdir dir="${jar.dir}/${lib.dir}"/> 
     <copy todir="${jar.dir}/${lib.dir}" flatten="true"> 
      <path refid="libraries.path"/> 
     </copy> 
     <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${class.dir}"> 
      <manifest> 
       <attribute name="Main-Class" value="${main-class}"/> 
       <attribute name="Class-Path" value="${jar.dir}/${lib.dir}/Apache HTTP.jar"/> 
      </manifest> 
     </jar> 
    </target> 

    <target name="run" depends="jar"> 
     <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/> 
    </target> 
</project> 

MANIFEST.MF:

Manifest-Version: 1.0 
Ant-Version: Apache Ant 1.8.3 
Created-By: 1.6.0_31-b05 (Sun Microsystems Inc.) 
Main-Class: HttpController 
Class-Path: dist/lib 

EDIT build.xml wurde gemäß Mikes Antwort aktualisiert. Das Problem ist immer noch nicht gelöst. Außerdem wurde der Inhalt der Manifest-Datei gemäß der Antwort von Danation gepostet.

+0

@see http://one-jar.sourceforge.net/index.php?page=build-tools&file=ant-example. – Jayan

+0

@jayan ist es möglich, dies ohne externe Tools zu tun? zB indem ich einfach Ant benutze und meine eigene build.xml Datei schreibe? – ewok

+0

Es gibt Fragen/Antworten in SO über die Erstellung von ausführbaren Gläsern mit Eclipse usw. Siehe http://StackOverflow.com/Questions/502960/Eclipse-How-To-Build-an-Executable-Jar-With-External-Jar. Ich bevorzuge Ein-Jar, da es eine einzelne ausführbare Datei erstellt. Die Integration in die Ameise sollte 10 Minuten dauern. Warum nicht versuchen, das Ergebnis zu sehen? – Jayan

Antwort

0

Werfen Sie einen Blick auf Ihre Manifest-Datei, es ist höchstwahrscheinlich ein Problem in dort. Ich habe diesen Fehler nur gesehen, wenn die Manifestdatei nicht korrekt ist.

Nur Spekulationen, aber ich denke, es versucht, eine ".java" -Datei zu starten, da es Hauptklasse ist, die nicht funktionieren wird.

Siehe das Orakel-Tutorial: http://docs.oracle.com/javase/tutorial/deployment/jar/appman.html.

Wenn das überhaupt nicht hilft, posten Sie den Inhalt Ihrer Manifest-Datei sowie die Verzeichnisstruktur der .jar-Datei in Ihrer ursprünglichen Frage.

+0

Ich weiß, dass es ein Problem mit der Manifest-Datei gibt, aber ich muss wissen, wie build.xml so konfiguriert wird, dass ant korrekt generiert wird. – ewok

+1

@ewok: Veröffentlichen Sie den Inhalt Ihrer Manifest-Datei sowie die Verzeichnisstruktur der .jar-Datei in Ihrer ursprünglichen Frage. Sobald das Problem identifiziert ist, sollten Sie eine bessere Vorstellung davon haben, wo das Problem in der build.xml ist. – Danation

+0

geschrieben. Ich aktualisierte auch build.xml basierend auf Mikes Antwort – ewok

16

Snip ...

ich Ihre build.xml Datei überarbeitet habe einschließen richtig die Bibliotheken in der JAR-Datei und in dem Manifest Classpath. Ich gehe davon aus, dass Ihre "Apache http.jar" Datei ein Wrapper für Apache Core ist, und enthält mehrere andere JAR-Dateien in es für den Apache-Client usw.

build.xml

<?xml version="1.0" encoding="ISO-8859-1"?> 
<project name="Test" basedir="." default="jar"> 
    <property name="source.dir"  value="src"/> 
    <property name="lib.dir"  value="lib"/> 
    <property name="class.dir"  value="bin"/> 
    <property name="jar.dir"  value="dist"/> 
    <property name="jar.file"  value="${jar.dir}/${ant.project.name}.jar"/> 
    <property name="main-class"  value="pack.HttpController"/> 

    <path id="libraries.path">  
     <fileset dir="${lib.dir}"> 
      <include name="*.jar"/> 
     </fileset> 
    </path> 

    <target name="clean" description="delete old files"> 
     <delete dir="${class.dir}"/> 
     <delete dir="${jar.dir}"/> 
    </target> 

    <target name="compile" description="build class files" depends="clean"> 
     <mkdir dir="${class.dir}"/> 
     <javac srcdir="${source.dir}" destdir="${class.dir}"> 
      <classpath refid="libraries.path"/> 
     </javac> 
    </target> 

    <target name="jar" depends="compile"> 
     <mkdir dir="${jar.dir}"/> 
     <mkdir dir="${class.dir}/${lib.dir}"/> 
     <copy todir="${class.dir}/${lib.dir}" flatten="true"> 
      <path refid="libraries.path"/> 
     </copy> 

     <manifestclasspath property="manifest.classpath" jarfile="${jar.file}"> 
      <classpath refid="libraries.path"/> 
     </manifestclasspath> 

     <jar destfile="${jar.file}" basedir="${class.dir}"> 
      <manifest> 
       <attribute name="Main-Class" value="${main-class}"/> 
       <attribute name="Class-Path" value="${manifest.classpath}"/> 
      </manifest> 
     </jar> 
    </target> 

    <target name="run" depends="jar"> 
     <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/> 
    </target> 

</project> 
+0

Ich machte die Änderungen empfohlen. Ein paar Dinge musste ich ändern (es gibt keine '$ {dist}' Eigenschaft, ich denke du meintest '$ {jar.dir}'), aber der Build gibt immer noch denselben Fehler zurück. – ewok

+0

Bitte geben Sie auch das Verzeichnislayout der JAR-Datei an. Ich frage mich, ob die RT verärgert ist, dass Ihre Klasse im Standardpaket ist. – Mike

+0

Ich habe 'HttpController.java' in das Paket' pack' (src/pack) verschoben und die Datei build.xml entsprechend angepasst, aber derselbe Fehler tritt auf. – ewok

4

Ihre Class-Path Eintrag ist falsch, Sie müssen jede JAR - Datei einzeln angeben, Sie können kein Verzeichnis mit JAR - Dateien angeben (nur Verzeichnisse mit.Klassendateien)

Dies ist in der JAR File specification dokumentiert und erklärt ganz gut in der Java tutorial

Wenn Sie zwei Bibliotheken nennen FirstLib.jar und SeconLib.jar Ihre Class-Path-Eintrag sollte wie folgt aussehen:

Class-Path: lib/FirstLib.jar lib/SecondLib.jar 

Bearbeiten:
In Ihrer build.xml würde dies wie folgt aussehen:

<jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${class.dir}"> 
    <manifest> 
     <attribute name="Main-Class" value="${main-class}"/> 
     <attribute name="Class-Path" value="${lib.dir}/FirstLib.jar ${lib.dir}/SecondLib.jar"/> 
    </manifest> 
</jar> 
+0

Ich habe meine build.xml-Datei bearbeitet, um dies widerzuspiegeln, aber ich bekomme immer noch den Fehler no main class. Aus welchem ​​Grund auch immer, es erkennt nicht die Hauptklasse, die ich definiert habe – ewok

+0

Hat Ihre Hauptklasse wirklich kein Paket? Denn das definiert 'Main-Class: HttpController'. –

+0

Ich werde den obigen Code aktualisieren. Ursprünglich hatte es kein Paket, aber ich habe ein Paket hinzugefügt und stoße immer noch auf das gleiche Problem – ewok

1

Dies ist eher eine allgemeine Lösung für die Herstellung von ausführbaren JAR-Dateien, aber das ist der Code, den ich verwenden:

<?xml version="1.0" encoding="UTF-8"?> 

<!-- 
    Any words or attribute values which are capitalized and separated by 
    underscores are places where you add the data. 

    Example: PROJECT_NAME, enter your project name 
--> 

<project name="PROJECT_NAME" default="jar" basedir="."> 
    <!-- source code package --> 
    <property name="src" value="SOURCE_CODE_FOLDER"/> 

    <!-- classes folder (will be deleted) --> 
    <property name="cls" value="classes"/> 

    <!-- the directory of the jar file --> 
    <property name="jar.dir" value="JAR_FILE_DIRECTORY"/> 

    <!-- the jar file itself --> 
    <property name="jar.file" value="${jar.dir}/${ant.project.name}-launch.jar"/> 

    <!-- the fully qualified name of the main class --> 
    <property name="main" value="PATH.TO.MAIN_CLASS"/> 

    <!-- initialization --> 
    <target name="-init"> 

     <!-- the class folder* --> 
     <mkdir dir="${cls}"/> 

     <!-- the jar directory --> 
     <mkdir dir="${jar.dir}"/> 
    </target> 

    <!-- compiling of files --> 
    <target name="-post-init-comp" depends="-init"> 

     <!-- 
      turn all of the source java classes into class files 
      located in the directory we made* 
     --> 
     <javac srcdir="${src}" destdir="${cls}"/> 
    </target> 

    <!-- creation of the jar file --> 
    <target name="jar" depends="-post-init-comp"> 

     <!-- make the executable jar --> 
     <jar destfile="${jar.file}" basedir="${cls}"> 
      <manifest> 

       <attribute name="Manifest-Version" value="1.0"/> 
       <attribute name="Ant-Version" value="Apache Ant 1.8.3"/> 

       <attribute name="Main-Class" value="${main}"/> 

       <!-- 
        for some reason, this is needed for me in order 
        to have the jar function right 
       --> 
       <attribute name="Class-Path" value="${main}"/> 

       <!-- Any other mainfest data is added here --> 

      </manifest> 
     </jar> 

     <!-- remove the class folder --> 
     <delete dir="${cls}"/> 
    </target> 
</project> 

ich diese Struktur verwendet habe viele verschiedene ausführbaren JAR-Dateien zu machen, und es ist einfacher als das, was Sie hatten :-)

Alle Daten in die Manifest-Tags unter den JAR-Tags wird eine automatisch generierte Manifest-Datei mit den angegebenen Daten.

Verwandte Themen