2011-12-01 73 views
3

我想使用亞馬遜機械土耳其語API構造一個jar文件。該SDK附帶了我想了罐子的完整性檢查一個HelloWorld文件 - 它位於:定義在捆綁一個罐子螞蟻主類的混亂

http://aws.amazon.com/code/SDKs/695

設置就緒後,我能夠使用Ant構建和執行正確地使用提供的build.xml文件。

bash-3.2$ ant helloworld 
ant helloworld 
Buildfile: /Users/astorer/Work/dtingley/java-aws-mturk-1.2.2/build.xml 

compile-sample: 
    [echo] Compiling the sample java source files... 
    [javac] /Users/astorer/Work/dtingley/java-aws-mturk-1.2.2/build.xml:252: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds 

helloworld: 
    [echo] Running the Hello World sample application... 
    [java] Got account balance: 10000.00 
    [java] Created HIT: 2RB2D5NQYN5F41KJ2IKYPNCW2H3A60 
    [java] You may see your HIT with HITTypeId '22R58B727M0IHQ4HZEXYISVF4XCWBC' here: 
    [java] http://workersandbox.mturk.com/mturk/preview?groupId=22R58B727M0IHQ4HZEXYISVF4XCWBC 
    [java] Success. 

BUILD SUCCESSFUL 
Total time: 11 seconds 

我希望helloworld可以由其他人執行而無需安裝庫。看起來這樣做的「正確」方法是從螞蟻內構建一個jar。

我的理解是,我需要包括:

  • 必要的庫,從SDK本身(和一個.jar提供)
  • 內置HelloWorld類文件
  • manifest屬性建立指定要運行的主類

我不知道是否需要包含任何其他內容。我知道在運行時有一個大的,複雜的類路徑,我可以在命令行上指定類路徑,但是我懷疑對類路徑進行硬編碼會阻止我分發.jar文件,這是整個點。

下面是罐子裏的build.xml片斷:

<target name="hellojar" depends="helloworld" description="Creates Jar of helloworld" > 
    <jar destfile="helloworld.jar"> 
     <fileset file="${sdk.jar}" /> 
     <fileset dir="${sample.classes.dir}/helloworld/" /> 
     <fileset dir="."/> 
     <manifest> 
     <attribute name="Main-Class" value="MTurkHelloWorld" /> 
     </manifest> 
    </jar> 
    </target> 

此建立。當我運行的罐子,但是它崩潰,:

bash-3.2$ java -jar helloworld.jar 
java -jar helloworld.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: MTurkHelloWorld (wrong name: helloworld/MTurkHelloWorld) 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) 
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 

這是有道理的,因爲我的MTurkHelloWorld實際上是在HelloWorld的包。因此,我應該更改爲:

<manifest> 
    <attribute name="Main-Class" value="helloworld.MTurkHelloWorld" /> 
    </manifest> 

這會成功建立。當我運行它:

bash-3.2$ java -jar helloworld.jar 
java -jar helloworld.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: helloworld/MTurkHelloWorld 
Caused by: java.lang.ClassNotFoundException: helloworld.MTurkHelloWorld 
    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:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 

,我們可以調查罐子中的文件:

jar tf helloworld.jar | grep hello 
build/private/classes/samples/helloworld/ 
samples/helloworld/ 
build/private/classes/samples/helloworld/MTurkHelloWorld.class 
samples/helloworld/MTurkHelloWorld.java 

這表明,也許如果classpath中被設定爲建立/私營/班/樣品/它會正常工作:

<attribute name="Class-Path" value="build/private/classes/samples/helloworld" /> 

這導致相同的錯誤。我認爲這裏有一些非常重要的東西,我很感激任何幫助!

回答

3

你的包文件夾必須直接開始,你不能把它們放在任何子目錄中的jar文件:

它必須看起來像這樣:

helloworld/ 
helloworld/MTurkHelloWorld.class 

jar-task將看起來像這樣:

<jar destfile="helloworld.jar" basedir="${sample.classes.dir}">> 
    <manifest> 
    <attribute name="Main-Class" value="MTurkHelloWorld" /> 
    </manifest> 
</jar> 

basedir是您的編譯軟件包的來源。 隨着<fileset />你只需添加普通文件。

此外,您不能將外部庫放入jar文件。它們必須與清單中的罐子,java classpathclasspath-attribute指定的文件夾位於同一個文件夾中。 或者您可以使用one jar task將這些類包含到您的jar中。

+0

您認爲在這種情況下最佳做法是什麼?要製作一個jar文件(使用一個jar文件),還是隻給出說明,讓大家自己安裝這個包並使ant任務運行? – alexplanation

+0

@alexplanation指令總是可能被誤讀。我建議(如果你直接給最終用戶)一個zip文件(包含所有內容,只需要解壓縮)。或者onejar方法。 – oers