カテゴリー「groovy/grails」の6件の記事

2011/05/07

NetBeans7上でJDK7を用いてEclipseと結果が異なっていたコンパイラの挙動を確認する

JDK7はこちらからダウンロードできる最新版(Build 141)を使用しました。なお、NetBeans7のリリースニュースで出ていた”JDK7デベロッパプレビュー版”というのはおそらくこちらのBuild 140ではないかと思いますので、若干バージョンが違います。

 

NetBeans実行に用いるJDKを変更するには、以前のエントリ

で記載しましたが、現在では日本語公式サイトにも方法が載っているようです。

NetBeansを起動しメニューから”ヘルプ”>”製品について”を選ぶと以下のような表示になりました。

製品バージョン: NetBeans IDE 7.0 (Build 201104080000)

Java: 1.7.0-ea; Java HotSpot(TM) 64-Bit Server VM 21.0-b11

システム: amd64 上で動作する Windows 7 バージョン 6.1; MS932; ja_JP (nb)

[追記: NetBeans7.0をJDK7eaで動作させると問題がいくつか出ました。ですのでこの設定で常用はしない方が良いでしょう。Java7を使用したいだけであれば上記の設定は不要です。]

また、プロジェクトをJava7でコンパイルするには、プロジェクトビューア(ウインドウ左上部にツリー表示されているやつですね)でプロジェクトを右クリックし”プロパティ”を選択するとプロジェクトプロパティーダイアログが開きますので”ソース”の”ソース/バイナリ形式”で”JDK7”を選択します。

[追記: 片貝さんのエントリにおいて図入りでより詳しく説明されています。]

 

さて何から試すか…取り敢えず私が昔エントリに書いたものを。

これはNetBeans7でも解消されていないですね…当初は6.9.1で修正予定、次に7で、とずれ込んでいったのですが、残念ながら今回も未修正のようです。続いてこちら。

よしよし、JDK7で正常に実行できました。…あれ?JDK6でもうまくいくぞ…?どうやらこれは6u18で修正されたようです(6548436:Incorrect inconvertible types error)

 

気を取り直して、以降、普通の業務系Javaプログラマなら必ず一度は罠にはまるEclipseコンパイラ(ECJというそうです)とOracle JDK6で差異があった部分がどうなったかを試してみます。問題の詳細はこちらでまとめている方がいらっしゃいましたので、そのエントリを参照してください。

 

『BOM付きUTF-8のjavaソースファイル』

BOM付きのテキストファイルはおそらくNetBeans単体では作れないと思うので、サクラエディタで保存したものを読み込ませてみたところやっぱり駄目でした。”エラー: \65279は不正な文字です”というエラーがでます。なお、NetBeansのエディタではBOMが見えてますので手で削除できました。

 

『アノテーションでの各要素の値で配列の最後にカンマ』

JDK7でコンパイル通りました。

 

『代入演算子での Integer 変数への Double 変数の加算』

Bug Databaseでは見つけられませんでしたが、下のbugの関連先でしょうかね?

ちなみに、double型(及びDouble型)からInteger型への変換が暗黙的には行えない、というのが問題の本質で、DoubleからのアンボクシングとIntegerへのボクシングを行ってもらえるよう、それぞれ明示的に型キャストしてあげればJDK6コンパイラに受け入れられるみたいです。

   1: Integer i = 1;
   2: Double d = 2.0D;
   3: i+=(int)(double)d;

確かにコンパイラがDoubleとint, doubleとIntegerの関係なんか知るか!って言いたい気持ちも分からなくはないですが、あんまりこんなコードは見たくないですね…

[追記: 元々の式は (int)+(double) だったのに対して上の式は (int)+(int) になっているので上の式は誤りですね。まあ、あくまでコンパイルを通すための手段の例示、ということで。]

JDK7では元のコードのままでコンパイルが通りました。これをJD-GUIでデコンパイルすると

