2012/07/06

Grailsでファイルアップロードするには

リファレンスに記載してあった。
http://grails.org/doc/latest/guide/theWebLayer.html#uploadingFiles

リファレンスのようにこんな感じで実装すればうまく動作した。

GSPに以下のようなタグを記述する。
Upload Form: <br />
    <g:uploadForm action="upload">
        <input type="file" name="myFile" />
        <input type="submit" />
    </g:uploadForm>
Controllerを以下のように実装する。
def upload() {
    def f = request.getFile('myFile')
    if (f.empty) {
        flash.message = 'file cannot be empty'
        render(view: 'uploadForm')
        return
    }
    f.transferTo(new File('/some/local/dir/myfile.txt'))
    response.sendError(200, 'Done')
}

Grailsのログ設定について

ここに詳しく掲載されていた。
http://grails.org/doc/latest/guide/single.html#logging


プロジェクトの作成時にConfig.groovyに以下のような設定がされているので、
あとは適切に設定すればいいみたい。
// log4j configuration
log4j = {
    // Example of changing the log pattern for the default console
    // appender:
    //
    //appenders {
    //    console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n')
    //}

    error   'org.codehaus.groovy.grails.web.servlet',  //  controllers
           'org.codehaus.groovy.grails.web.pages'     //  GSP,
           'org.codehaus.groovy.grails.web.sitemesh', //  layouts
           'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping
           'org.codehaus.groovy.grails.web.mapping', // URL mapping
           'org.codehaus.groovy.grails.commons', // core / classloading
           'org.codehaus.groovy.grails.plugins', // plugins
           'org.codehaus.groovy.grails.orm.hibernate', // hibernate integration
           'org.springframework',
           'org.hibernate',
           'net.sf.ehcache.hibernate'
}

2012/07/03

[Grails] validationエラー時のメッセージを変更するには

概要

Domainクラスに定義できる制約(validation)でエラーが発生すると以下のようなメッセージが出力されます。
[class jp.co.wave.dsam.Test]クラスのプロパティ[name]の空白は許可されません。
これだとユーザーに全然優しくないので、分かりやすいメッセージに変更する方法を照会します。

検証環境

項目内容
OSMac OS X 10.06
Grails2.0.4

内容

リファレンスの7.5節に変更する方法が記載されていました。 抜粋します。
If a constraint is violated Grails will by convention look for a message code of the form:

[Class Name].[Property Name].[Constraint Code]
In the case of the blank constraint this would be user.login.blank so you would need a message such as the following in your grails-app/i18n/messages.properties file:

user.login.blank=Your login name must be specified!
The class name is looked for both with and without a package, with the packaged version taking precedence. So for example, com.mycompany.myapp.User.login.blank will be used before user.login.blank. This allows for cases where your domain class message codes clash with a plugin's.

For a reference on what codes are for which constraints refer to the reference guide for each constraint.
Googleで翻訳してみますと、
制約が違反している場合は、Grailsは慣例により、フォームのメッセージコードを探します。
[Class Name].[Property Name].[Constraint Code]

このようなあなたのgrails-app/i18n/messages.propertiesファイルに次のようなメッセージが必要になりますので、空白の制約の場合、これはuser.login.blank次のようになります。

user.login.blank=Your login name must be specified!

クラス名が優先してパッケージ化されたバージョンでは、とと、パッケージなしの両方で検索されます。したがって、たとえば、com.mycompany.myapp.User.login.blankはuser.login.blank前に使用されます。これは、ドメインクラスのメッセージコードは、プラグインのと衝突例が可能になります。

制約は、それぞれの制約のためにリファレンスガイドを参照しているコードが何であるかに参考のため。


これを自分なりに読み解きますと、
validationでエラーが発生すると、
grails-app/i18n/messages.propertiesから、
[Class Name].[Property Name].[Constraint Code]
という形式のメッセージコードを探します。

独自に定義することにより、プラグインで表示するメッセージとと異なるメッセージを出力することができます。
試しにやってみると、追加したメッセージが出力されることを確認しました。

参考情報

7 Validation - Reference Documentation

最後に

2012/06/26

[Swing] JXTreeTableを試す

概要

JXTreeTableを試してみました

検証環境

項目内容
OSMac OS X Lion

実装例

