как создать в комплекте исполняемый jar с помощью Ant - PullRequest
7 голосов
/ 26 марта 2012

Я посмотрел на этот вопрос , но это не решило мою проблему, поэтому я решил опубликовать новый.

Мне нужно создать исполняемый jar (запускаемый простым двойным щелчком) с использованием Ant. У меня есть следующий код Java и файл build.xml, который прекрасно компилирует код и создает файл JAR, но когда я пытаюсь запустить JAR с помощью двойного щелчка, я получаю сообщение «Не удалось найти основной класс: HttpController. Java. "

У меня есть подозрение, что моя проблема связана с загрузкой внешнего Apache Http.jar, так как я успешно собрал и запустил jar-файл для идентичного проекта, за исключением того, что он не ссылается ни на какие внешние jar-файлы.

Вот мой код:

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

РЕДАКТИРОВАТЬ build.xml был обновлен в соответствии с ответом Майка. Проблема до сих пор не решена. Также опубликовано содержимое файла манифеста, согласно ответу Danation.

Ответы [ 4 ]

17 голосов
/ 26 марта 2012

Снип ...

Я переработал ваш файл build.xml, чтобы правильно включить библиотеки в файл jar и в путь к классам Manifest. Я предполагаю, что ваш файл "apache http.jar" является оболочкой для Apache Core и содержит несколько других jar-файлов для клиента apache и т. Д.

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>
5 голосов
/ 26 марта 2012

Ваша запись Class-Path неверна, вы должны указать каждый файл jar отдельно, вы не можете указать каталог с файлами .jar (только каталоги с файлами .class)

Это задокументировано в Спецификация JAR-файла и довольно хорошо объяснена в руководстве по Java

Если у вас две библиотеки с именами FirstLib.jar и SeconLib.jar, ваша запись Class-Path должна выглядеть следующим образом:

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

Редактировать :Внутри вашего build.xml это будет выглядеть так:

<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>
1 голос
/ 05 апреля 2016

Это более общее решение для создания исполняемых jar-файлов, но я использую этот код:

<?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>

Я использовал эту структуру для создания множества различных исполняемых jar-файлов, плюс она прощечем то, что у вас было: -)

Все данные, помещенные в теги манифеста под тегами jar, станут автоматически сгенерированным файлом манифеста с данными.

0 голосов
/ 26 марта 2012

Взгляните на свой файл манифеста, скорее всего, это проблема там.Я видел эту ошибку только тогда, когда файл манифеста неверен.

Просто предположение, но я думаю, что он пытается запустить файл ".java" в качестве основного класса, который не будет работать.

См. Руководство к оракулу: http://docs.oracle.com/javase/tutorial/deployment/jar/appman.html.

Если это не поможет, опубликуйте содержимое файла манифеста, а также структуру каталогов файла .jar в исходном вопросе..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...