web-dev-qa-db-ja.com

Mavenなしで桟橋を起動する実行可能戦争ファイル

「実行可能」なwarファイル(Java -jar myWarFile.war)実行したWARファイルに含まれるwebappをホストするJetty Webサーバーを起動します。

私が見つけた ページ それは私が探しているものを作る方法を説明しています:

しかし、実行可能なjar(war)を作成することになっていると私が思う方法と一緒にそのアドバイスに従うことは機能しません。

次のようなマニフェストを持つWARファイルを作成するAntタスクがあります。

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 1.5.0_18-b02 (Sun Microsystems Inc.)
Main-Class: Start

WARファイルの内容は次のようになります。

> Start.class
> jsp
>   build.jsp 
> META-INF  
>   MANIFEST.MF
> WEB-INF
>   lib
>     jetty-6.1.22.jar
>     jetty-util.6.1.22.jar

WARファイルを実行しようとすると、エラーは次のようになります。

Exception in thread "main" Java.lang.NoClassDefFoundError: org/mortbay/jetty/Handler
Caused by: Java.lang.ClassNotFoundException: org.mortbay.jetty.Handler
        at Java.net.URLClassLoader$1.run(URLClassLoader.Java:202)
        at Java.security.AccessController.doPrivileged(Native Method)
        at Java.net.URLClassLoader.findClass(URLClassLoader.Java:190)
        at Java.lang.ClassLoader.loadClass(ClassLoader.Java:307)
        at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:301)
        at Java.lang.ClassLoader.loadClass(ClassLoader.Java:248)
Could not find the main class: Start. Program will exit.

ここには2つのエラーがあるようです。1つはJARファイルが見つからないと思われるエラー、もう1つはStartクラスが見つからないエラーです。

最初の問題を修正するために、Jetty JARファイルをWARファイルのベースに配置し、同じエラーを再試行しました。また、WEB-INF/lib/<specific-JAR-files>からClass-Pathマニフェストの属性。それもうまくいきませんでした。

誰が私が正しい/間違っているのか、この実行可能なWARファイルを起動して実行する方法についての洞察はありますか?

52
twilbrand

質問にある link は、必要なもののほとんどを提供します。ただし、それに加えていくつかのことが必要です。

Jettyの起動に必要なクラスファイルは、パッケージ化するときにwarファイルのルートに配置する必要があります。 Antを活用して、<war> ファイル。戦争のマニフェストファイルには、Main-Class属性は、サーバーを実行します。

手順は次のとおりです。

Jettyサーバークラスを作成します。

これはあなたが提供したリンクから適応されます。

package com.mycompany.myapp;

import Java.io.File;
import Java.net.URL;
import Java.security.ProtectionDomain;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppContext;

public final class EmbeddedJettyServer
{
    public static void main(String[] args) throws Exception
    {
        int port = Integer.parseInt(System.getProperty("port", "8080"));
        Server server = new Server(port);

        ProtectionDomain domain = EmbeddedJettyServer.class.getProtectionDomain();
        URL location = domain.getCodeSource().getLocation();

        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        webapp.setDescriptor(location.toExternalForm() + "/WEB-INF/web.xml");
        webapp.setServer(server);
        webapp.setWar(location.toExternalForm());

        // (Optional) Set the directory the war will extract to.
        // If not set, Java.io.tmpdir will be used, which can cause problems
        // if the temp directory gets cleaned periodically.
        // Your build scripts should remove this directory between deployments
        webapp.setTempDirectory(new File("/path/to/webapp-directory"));

        server.setHandler(webapp);
        server.start();
        server.join();
    }
}

ここで設定できるすべてを確認するには、 Jetty APIドキュメント をご覧ください。

Antで戦争を構築します。

これは、ステージングディレクトリを使用して必要なクラスファイルを戦争のルートに解凍し、戦争の実行時にアクセスできるようにします。