以下を参考に実装してみました。 http://d.hatena.ne.jp/takezoe/20100111 これにボタンとか独自のレンダラとか設定する方法はあるのだろうか。 独自に作ったエディターやら、レンダラーを設定するだけでいいのか、機会があったら調べたい。

2012/06/19

POIでシート名を変更する

概要

Apache POIを使用してExcelのWorkBookのシート名を変更する簡単な例を紹介します。

検証環境

項目内容
OSMac OS X Lion
POI3.8

実装例

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.Workbook



class ChangeSheetName {



    publicstaticvoid main(String[] args) {

        

        File file = new File('test.xls')

        

        file.withInputStream {

            Workbook wb = new HSSFWorkbook(it)

            // 0番目のシートの名前を変更する

            wb.setSheetName(0, 'シート名を変更した')

            

            // 複製した結果を元ファイルに書き込む

            file.withOutputStream {

                wb.write(it)

            }

        }

    }

}

POIでシートを複製する

概要

Apache POIを使用してExcelのWorkBookのシートを複製する簡単な例を紹介します。

検証環境

項目内容
OSMac OS X Lion
POI3.8

実装例

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.Workbook

class CloneSheet {

    publicstaticvoid main(String[] args) {
        
        File file = new File('test.xls')
        
        file.withInputStream {
            Workbook wb = new HSSFWorkbook(it)
            // 0番目のシートを複製する
            wb.cloneSheet(0)
            
            // 複製した結果を元ファイルに書き込む
            file.withOutputStream {
                wb.write(it)
            }
        }
    }
}

2012/06/15

eclipseでGroupSessionの開発環境を構築する

概要

公式サイトに開発環境構築ガイドがあるのですが、思い切りはまりました。。。
試行錯誤の結果、環境構築することができたので、その方法についてのメモ。
※WTPで起動し、管理画面を操作できるところまで確認しました。

環境

項目内容
OSMac OS X Lion
JavaJava SE 7 (MacOS X Default)
eclipseEclipse Indigo(3.7)
TomcatTomcat6
GroupSession4.0.3(訳あって最新版ではないです)

下準備

・GroupSessionの入手
以下のURLから最新バージョンの「gsession_src.zip」をダウンロードします。
http://www.gs.sjts.co.jp/v4/download/index.html

ダウンロードが完了したら適当な場所に解凍します。

構築

公式サイトにあるEclipseでGroup Sessionの開発を行う方法を参考にやってみましたが、全然うまくいきませんでした。。。
Antのタスクを実行すると「BUILD SUCCESSFUL」とかなるのですが
WarningLogが出まくっているし、何が何やら。。。

そこで、以下のような手順を行い環境構築しました。

1.動的Webプロジェクトを作成します

2.WebContent直下に「gsession_src.zip」を解凍してできたファイルをコピーします

3.ソースフォルダを指定します
/gsession4/WebContent/WEB-INF/plugin直下にpluginがぎっしりあります。
それらを一つずつ開き、「src」フォルダがあれば、それを一つずつ指定していきます。
※数が多いので非常に時間がかかります。

なお、詳細な方法については、公式サイトで詳細に解説していましたので、
やり方が分からない場合、そちらを参考にして下さい。

やり終えるとこんな感じになるはずです。

4.ビルドパスを編集します
1.WEB-INF/libにある全てのJarをビルドパスに追加します。
2.WEB-INF/classesをクラスフォルダとしてビルドパスに追加します。
3.WEB-INF/plugin/licenseとmobileをクラスフォルダとしてビルドパスに追加します。

5.ビルドを実行します
Ctrl+Bでビルドを実行します。かなり時間がかかります。気長に待ちます。

6.ServersビューでTomcat6サーバを追加します。

7.追加したサーバに1で作成したプロジェクトを追加します。

