2009年11月23日月曜日

maven2を使ってScalaのHello Worldを書いてみた

先日@yuroyoro氏により開催されましたScala Hackathon #1に行ってきました。Scalaは初めてだったので、ハッカソン資料に従ってまずはHello Worldから作ってみました。資料によると、
  • インタラクティブコンソールを使う
  • Eclipseのプラグインを使う非推奨
  • NetBeansのプラグインを使う
  • IntelliJ IDEAのプラグインを使う
  • テキストエディタとMavenとmaven-scala-toolsを使う
  • テキストエディタとsbt(Simple build Tool)を使う
これだけの開発手法を選択することが出来るそうです。そこであえて私はMaven2を使ってScalaのHello Worldを書いてみることにしました。

参考にした資料はこちら。
http://dl.dropbox.com/u/261418/scala-hackathon/setup.html#maven2
参考にしたページはこちら。
http://scala-tools.org/mvnsites/maven-scala-plugin/plugin-info.html
http://scala-tools.org/mvnsites/maven-scala-plugin/usage_run.html


■まずはmvnプロジェクトを作る
基本的には資料に記載されている内容と全く同じです。次の殺人的に長いmvnコマンドを入力するだけでプロジェクトを作ってくれます。
mvn org.apache.maven.plugins:maven-archetype-plugin:1.0-alpha-7:create \
-DarchetypeGroupId=org.scala-tools.archetypes \
-DarchetypeArtifactId=scala-archetype-simple \
-DarchetypeVersion=1.2 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=scalahackathon.helloworld -DartifactId=scalahackathon.helloworld
ただし、このコマンドによって生成されたデフォルトのScalaプロジェクトではそのままビルド結果を実行することができません。多少不備があります。後ほど詳しく説明します。とりあえずビルドとテストはできるので後回しにします。


■Appクラスを書かなくちゃ始まらない
生成されたデフォルトのScalaプロジェクトにあるAppクラスを書きます。このAppクラスと言う奴が、いわゆるJavaでいうmain関数を持ったメインクラスの扱いになってるみたいです。
akisute scalahackathon.helloworld$ cd src/main/scala/scalahackathon/helloworld 
akisute helloworld$ vim App.scala
package scalahackathon.helloworld

/**
* Hello world!
*
*/
object App extends Application {
println("Hello World!");
val l = List(1, 2, 3, 4, 5, 6);
l.foreach(println(_));
}
Applicationを拡張したAppクラスの中身が、そのままmain関数相当になるみたいです。このあたりよく分かってませんが、Appクラスの中で再度main関数を定義すると思いっきり怒られるのできっとそうなんだと思います。


■さて実行、その前に
さてここで
mvn scala:run
を実行すればプロジェクトをビルドして実行してくれるのですが、実は先ほど申し上げましたようにこのままではビルドには成功しますが実行に失敗します。原因はメインクラスがpom.xmlで定義されていないためです。
実行するためには、以下のように直接メインクラスを指定するか、
mvn scala:run -DmainClass=scalahackathon.helloworld.App
または以下のようにpom.xmlを修正してから実行する必要があります。毎回毎回直接メインクラスを指定するのは骨が折れるので、pom.xmlを直してみましょう。
<!-- reportingの中を直す、build要素はそのままでよい -->
<reporting>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<configuration>
<scalaVersion>${scala.version}</scalaVersion>
<!-- このlaunchers要素を新規に作る。idとmainClassは必須。 -->
<launchers>
<launcher>
<id>app</id>
<mainClass>scalahackathon.helloworld.App</mainClass>
<!-- 以下、任意要素。 args と jvmArgs を指定できます。 -->
<!--
<args>
<arg>arg1</arg>
</args>
<jvmArgs>
<jvmArg>-Xmx128m</jvmArg>
<jvmArg>-Djava.library.path=...</jvmArg>
</jvmArgs>
-->
</launcher>
</launchers>
</configuration>
</plugin>
</plugins>
</reporting>
修正してからmvn scala:runを実行すると、長い長いjarダウンロードの末、以下のような結果が得られます。
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'scala'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Unnamed - scalahackathon.helloworld:scalahackathon.helloworld:jar:1.0-SNAPSHOT
[INFO] task-segment: [scala:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing scala:run
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:compile {execution: default}]
[INFO] Checking for multiple versions of scala
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:testCompile {execution: default}]
[INFO] Checking for multiple versions of scala
[INFO] Nothing to compile - all classes are up to date
[INFO] [scala:run]
[INFO] Checking for multiple versions of scala
[INFO] launcher 'app' selected => scalahackathon.helloworld.App
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Hello World!
1
2
3
4
5
6
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Mon Nov 23 20:59:51 JST 2009
[INFO] Final Memory: 18M/79M
[INFO] ------------------------------------------------------------------------
うまくいったみたいですね。