Integer.valueOf((int)(localInteger.intValue() + localDouble.doubleValue()));

のような形になりました。Eclipseと一緒ですね。

 

『ジェネリックパラメータ』

最新のJDK6では修正されていました。6u22-revというバージョン表記が何を意味しているのか理解していないのですが、私のインストールしているJDKで確認したところ、6u20,6u21,6u22はNG、6u25はコンパイルOKでした。JDK7でももちろんOKです。

一番最初に記載したEnumの問題に次いでこれでよく引っかかってたのですが、そうか、JDK6を最新版にすれば大半は解消するんですね…

 

『拡張for文 (foreach文) のキャスト』

bugdatabaseと格闘する集中力が切れました…

JDK7では正常に実行終了します。JDK7でコンパイルしたものを先程と同じくJD-GUIで見てみると、

   1: for (Number localNumber : localArrayList2) {
   2:   System.out.print(localNumber);
   3:   System.out.println();
   4: }

あれ、拡張for文が展開されていないですね。仕方が無いのでjavap –v の出力結果をJDK6のものとJDK7のもので比べてみると、JDK6では

50:  checkcast       #11; //class java/lang/Double

となっているコメントが、JDK7では

50: checkcast     #11                 // class java/lang/Number

になっていました。

 

結論としては、Java7では目につくEclipseコンパイラとの動作差異は粗方無くなっていると見てよいのではないでしょうか。

2010/07/02

Grails1.3で標準出力が文字化けする原因について

以前、Grails1.2.1からGrails1.3.1(確認したところその後にリリースされたGrails1.3.2も同様でした)へバージョンアップした際に、Windowsのコマンドプロンプトに出力されるメッセージが化ける、という話題に触れました。

この直接の原因は、GRAILS-6123の対応において、grailsコマンドにデフォルトで-Dfile.encoding=utf-8が設定されるようになったことのようです。ただし、GRAILS-6123で報告されている問題は、Grails1.2.1では(-Dfile.encoding=utf-8を設定していないにもかかわらず)発生しないため、何か他の変更が影響した結果、このような対応を取らざるを得なくなったのではないかと考えます。

で、coroidにおける対応策なのですが、coroidではGRAILS-6123の問題が発生するような使い方はしていない(はず)なので、明示的にfile.encodingをシステムのものに合わせてやればよいです。Windowsであれば、

grails run-app –https –Dfile.encoding=MS932

というようなコマンドになります(–Dfile.encoding=MS932 を追加する)。

GRAILS-6123の本来の対応は、GRAILS-2177で追加したコンフィグgrails.views.gsp.encodingで制御すべきではないのかな、と思っているのですが、どうなんでしょうね…

2010/06/18

NetBeans6.9でgroovyファイルが含まれているとテスト実行できない

NetBeans6.9にアップグレードしたのですが、以前まで問題なかったJavaプロジェクトのJUnitテストが実行できなくなりました。エラーメッセージは以下の通り。

nbproject/build-impl.xml:725:
Unknown attributes [apgeneratedsrcdir, processorpath]

ちなみにバグレポートは既に挙がっているようです。Bug185686 - Adding groovy class to Java Project - bad ant file build-impl.xml

Subversionで管理していたプロジェクトでしたので、nbprojectディレクトリ以下をrevertしてアップグレード前に戻してだましだまし使用してきましたが、今回新規プロジェクトを作成したので昔のバージョンに戻すという手段が取れず、根本的な解決を探りました。

 

nbproject/groovy-build.xmlの中にある-groovy-init-macrodef-javacターゲットの記述が、自動生成されるJava側のAntファイル(nbproject/build-impl.xml)に追従できていないのが問題のようです。

エラーメッセージにある2つのattributeの宣言(これはbuild-imple.xmlの中にもあります)

<attribute default="${javac.processorpath}" name="processorpath"/>
<attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/>

を、groovy-build.xml中の

<macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">