8.サーバを起動します。
こんな感じのログが出力されます。
例外が発行されていなければ正常に動作していると思います。
--
2012/06/15 22:59:35 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: .:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
2012/06/15 22:59:35 org.apache.tomcat.util.digester.SetPropertiesRule begin
警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:gsession4' did not find a matching property.
2012/06/15 22:59:36 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8080 で初期化します
2012/06/15 22:59:36 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 1062 ms
2012/06/15 22:59:36 org.apache.catalina.core.StandardService start
情報: サービス Catalina を起動します
2012/06/15 22:59:36 org.apache.catalina.core.StandardEngine start
情報: Starting Servlet Engine: Apache Tomcat/6.0.35
log4j:WARN No appenders could be found for logger (jp.groupsession.v2.cmn.GroupSession).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
2012/06/15 22:59:46 org.apache.coyote.http11.Http11Protocol start
情報: Coyote HTTP/1.1を http-8080 で起動します
2012/06/15 22:59:46 org.apache.jk.common.ChannelSocket init
情報: JK: ajp13 listening on /0.0.0.0:8009
2012/06/15 22:59:46 org.apache.jk.server.JkMain start
情報: Jk running ID=0 time=0/64  config=null
2012/06/15 22:59:46 org.apache.catalina.startup.Catalina start
情報: Server startup in 10221 ms

--
正常に動作しているかブラウザで確認します。

うまく動作しているとこんな感じの画面が表示されるはずです。

2012/06/14

POIで新しいシートを追加する


概要

Apache POIを使用してExcelのWorkBookに新しいシートを追加する簡単な例を紹介します。

実装例

import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.ss.usermodel.Workbook

class AddNewSheet {

    public static void main(String[] args) {
        
        new File('test.xls').withInputStream {
            Workbook wb = new HSSFWorkbook(it)
            
            // シートを5つ追加する
            (0..<5).each {
                wb.createSheet()
            }
            
            wb.createSheet('てすと')
        }
    }
}

2012/06/13

Groovyでdbunit

概要

DBUnitを簡単に使う方法を探していたら、以下のページを見つけました。
http://d.hatena.ne.jp/kiy0taka/20100109/1262967959

上記はGrabを使い、必要なライブラリをロードしておりましたが、同じように試してみたけどうまくいかず。。。
何かたんねーんだろう。。。
そこで普通に必要ライブラリを入手し試してみました。

下準備


以下のライブラリを入手し、クラスパスに追加します。
・dbunit-2.4.8.jar
http://www.dbunit.org/
・slf4j-api-1.6.6.jar
・slf4j-jcl-1.6.6.jar
http://www.slf4j.org/
・mysql-connector-java-5.1.20-bin.jar
http://dev.mysql.com/downloads/connector/j/
※mysqlで試しました。
・commons-logging-1.1.1.jar
http://commons.apache.org/logging/

実装例

ほぼ参考にさせて頂いたサイトそのままですが。。。 こんな感じに実装しました。
package jp.co.indoor.test;

import org.dbunit.Assertion;
import org.dbunit.JdbcDatabaseTester;
import org.dbunit.dataset.xml.FlatXmlDataSet;

import groovy.sql.Sql;
import groovy.util.GroovyTestCase;
import groovy.xml.StreamingMarkupBuilder;

class DbUnitSampleTest extends GroovyTestCase {

    static {
        Sql.newInstance('jdbc:mysql://localhost:3306/test', '', '', 'com.mysql.jdbc.Driver').executeUpdate('delete from emp')
//        .execute(
//            """
//            CREATE TABLE emp (
//                empno INTEGER PRIMARY KEY,
//                ename VARCHAR(10),
//                job VARCHAR(9)
//            );
//        """)
    }
    
    JdbcDatabaseTester tester
    
    void setUp() {
        tester = new JdbcDatabaseTester('com.mysql.jdbc.Driver', 'jdbc:mysql://localhost:3306/test', '', '')
    }
    void test() {
        tester.dataSet = dataSet {
            emp empno:7369, ename:'SMITH', job:'CLERK'
            emp empno:7499, ename:'ALLEN', job:'SALESMAN'
            emp empno:7521, ename:'WARD', job:'SALESMAN'
        }
        
        tester.onSetup()

        assert 1 == Sql.newInstance('jdbc:mysql://localhost:3306/test', '', '', 'com.mysql.jdbc.Driver').executeUpdate('delete from emp where empno = 7499')

        Assertion.assertEquals dataSet {
            emp empno:7369, ename:'SMITH', job:'CLERK'
            emp empno:7521, ename:'WARD', job:'SALESMAN'
        }, tester.connection.createDataSet()
    }
    
    def dataSet(c) {
        new FlatXmlDataSet(new StringReader(new StreamingMarkupBuilder().bind{dataset c}.toString()))
    }
}

動かしたところ、普通に動きました。あっさりと。
なんか変なログは出ていますが。。。