<target name="war" description="--> Creates self-executing war">
  <property name="staging.dir" location="${basedir}/staging"/>
  <property name="webapp.dir" location="${basedir}/src/webapp"/>

  <mkdir dir="${staging.dir}"/>

  <!-- assumes you have all of your war content (excluding classes and libraries) already structured in a directory called src/webapp -->
  <!-- e.g. -->
  <!-- src/webapp/index.html -->
  <!-- src/webapp/WEB-INF/web.xml -->
  <!-- src/webapp/WEB-INF/classes/my.properties -->
  <!-- etc ... -->
  <copy todir="${staging.dir}">
    <fileset dir="${webapp.dir}" includes="**/*"/>
  </copy>

  <unjar dest="${staging.dir}">
    <!-- you'll have to locate these jars or appropriate versions; note that these include JSP support -->
    <!-- you might find some of them in the downloaded Jetty .tgz -->
    <fileset dir="path/to/jetty/jars">
      <include name="ant-1.6.5.jar"/>
      <include name="core-3.1.1.jar"/>
      <include name="jetty-6.1.24.jar"/>
      <include name="jsp-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary -->
      <include name="jsp-api-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary -->
      <include name="servlet-api-2.5-20081211.jar"/><!-- your Servlet API implementation may vary -->
    </fileset>
    <patternset><!-- to exclude some of the stuff we don't really need -->
      <exclude name="META-INF/**/*"/>
      <exclude name="images/**/*"/>
      <exclude name=".options"/>
      <exclude name="about.html"/>
      <exclude name="jdtCompilerAdapter.jar"/>
      <exclude name="plugin*"/>
    </patternset>
  </unjar>

  <!-- copy in the class file built from the above EmbeddedJettyServer.Java -->
  <copy todir="${staging.dir}">
    <fileset dir="path/to/classes/dir" includes="com/mycompany/myapp/EmbeddedJettyServer.class"/>
  </copy>

  <war destfile="myapp.war" webxml="${webapp.dir}/WEB-INF/web.xml">
    <fileset dir="${staging.dir}" includes="**/*"/>
    <classes dir="path/to/classes/dir"/><!-- your application classes -->
    <lib dir="path/to/lib/dir"/><!-- application dependency jars -->
    <manifest>
      <!-- add the Main-Class attribute that will execute our server class -->
      <attribute name="Main-Class" value="com.mycompany.myapp.EmbeddedJettyServer"/>
    </manifest>
  </war>

  <delete dir="${staging.dir}"/>
</target>

戦争を実行する:

上記がすべて適切に設定されていれば、次のことができるはずです。

Java -jar myapp.war

// or if you want to configure the port (since we are using the System property in the code)

Java -Dport=8443 -jar myapp.war
50
Rob Hruska

これは、@ RobHruskaの回答のMavenへの適応です。メインクラスのファイルをコピーし、Jetty JARファイルをWARファイルにマージします。新しいものは何もありません。Mavenを初めて使用する場合は、人生を単純化するためだけに使用します。

<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>move-main-class</id>
            <phase>compile</phase>
            <configuration>
                <tasks>
                    <copy todir="${project.build.directory}/${project.build.finalName}">
                        <fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/classes/">
                            <include name="main/*.class" />
                        </fileset>
                    </copy>

                    <unjar dest="${project.build.directory}/${project.build.finalName}">
                        <!-- you'll have to locate these jars or appropriate versions; note that these include JSP support -->
                        <!-- you might find some of them in the downloaded Jetty .tgz -->
                        <fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/lib/">
                            <include name="ant-1.6.5.jar"/>
                            <!--<include name="core-3.1.1.jar"/>-->
                            <include name="jetty*"/>
                            <include name="servlet-api*"/>
                        </fileset>

                        <patternset><!-- to exclude some of the stuff we don't really need -->
                            <exclude name="META-INF/**/*"/>
                            <exclude name="images/**/*"/>
                            <exclude name=".options"/>
                            <exclude name="about.html"/>
                            <exclude name="jdtCompilerAdapter.jar"/>
                            <exclude name="plugin*"/>
                        </patternset>
                    </unjar>
                </tasks>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin> 
<plugin>
    <groupId>org.Apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <archiveClasses>true</archiveClasses>
        <archive>
            <manifest>
                <mainClass>main.Main</mainClass> 
            </manifest>
        </archive>
    </configuration>
</plugin>
45
AhHatem

Jetty-console-maven-pluginを使用してこれを把握しました。

Mvn packageを実行すると、Java -jar whateverpackage-runnable.warで使用できる別のwarが作成されます

        <plugin>
            <groupId>org.simplericity.jettyconsole</groupId>
            <artifactId>jetty-console-maven-plugin</artifactId>
            <version>1.45</version>
            <executions>
                <execution>
                    <goals>
                        <goal>createconsole</goal>
                    </goals>
                </execution>
            </executions>

            <configuration>
                <additionalDependencies>
                    <additionalDependency>
                        <artifactId>jetty-console-requestlog-plugin</artifactId>
                    </additionalDependency>
                    <additionalDependency>
                        <artifactId>jetty-console-gzip-plugin</artifactId>
                    </additionalDependency>
                    <additionalDependency>
                        <artifactId>jetty-console-ajp-plugin</artifactId>
                    </additionalDependency>
                    <additionalDependency>
                        <artifactId>jetty-console-startstop-plugin</artifactId>
                    </additionalDependency>
                </additionalDependencies>
            </configuration>
        </plugin>