の下あたりに挿入することで、エラーが出なくなりました。(注:この対策が本当に正しいのかどうかは、実のところ自信はありません)

[追記: 現在ではバグレポートに上記のことが書いてあります(どうも巡り巡ってこのエントリが英語文章化されたみたいなので、やっぱりこの回避策で良いのかは確信が持てませんが)。]

余談ですが、groovyで記述したテストケースをNetBeansで実行するには、Running Groovy tests in NetBeans 6.7.1というエントリが参考になります。

2010/03/28

Grailsでワーカスレッドを作ってそこからHibernateで永続化したい、んだけれど…

coroidでは、動画変換serviceを作って、そこで動画の処理を行っています。その中で、処理の経過を永続化しています。

class NicoContentService
    def transcode(){
        // (1)処理開始状態を永続化
        // (2)変換処理
        // (3)処理終了状態を永続化
    }
}

(2)が重たい処理なので、ワーカスレッドを作成し、処理完了を待たずに制御を戻すことにしました。

class NicoContentService
    def transcode(){
        Thread.start{
            // (1)処理開始状態を永続化
            // (2)変換処理
            // (3)処理終了状態を永続化
        }
    }
}

coroid ver.0.1.0まではこのような実装でした。これでGrails1.1.1ではうまく動いていたのですが、1.2.1にバージョンを上げるとこちらに書かれている通り、

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

という例外が出るようになりました。これは、Thread.startで作ったワーカスレッドがHibernateのセッションを持っていないので発生したのでしょう。1.1.1では、セッションが必要になればGrailsフレームワーク側で自動で取得していたのではないかと想像します。また、1.2.1でも、Grailsフレームワーク側を変更すればそのような動作にできるようです(参考)。Grailsの中で使用しているSpringFrameworkのHibernateTemplateクラスコンストラクタに渡す引数を変更する、という対応のようです。

coroidはGrailsを含めて配布しているわけではないので、上記の対応は採用できません。他の方法を探したところ、BackgroundThread pluginというものがありました。このプラグインの説明に以下のような記述がありましたので、問題を解消できるだろうと考えました。

Beyond the inherent difficulty of concurrent programming, Grails had a few other difficulties: most significantly, the Hibernate session is bound to the thread, and so threads need to do their own Hibernate session management. This plugin takes care of those issues.

このプラグインを用い、以下のようにソースを変更しました。これがcoroid ver.0.2.0です。

class NicoContentService
    def transcode(){
        backgroundService.execute("Working for converting",{
            // (1)処理開始状態を永続化
            // (2)変換処理
            // (3)処理終了状態を永続化
        })
    }
}

 

ここからが問題です。

こちらに記載した通り、次のバージョンでは処理の進捗率を表示させたいと考えています。この情報は、さきゅばすが通知するステータステキスト(さきゅばすをGUIで起動して変換処理を行ったとき、画面下部のステータスバーに表示される情報です)を加工して永続化すれば良いと考えました。

この通知は、さきゅばすが作成するワーカスレッドが行います。つまり、この処理を追加することで、backgroundServiceワーカスレッドとはまた別のスレッドでHibernateを利用する必要がでてきた、ということです。

backgroundThread pluginのソースコードBackgroundThreadManager.javaを見ると、Hibernateセッションを以下のように取り扱っていました。パッケージ名を見るにつけ、どうやらSpring Frameworkの機能を利用しているようです。

開始時(bind):

Session session = SessionFactoryUtils.getSession(sessionFactory, true);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));


終了時(unbind):

SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());

上記と同じようなコードを、さきゅばすのワーカスレッド永続化処理に追加してみたのですが、”(3)処理終了状態を永続化”のところで以下の例外が出ました。

ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect):

さて、これをどう解決すればよいやら。Springも絡んできそうな様相なのですが、さっぱり知らないし、というところです。

2009/11/14

ニコニコ動画のRSS一覧作成するGroovyスクリプト

 