Mac OS Xには最初から/usr/share以下にmaven2やantが付いてくる

先日のScala Hackathon #1にて初めて気づいた驚愕の事実。なんとMac OS Xには最初からJavaの開発ツールが付いてきていたのでした。
akisute ~$ mvn --version
Maven version: 2.0.9
Java version: 1.6.0_15
OS name: "mac os x" version: "10.6.2" arch: "x86_64" Family: "mac"
akisute ~$ ant -version
Apache Ant version 1.7.0 compiled on July 20 2009
akisute ~$ which mvn
/usr/bin/mvn
akisute ~$ which ant
/usr/bin/ant
ちょっとmaven2のバージョンが古いですが、普通に使う分にはたぶん問題なさそうです。ちなみにこれらのツールは/usr/share以下に用意されています。
akisute ~$ cd /usr/share
akisute share$ ls
NotificationServer/ distcc_compilers info/ sandbox/
Ssh.bin doc/ java/ screen/
TargetConfigs/ emacs/ junit/ sdef/
aclocal/ enscript/ langid/ servermgrd/
aclocal-1.10/ examples/ libiodbc/ skel/
ant/ file/ libtool/ snmp/
apr-1/ ftpd/ locale/ statsCollector/
autoconf/ gdb/ man/ swig/
automake-1.10/ germantok/ maven@ tabset/
bakefile/ gprof.callg mecab/ tcsh/
bison/ gprof.flat misc/ terminfo/
caldavd/ groff/ mk/ texi2html/
calendar/ gtk-doc/ openmpi/ texinfo/
cracklib/ gutenprint/ openmpi-default-hostfile uucp/
cups/ heapdiff/ openmpi-mca-params.conf vim/
cvs/ hiutil/ openmpi-totalview.tcl xcode-select/
derby/ httpd/ podcastproducer/ zoneinfo/
dict/ icu/ ri@ zsh/
おお、他にもderbyとかありますね。TomcatやJettyのようなサーブレットコンテナがないので、そのまますぐにWebアプリ開発とはいきませんが、なかなか面白そうです。

・・・む、ひょっとしてこれ常識ですか? ><

2009年11月8日日曜日

表示専用のカレンダーJSが欲しい

日付を選択するためのカレンダーJSはよく見るのですが、表示に特化したものは余り見ないので。たとえばこんな感じでjQueryのプラグインみたいに使えるカレンダーが欲しいのです。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Calendar object test</title>
<script type="text/javascript" src="js/jquery-1.2.6.min.js" type="text/javascript"></script>
<script type="text/javascript" >
$(function(){
// add a new text and set its style
$("calendar")
.from(2009, 10, 30)
.to(2009, 10, 31)
.text("Halloween")
.color("#ffcccc")
.style("bold")
.backgroundcolor("#ffddcc");
});

// calendar event handling
// use customized Event object which has "day" and "from, to" attr
$("calendar").click(function(e){
day = e.day
this.day(day).text("clicked")
});
$("calendar").select(function(e){
from = e.from
to = e.to
this.from(from).to(to).text("selected")
});
</script>
</head>
<body>
<div id="calendar">Calendar will be shown here</div>
</body>
</html>
どうでしょ?探せばあると思うのですが・・・