6 13, 2012 12:35:18 午前 org.slf4j.impl.JCLLoggerAdapter warn
警告: Potential problem found: The configured data type factory 'class org.dbunit.dataset.datatype.DefaultDataTypeFactory' might cause problems with the current database 'MySQL' (e.g. some datatypes may not be supported properly). In rare cases you might see this message because the list of supported database products is incomplete (list=[derby]). If so please request a java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory, ensure that you override getValidDbProducts() to specify the supported database products.
6 13, 2012 12:35:18 午前 org.slf4j.impl.JCLLoggerAdapter warn
警告: Potential problem found: The configured data type factory 'class org.dbunit.dataset.datatype.DefaultDataTypeFactory' might cause problems with the current database 'MySQL' (e.g. some datatypes may not be supported properly). In rare cases you might see this message because the list of supported database products is incomplete (list=[derby]). If so please request a java-class update via the forums.If you are using your own IDataTypeFactory extending DefaultDataTypeFactory, ensure that you override getValidDbProducts() to specify the supported database products.

2012/06/12

POIでWorkbookを読み込む

概要

Apache POIを使用してExcelのWorkBookを読み込む簡単な例を紹介します。
Javaだと色々面倒なのでGroovyを使っています。

実装例

以下のようにすればWorkBookを読み込むことができます。
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;

class ReadWorkbook {

    public static void main(String[] args) {
        
        new File('test.xls').withInputStream {
            Workbook wb = new HSSFWorkbook(it)
            println wb.getSheetName(0) // 読み込めたかどうか、確認するためコンソールにシート名を出力しています
        }
    }
}

2012/06/10

POIでWorkbookを作成する

概要

Apache POIを使用してExcelのBookを作成する簡単な例を紹介します。
Javaだと色々面倒なのでGroovyを使っています。

下準備

POIのサイトからライブラリを入手します。
http://poi.apache.org/
※poi-bin-3.8-20120326.zipをダウンロードしました。

適当な場所に解凍して、以下のライブラリをクラスパスに通します。
poi-3.8-20120326.jar

実装例

簡単ですが、こんな感じで実装すれば空のWorkBookを作成することができます。 ※例外処理を書いていませんが。。
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

class StartUp {

    /**
     * エントリーポイント
     * @param args
     */
    public static void main(String[] args) {

        // WORKBOOKを作成する        
        Workbook workbook = new HSSFWorkbook()
        
        // シートを作成する
        Sheet sheet = workbook.createSheet()
        
        // WORKBOOKを保存する
        FileOutputStream out = new FileOutputStream("test.xls")
        workbook.write(out)
        out.close()
    }
}

2012/01/03

JTableのセルを活殺制御する方法について

JTableのセルを活殺制御する方法に関するメモ。

JTableのMouseListner、PropertyChangeListenerを以下のように実装したら何とかできた。

private void tbl_listPropertyChange(java.beans.PropertyChangeEvent evt) {                                        

        int row = tbl_list.getSelectedRow();
        if (row != -1) {
            for (int col = 1; col < tbl_list.getColumnCount(); col++) {
                Object val = tbl_list.getValueAt(row, col); // (1)
                TableCellEditor editor = tbl_list.getCellEditor(row, col); // (2)
                Component comp = editor.getTableCellEditorComponent(tbl_list, val, true, row, col); // (3)
                comp.setEnabled(!machineList.get(row).getDeleteFlag()); // (4)
            }
        }
    }

    private void tbl_listMouseClicked(java.awt.event.MouseEvent evt) {

        int row = tbl_list.rowAtPoint(evt.getPoint());
        int col = tbl_list.columnAtPoint(evt.getPoint());

        tbl_list.changeSelection(row, col, false, false); // 5)
    }
1)セルに設定されている値を取得する。
2)セルに設定されているエディターを取得する
3)エディターに設定されているコンポーネントを取得する。取得時に初期値として変更前の値を取得する
4)コンポーネントを活殺制御する。

5)マウスがクリックされた位置に確実にフォーカスを移動させる。
これをしないと編集中に別セルをダブルクリックした際に正常にフォーカス移動しない。

なお、セルにコンボボックスを使用する場合、DafaultCellEditorを以下のように初期化すること。

dCellEditor = new DefaultCellEditor(cmb_seizo_moto);
dCellEditor.setClickCountToStart(2); // (1)
(1)セルエディタの起動する回数を2回に変更する。