最近全くGroovyを触っていなかったので、手慣らしにスクレイピングでニコニコ動画のRSS一覧を作成するスクリプトを書いてみた。[追記: 下のコードは古いので現在のニコニコ動画サービスには対応できていません。最新版はgithubに上げています。]

import org.cyberneko.html.parsers.SAXParser
 
def rankUrl = 'http://www.nicovideo.jp/ranking'
def kinds = ['総合':'fav', 'マイリスト':'mylist', '再生':'view', 'コメント':'res']
def spans = ['毎時':'hourly', 'デイリー':'daily', '週間':'weekly', '月間':'monthly', '合計':'total']
 
def rankHtml = new XmlSlurper(new SAXParser()).parse(rankUrl)
 
def groups = rankHtml.'BODY'.'DIV'.'DIV'.'TABLE'.'TR'.'TD'.'TABLE'.'TR'.'TH'.'A'
def groupMap = [:]
groups.each{groupMap[it.text()] = it.@href.toString().split('/')[6]}
//groupMap.each{println it.key + ', ' + it.value}
 
 
println '<HTML><BODY>'
 
for(kind in kinds){
    for(span in spans){
        println '<A HREF="' + rankUrl + '/' + kind.value + '/' + span.value + '/' + 'all' + '?rss=2.0">'
        println '' + 'カテゴリ合算' + ' - ' + kind.key + ' - ' + span.key + '</A><BR>'
    }
}
 
 
for(group in groupMap){
    def groupUrl = rankUrl + '/fav/daily/' + group.value
    def groupHtml = new XmlSlurper(new SAXParser()).parse(groupUrl)
    def categories = groupHtml.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'*'.'NOBR'.'A'
    def categoryMap = [:]
    categories.each{categoryMap[it.'DIV'.text()] = it.@href.toString().split('/')[6]}
    //    categoryMap.each{println it.key + ', ' + it.value}
 
 
    println '<P>'
    println '<H3>カテゴリグループ: ' + group.key + '</H3><BR>'
    for(category in categoryMap){
        for(kind in kinds){
            for(span in spans){
                println '<A HREF="' + rankUrl + '/' + kind.value + '/' + span.value + '/' + category.value + '?rss=2.0">'
                println '' + category.key + ' - ' + kind.key + ' - ' + span.key + '</A><BR>'
            }
        }
    }
    println '</P>'
}
println '</BODY></HTML>'

出力結果はこういう感じになる。

実行にはCyberNeko HTML Parserが必要。

2009/03/25

JAVA POWER TOOLS/GROOVY MAG

思い出しついでに。

Jolt Awardsのfinalistに選ばれていたこと、FEST-Swingのことが記載されていること、の2点の理由で、JAVA POWER TOOLSを購入した。

あまり事前に調べずに買ったせいで、届いたときの本の分厚さに驚いた。870ページほどあり、日本語版が出るとしたら上下巻に分かれるのでは、と思われる程。

内容の方は、やや期待外れ。目当てのFEST-Swingの記事については、Webサイトで開発者が書かれている記事ほぼそのままで、この書籍にしか載っていない情報、というものは無かった。

全体的に、プロダクトの機能紹介と、ある程度までのチュートリアル、という内容である。目次を見れば分かるとおり、名前くらいは聞いたことがあるメジャーなプロダクトが殆どであり、検索すれば日本語で解説されているサイトも多く存在する。英語が得意でない私のような人間にとっては、残念ながらあまりためになる書籍ではないと思う。

また、日本語訳が出たとしても、その頃には内容が陳腐化しているのでは、という懸念もある。

プロジェクトにここに載っているプロダクトを導入しようと考えている場合、上司に、書籍に載るくらいには有名なものである、という説得材料には使えそうだ。

2点目のGROOVY MAG。groovy言語の電子出版月刊雑誌であり、5ドルとリーズナブルである。ただ、内容が(少なくとも今のところ)充実しているとは言い難く、あまり薦められない。創刊されてからまだ半年ほど?のようなので今後に期待か。今であれば、Grailsの本家サイトと前回記載したGrails in Actionだけ購入しておけば良いのではないかと思う。