また、init.dスクリプトとすべてを生成します!

14
Rafael Sanches

Hudsonは、このユースケースを直接サポートするWinstoneサーブレットコンテナを使用して、この正確な問題を解決します。 http://winstone.sourceforge.net/#embedding

おそらくこれはあなたのために働くでしょうか?

これは一種の古いものですが、Jetty 8の別の代替方法は、Jetty jarをpomに依存関係として単純に含め、pomに以下を追加することです(戦争をアンパッケージして再パッケージ化するantスクリプトとは異なります):

            <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <transformers>
                            <transformer
                                implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>JettyStandaloneMain</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- The main class needs to be in the root of the war in order to be 
            runnable -->
        <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <executions>
                <execution>
                    <id>move-main-class</id>
                    <phase>compile</phase>
                    <configuration>
                        <tasks>
                            <move todir="${project.build.directory}/${project.build.finalName}">
                                <fileset dir="${project.build.directory}/classes/">
                                    <include name="JettyStandaloneMain.class" />
                                </fileset>
                            </move>
                        </tasks>
                    </configuration>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
6
Rodney Beede

「mavenなし」では、「mvn jetty:run」ではなく、自分で実行できるjarが必要だと思います。mavenをまったく使用したくないというわけではありません。

多くのオプションが見つかりましたが、どれも簡単ではありませんでしたので、これを理解するのに長い時間がかかりました。最終的に私は シンプルさからこのmavenプラグイン を見つけました。それは素晴らしく機能します。

3
schmmd

これは、私のANT抽出の例です。その考えは、Jetty依存関係をアンパッケージし、通常のJARファイルのようにローカルに含めることです。

<!-- Hack: Java doesn't support jars within jars/wars -->
<unjar src="${lib.dir}/container/jetty.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/jetty-util.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/servlet-api.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/jsp-api.jar" dest="${build.dir}/unjar"/>

<!-- Build war file as normal, just including the compiled and unjar'ed files -->
<war destfile="${war.file}" webxml="${config.dir}/web.xml">
    <fileset dir="${build.dir}/classes"/>
    <fileset dir="${build.dir}/unjar"/>
    <fileset dir="${resources.dir}" excludes="*.swp"/>
    <lib dir="${lib.dir}/runtime"/>
    <manifest>
        <attribute name="Main-Class" value="Start"/>
    </manifest>
</war>

注:

WEB-INF/libディレクトリは、Webアプリケーションの依存関係用です。この場合、起動時に通常のJetty JARファイルのように動作するようにWARファイルをパッケージ化します

1
Mark O'Connor

以前にも同様のことをしましたが、アプリを「Java -jar xxx.war」として起動しますか? jarファイルは2つしかなく、それだけでは不十分だと思います。また、Jetty 7.0.0M1(最新バージョン)を使用してみてください。 jetty-serverとjetty-webappを2つの依存関係(org.Eclipse.jettyからのもの)として追加すると、libディレクトリに次のjarが含まれます。参考までに、org.mortbay.jetty.Handlerはjetty-server * .jarにありました。

  • jetty-continuation-7.0.0.M1.jar
  • jetty-http-7.0.0.M1.jar
  • jetty-io-7.0.0.M1.jar
  • jetty-security-7.0.0.M1.jar
  • jetty-server-7.0.0.M1.jar
  • jetty-servlet-7.0.0.M1.jar
  • jetty-util-7.0.0.M1.jar
  • jetty-webapp-7.0.0.M1.jar
  • jetty-xml-7.0.0.M1.jar
0
Kannan Ekanath
  • .jarファイルを.warファイルルート内に配置しても何も起こりません
  • .jarをWEB-INF/lib内に配置しても、JVMがJettyファイルを見つけて.warの起動を開始することはできません。そこに置くのは「遅すぎる」。
  • .jarをマニフェストClass-Pathに入れることは、外部.jarファイルに対してのみ機能し、.jarに含まれるファイルに対しては機能しません。

じゃあ何をすればいいの?

  • ビルドスクリプトを使用して、必要なすべての.jarファイルを.warファイルに単純にマージします。これには少し余分な作業が必要です。また、コンパイルされたコードが.war内のサービス可能なファイルの一部であるという点で少しいです。
  • 「Java -cp jetty.jar:... ...」を使用して、JVMのクラスパスに依存する.jarを追加する
0
Sean Owen