Fat Jarプラグインを使ってみた

Fat Jarというのは、依存する外部ライブラリをすべてまるまる一つのJarに入れておいたもの。Jarのサイズはかなりでかくなるが、他の人に渡すときにJar一つで実行できるので便利。Uber JarともOne-Jarとも言われる。

で、こちらを参考にFat Jar プラグインEclipseに導入してみた。


http://d.hatena.ne.jp/lime55/20100419/1271666741


動作確認に使ったプロジェクトはこちらの、複数ExcelGrepのように検索するというプロジェクト。


http://simultechnology.blendmix.jp/blog/archives/1272


Mavenで以下依存関係を読み込むようにしてある。

org.apache.loggin.log4jlog4j-api
javax.servletのjavax.servlet-api
javax.servletjsp-api
org.apache.commonsのcommons-lang3
org.apache.poiのpoi(3.9)
org.apache.poiのpoi-ooxml(3.9)

プロジェクトのトップから、Fat Jarのビルド、メインクラスを選んで、One-Jarにチェックを付ければfat-jarがビルドできます。これは、ちゃんと動いた。

一方で、Scalaのプロジェクトではなぜかうまく動作しないところがある。動きはするんだが、変なエラーがでる。ZIPファイルをどこかのフォルダに展開すること無く、格納されているテキストファイルの中身をずらずらっと表示する、というだけのものだが、ずらずらっと表示している途中でエラーがでる。

<?xml version="1.0" encoding="utf-8"?>
<ErrorSupportMessage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Messages>
    <anyType xsi:type="xsd:string">   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at DevExpress.XtraBars.BarItem.OnClick(BarItemLink link)
   at DevExpress.XtraBars.BarBaseButtonItem.OnClick(BarItemLink link)
   at DevExpress.XtraBars.BarItemLink.OnLinkClick()
   at DevExpress.XtraBars.BarItemLink.OnLinkAction(BarLinkAction action, Object actionArgs)
   at DevExpress.XtraBars.BarButtonItemLink.OnLinkAction(BarLinkAction action, Object actionArgs)
   at DevExpress.XtraBars.BarItemLink.OnLinkActionCore(BarLinkAction action, Object actionArgs)
   at DevExpress.XtraBars.ViewInfo.BarSelectionInfo.ClickLink(BarItemLink link)
   at DevExpress.XtraBars.ViewInfo.BarSelectionInfo.UnPressLink(BarItemLink link)
   at DevExpress.XtraBars.Controls.CustomLinksControl.OnMouseUp(MouseEventArgs e)
   at System.Windows.Forms.Control.WmMouseUp(Message&amp; m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message&amp; m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp; m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp; m)
   at System.Windows.Forms.NativeWindow.CalException in thread "main" java.lang.reflect.InvocationTargetException
(ここまではテキストファイルの中身で、以下Javaのエラー)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.simontuffs.onejar.Boot.run(Boot.java:306)
        at com.simontuffs.onejar.Boot.main(Boot.java:159)

ソースコードはこんな感じ。

import java.util.zip.{ZipEntry, ZipFile, ZipInputStream}
import java.io.{BufferedInputStream, FileInputStream, InputStream}

object Checker extends App {
	val z = new ZipOpener("c:\\temp\\hoge.zip")
	for (n <- z.getFiles) println(n)
	val is = z.getStream("Data.xml")
	scala.io.Source.fromInputStream(is)("UTF-8").foreach(print)
}


/**
 * @param zipfile zip形式で圧縮されたファイル
 */
class ZipOpener(zipfile:String) {
  val zi = new ZipIter(zipfile)
  val zf = new ZipFile(zipfile)
  
  def getFiles: List[String] = {
	{for (elem <- zi) yield elem.getName}.toList
  }
  
  /**
   * @param filename zipファイルに含まれるファイル名
   */
  def getStream(filename: String): InputStream = {
    zf.getInputStream(zf.getEntry(filename)) 
  }
}


/**
 * @param zipfile zip形式で圧縮されたファイル
 */
class ZipIter(zipfile: String) extends Iterator[ZipEntry] {
  private val zis = new ZipInputStream(new FileInputStream(zipfile))
  private var entry:ZipEntry = zis.getNextEntry
  private var cached = true
  private def cache {if (entry != null && !cached) {
	  cached = true; entry = zis.getNextEntry
  	}
  }
  def hasNext = { cache; entry != null }
  def next = { 
    if (!cached) cache
    cached = false
    entry
  }
}

(2013/12/2 16:52 追記)ここを参考に

http://stackoverflow.com/questions/1757272/how-to-resolve-java-nio-charset-unmappablecharacterexception-in-scala-2-8-0
http://d.hatena.ne.jp/xuwei/20101021/1287691097

scala.io.Source.fromInputStream(is).foreach(print)

scala.io.Source.fromInputStream(is)("UTF-8").foreach(print)


としたら動いた。エラーメッセージからピンと来ないよなあ。