ちなみに、現在のGrails in Action、誤記がいくつかあるのでサポートフォーラムも覗いておいた方がよいだろう。

電子書籍を購入するのに当たって、PayPalを利用した。アメリカではネットオークション(eBay)等で発生する個人間の送金をこれで行うことが多いらしいが、日本でもこういったサービスは普及するのだろうか。

また、今回Googleが似たようなGoogle Checkoutというサービスを行っていることを初めて知った。Googleの無償サービスはかなり利用しているだけに、逆にこういった個人情報に深く関わるサービスは利用したくない、という意識が働くことに気付いた。

other sites

  • follow us in feedly
  • github
  • stackoverflow

ソフトウェアエンジニアとして影響を受けた書籍

  • Christain Bauer: HIBERNATE イン アクション

    Christain Bauer: HIBERNATE イン アクション
    理論と実践が双方とも素晴らしい製品であるHibernate。本書はそのプロダクトを書名に冠していますが、Hibernateを使うつもりがなく、ORマッピングの解説書として読むにしても十分な良書です。Second EditionとしてJava Persistence With Hibernateという書籍も出版されていますが、残念ながら現在のところ 和訳はされていません。-インアクションは2.xの、Java Persistence-は3.1の頃のものなので、最新版とはちょっと違うところもあることに注意。 (★★★★★)

  • アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版

    アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版
    クライアント/サーバシステムを構築する上で必要となる知識が総論されてます。Web技術者も、フレームワーク部分を開発するのであれば必読。 (★★★★★)

  • Joel Spolsky∥著: ジョエル・オン・ソフトウェア

    Joel Spolsky∥著: ジョエル・オン・ソフトウェア
    前述の書籍「ソフトウエア開発プロフェッショナル」をより砕いたもの、という感じでしょうか。 前書きではプログラマでなくSE向けの本のように書かれているが、プログラマが読んでも面白い本であると思われます。 SEになった新人(あるいはそういう会社に入る/入りたての人)にとっては、これからどういったことが仕事を遂行していく上で起こりえるのか、どのように考えて行なっていけばいいのか決定する助けになると思います。 元は″Joel on Software″というブログの記事で、web上でも一部日本語で読めます。 http://japanese.joelonsoftware.com/ (★★★)

  • ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか

    ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか
    問題解決(一昔前のの流行語で言うところの『ソリューション』)能力は、システムエンジニアのスキルとして備えるべきもののうちのひとつです。しかし、これは難しい。学校で出されるテストと違い、唯一の、(問題提出者が想定している)解を求めるだけが「問題解決」では無いからです。そもそも、何が問題なのか、それは本当に問題なのか、それは本当に解決すべき問題なのか、その問題解決方法は正しいのか、などを解決しなければ、「その解は正しいのか」に辿りつくことができません。この本の最も良いところのひとつは、本があまり厚くないこと。すぐに読めるし、何回も読み返す気になるでしょう。 (★★★★★)

  • スティーブ・マコネル: ソフトウエア開発プロフェッショナル

    スティーブ・マコネル: ソフトウエア開発プロフェッショナル
    コードコンプリートで有名なスティーブマコネルの著書。新人SEに読んで欲しい。個人として業界の中でどうあるべきか、組織としてどうあるべきか、SEのプロ意識とは?SEの心構え概論、といったところでしょうか。また、業界における資格の重要性についても説かれています。この業界では資格が特に軽んじられる傾向がありますが、この傾向はどんな弊害をもたらすのか、将来的にこの業界は資格に対してどのような姿勢で臨んでいくべきなのか。日経BP社では(他の出版社もだが)最近、似たような類いのあまり面白くない書籍が乱出版されていますが、この本は別格だと思うので安心して購入して欲しいと思います。 (★★★★★)

無料ブログはココログ