Home > Java

Java Archive

TeedaのラジオボタンにString型ではなく列挙型(Enum)を使う

Teedaのラジオボタンは通常、String型でPageクラスに定義します。
http://teeda.seasar.org/ja/extension/reverse/input.html#%E3%83%A9%E3%82%B8%E3%82%AA%E3%83%9C%E3%82%BF%E3%83%B3_%E9%9D%99%E7%9A%84
が、そこを列挙型(Enum)することができます。こちらの方が型安全になっていいかなと思います。
もちろん、静的・動的両方いけます。

以下、サンプルです。

HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:te="http://www.seasar.org/teeda/extension" xml:lang="ja"
    lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Enumのサンプル</title>
</head>
<body>
<form id="Form">
<span id="allMessages"></span>

<h1>ラジオボタン(静的)</h1>
<div id="sex">
    <label><input type="radio" name="sex" value="MALE" />男性</label>
    <label><input type="radio" name="sex" value="FEMALE" />女性</label>
</div>

<h1>ラジオボタン(動的)</h1>
<input type="hidden" id="languageItemsSave" />
<span id="language">
    <input type="radio" name="language" />
</span>

<p><input type="submit" value="送信" id="doSubmit" /></p>

</form>
</body>
</html>

列挙型

public enum Sex {
    MALE("男性"),
    FEMALE("女性");

    private String japaneseName;

    private Sex(String japaneseName) {
        this.japaneseName = japaneseName;
    }

    public String getJapaneseName() {
        return japaneseName;
    }
}
public enum Language {

    JAPANESE("日本語", "JAPANESE", "こんにちわ"),
    ENGLISH("英語", "ENGLISH", "Hello");

    private String label;
    private String value;
    private String greeting;

    private Language(String label, String value, String greeting) {
        this.label = label;
        this.value = value;
        this.greeting = greeting;
    }

    public String getLabel() {
        return label;
    }

    public String getValue() {
        return value;
    }

    public String getGreeting() {
        return greeting;
    }
}

Pageクラス

public class EnumSamplePage {

    public Sex sex;

    public Language language;
    public List<Language> languageItems;

    public Class<?> initialize() {
        // 初期値の設定
        sex = Sex.FEMALE;
        language = Language.ENGLISH;

        languageItems = new ArrayList<Language>();
        for (Language lang : Language.values()) {
            languageItems.add(lang);
        }

        return null;
    }

    public Class<?> prerender() {
        return null;
    }

    public Class<?> doSubmit() {
        System.out.println(sex.getJapaneseName());
        System.out.println(language.getGreeting());
        return null;
    }
}

注意としては、
静的なラジオボタンで使う場合は、value属性に“列挙子”を指定すること(サンプルだと「MALE」「FEMALE」)
静的なラジオボタンで使う場合は、列挙型のフィールドに“label”“value”を変数名にもつ値を定義すること。
あと、HTMLにhidden属性に”~~ItemsSave”を配置すること。これをしないとPOSTしたときにデータが消えてしまう(これはString型でも同じですが)

livedoor Reader をJavaから操作する何か作った

  • Posted by: sinsengumi
  • 2011年2月21日 12:21 AM
  • Java
  • |

追記
Github にホスティングしました。これからはGithub 使います。
https://github.com/sinsengumi/LDR4J

掲題の通り、livedoor Reader をJavaからHTTPアクセスして未読記事取ったり、ピン付けたりするライブラリ「ldr4j」を作りました。
実はAndroidでlivedoor Readerクライアントアプリを作りたくて、その前段階としてこのラッパーライブラリを作った感じです。

で、生まれてはじめて、まとまったコードをOSSとして公開してみました。
コードはSourceForge.JPでホスティングしています。
(eclipseプラグインのEGITがよさそうであれば、githubでホスティングしたいと思います。)

「ldr4j」プロジェクトページ

http://sourceforge.jp/projects/ldr4j/

以下で、Subversionからチェックアウトできます。
http://svn.sourceforge.jp/svnroot/ldr4j/

※なお、livedoor Reader API はlivedoor から正式にアナウンスされているAPIではないので、仕様変更で使えなくなる可能性はあります。

livedoor Reader が大好きで、もうこれがないとネット生活していけないくらいですね。
今回 ldr4j を作っていく過程で、livedoor Reader がどういう風に出来ているかもなんとなくですがわかりました(livedoor ReaderのOSS版である fastladder を参考にしました。)

このライブラリはこれからもちゃんとメンテナンスしていこー。テストとかもちゃんと書きたいし。

参考

よく見るClosable使ったコード

  • Posted by: sinsengumi
  • 2011年2月16日 8:23 PM
  • Java

Streamなんかを閉じる(close)時のコードなんかでよく見るパターン。
nullチェックして、closeする。さらにそのcloseはチェック例外出すからめんどいよ、ってことなのかしら。
結構有名なのかな?

private void close(Closeable stream) {
    if (stream != null) {
        try {
            stream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

JavaでFTPアップロードを行う。

  • Posted by: sinsengumi
  • 2011年2月1日 9:00 PM
  • Java
  • |

JavaでFTPを使用するにはいくらか方法がありますが、仕事でcommons-netのFTPを使ったのでその備忘録です。

実行環境は以下です。

  • JRE 1.6
  • commons-net-2.0.jar

はまった箇所が2点ほどあって、ひとつはエンコーディングの設定は必ずコネクトする前に行うこと。とPASVモードについてです。

commons-netのFTPClientクラスで、PASVモードにできそうな名前のメソッドが2つあって、それのどっちを使えばいいのか、もしくは違うのか結構悩みました。

  • enterLocalPassiveMode()
  • enterRemotePassiveMode()

結果的にいうと、どっちも違くて、FTPClientの親クラスであるFTPクラスのpasv()メソッドでOKでした。
これらの違いは、ソースやJavadocを見た感じ、恐らく以下のような感じだと思います。

pasv()

FTPのPASVコマンドを発行する。

enterLocalPassiveMode()

dataConnectionModeを「2」に設定する。

enterRemotePassiveMode()

内部的にpasv()を呼び出している。

以下、サンプルコードです。

public class FTPUpload {

    private static final String FTP_HOST = "127.0.0.1";
    private static final String FTP_USER = "username";
    private static final String FTP_PASSWORD = "password";

    private static final String UPLOAD_FILE = "C:\\サンプル.xls";
    private static final String UPLOADED_FILENAME = "リネーム.xls";

    public static void main(String[] args) {
        try {
            execute();
        } catch (ApplicationException e) {
            e.printStackTrace();
        }
    }

    private static void execute() throws ApplicationException {

        FTPClient ftpClient = new FTPClient();

        try {
            // エンコーディングの設定は、connectする前に行う。
            ftpClient.setControlEncoding("SJIS");

            // FTPサーバに接続
            ftpClient.connect(FTP_HOST);
            printFtpReply(ftpClient);

            // ログイン
            ftpClient.login(FTP_USER, FTP_PASSWORD);
            printFtpReply(ftpClient);

            // PASVモードに設定
            ftpClient.pasv();
            printFtpReply(ftpClient);

            // データの変換モードをバイナリに設定
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            printFtpReply(ftpClient);

            // ファイル転送
            FileInputStream fis = new FileInputStream(UPLOAD_FILE);
            ftpClient.storeFile(UPLOADED_FILENAME, fis);
            printFtpReply(ftpClient);

        } catch (NumberFormatException e) {
            throw new ApplicationException("FTPポートの値が数値ではありません。", e);
        } catch (SocketException e) {
            throw new ApplicationException("Socket通信に失敗しました。", e);
        } catch (FileNotFoundException e) {
            throw new ApplicationException("アップロードするファイルが見つかりません。", e);
        } catch (IOException e) {
            throw new ApplicationException("IOレベルで例外が発生しました。", e);
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    private static void printFtpReply(FTPClient ftpClient)throws ApplicationException {

        System.out.print(ftpClient.getReplyString());

        int replyCode = ftpClient.getReplyCode();

        if (!FTPReply.isPositiveCompletion(replyCode)) {
            throw new ApplicationException("送信したFTPコマンドは失敗しました。");
        }
    }
}

PASVモードやFTPのプロトコルに関しては、以下が大変参考になりました。
http://www.atmarkit.co.jp/fnetwork/rensai/netpro10/netpro01.html

Teedaでcolspanする

Teedaでcolspanするにはダイナミックプロパティを利用すればできます。

colspan.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:te="http://www.seasar.org/teeda/extension" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Teedaでcolspan</title>
</head>
<body>

<form id="Form">
<table border="1">
	<tr>
		<th>OS名</th>
		<th id="versionColspan" colspan="1">バージョン</th>
	</tr>
	<tr>
		<td><span id="osName">dummy</span></td>
		<div id="versionItems">
		<td><span id="codeName">dummy</span><br /><span id="number">dummy</span></td>
		</div>
	</tr>
</table>
</form>

</body>
</html>

ColspanPage.java

package org.sample.web.fnc;

import java.util.ArrayList;
import java.util.List;

public class ColspanPage {

	public int versionColspan;

	public List<VersionDto> versionItems;
	public String codeName;
	public String number;

	public String osName;

	public Class<?> initialize() {
		return null;
	}

	public Class<?> prerender() {
		osName = "Mac";

		// Macのバージョン
		versionItems = new ArrayList<ColspanPage.VersionDto>();

		VersionDto mac1 = new VersionDto();
		mac1.number = "10.3";
		mac1.codeName = "Panther";
		versionItems.add(mac1);

		VersionDto mac2 = new VersionDto();
		mac2.number = "10.4";
		mac2.codeName = "Tiger";
		versionItems.add(mac2);

		VersionDto mac3 = new VersionDto();
		mac3.number = "10.5";
		mac3.codeName = "Leopard";
		versionItems.add(mac3);

		VersionDto mac4 = new VersionDto();
		mac4.number = "10.6";
		mac4.codeName = "SnowLeopard";
		versionItems.add(mac4);

		return null;
	}

	class VersionDto {
		public String codeName;
		public String number;
	}

	public int getVersionColspanColspan() {
		return versionItems.size();
	}
}

JavaでMapコレクションの繰り返し

  • Posted by: sinsengumi
  • 2010年10月22日 11:34 AM
  • Java

毎回忘れて、調べてるのでメモ。

public class Sample {

    public static void main(String[] args) {

        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(0, "Kondou");
        map.put(1, "Hijikata");

        for (Entry<Integer, String> e : map.entrySet()) {
            System.out.print(e.getKey());
            System.out.print(" ");
            System.out.println(e.getValue());
        }
    }
}

JavaのHttpClient 4 を触ってみた。

  • Posted by: sinsengumi
  • 2010年10月7日 11:30 AM
  • Java
  • |

HttpClientの3.0系はレガシーということで、4系を触ってみました。
実行環境は以下です。

  • JRE 1.6
  • HttpClient 4.0.3 (httpclient-4.0.3.jar)
  • HttpCore 4.0.1 (httpcore-4.0.1.jar)
  • Commons Logging 1.1.1 (commons-logging-1.1.1.jar)

簡単に、HTTP接続ができていい感じです。

サンプルは以下。

public class HTTPSample {

    private static HttpClient httpClient = new DefaultHttpClient();

    public static void main(String[] args) {

        // プロキシがある場合は、以下のようにして設定する
        //HttpHost proxy = new HttpHost("XXX.XXX.XXX.XXX", 8080);
        //httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

        Map<String, String> requestParams = new HashMap<String, String>();
        requestParams.put("pattern", "ltrim");
        requestParams.put("lang", "ja");

        httpGet("http://jp2.php.net/manual-lookup.php", requestParams);
        // httpPost("http://jp2.php.net/manual-lookup.php", requestParams);

        // HTTP接続を閉じる(shutdownを実行するとセッションが切れます)
        httpClient.getConnectionManager().shutdown();
    }

    private static void httpGet(String url, Map<String, String> requestParams) {

        HttpGet httpGet = null;

        try {
            // リクエストパラメータの設定
            StringBuilder builder = new StringBuilder(url);
            builder.append("?");
            for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                builder.append((String) entry.getKey());
                builder.append("=");
                builder.append((String) entry.getValue());
                builder.append("&");
            }

            String tmpUrl = builder.toString();
            tmpUrl = tmpUrl.substring(0, tmpUrl.length() - 1);

            httpGet = new HttpGet(tmpUrl);

            System.out.println("executing request " + httpGet.getURI());
            System.out.println("-------------------------------------");

            HttpResponse response = httpClient.execute(httpGet);

            // レスポンスヘッダーの取得
            System.out.println(response.getStatusLine().getStatusCode());

            Header[] headers = response.getAllHeaders();
            for (Header header : headers) {
                System.out.println(header.getName() + ": " + header.getValue());
            }

            System.out.print(System.getProperty("line.separator"));

            // レスポンスボディの取得
            HttpEntity httpEntity = response.getEntity();
            System.out.println(EntityUtils.toString(httpEntity));

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
        }
    }

    private static void httpPost(String url, Map<String, String> requestParams) {

        HttpPost httpPost = null;

        try {
            // リクエストパラメータの設定
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            for (Map.Entry<String, String> entry : requestParams.entrySet()) {
                params.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue()));
            }

            httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

            System.out.println("executing request " + httpPost.getURI());
            System.out.println("-------------------------------------");

            // レスポンスヘッダーの取得
            HttpResponse response = httpClient.execute(httpPost);
            System.out.println(response.getStatusLine().getStatusCode());

            Header[] headers = response.getAllHeaders();
            for (Header header : headers) {
                System.out.println(header.getName() + ": " + header.getValue());
            }

            System.out.print(System.getProperty("line.separator"));

            // レスポンスボディの取得
            HttpEntity httpEntity = response.getEntity();
            System.out.println(EntityUtils.toString(httpEntity));

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (httpPost != null) {
                httpPost.abort();
            }
        }
    }
}

参考

iBATISのSqlMapConfig.xmlについて

SqlMapConfig.xmlの設定を書いておきます。
正直、コネクションプーリングとか遅延ローディングだとかよく分からなかったので、そこらへんはとりあえずデフォルト設定にしておいたほうがいいかも。
分かるようになったら更新します。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
        "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

    <!--
        sqlMapClientの最適化を行う(この<settings>エレメントは任意)
        maxRequests : 一度にSQLを実行するスレッドの最大数
                    (maxRequests > maxTransactions*10)
        maxSessions : 一時にアクティブになることができるセッション数
                    (maxTransactions < maxRequests < maxRequests)
        maxTransactions : 一度にSqlMapClient.startTransaction()に入ることができるスレッドの最大数
                        (maxTransactions < maxSessions && maxTransactions << maxRequests)
        cacheModelsEnabled : キャッシュを有効にするかどうか
        lazyLoadingEnabled : 遅延ローディングを有効にするかどうか
        enhancementEnabled : lazyLoadingの拡張?
        useStatementNamespaces : prepared statementsのローカルキャッシュを使用するかどうか
        defaultStatementTimeout : ?よくわからない
        classInfoCacheEnabled : キャッシュされたクラスを使用するかどうか
        statementCachingEnabled : prepared statementsのローカルキャッシュを使用するかどうか

        ちなみに以下の値はすべてデフォルト値です。
    -->
    <settings
        maxRequests="512"
        maxSessions="128"
        maxTransactions="32"
        cacheModelsEnabled="true"
        lazyLoadingEnabled="true"
        enhancementEnabled="true"
        useStatementNamespaces="false"
        classInfoCacheEnabled="true"
        statementCachingEnabled="true"
    />

    <!--
        トランザクション管理サービスの設定
    -->
    <transactionManager type="JDBC">
        <dataSource type="SIMPLE">
            <property name="JDBC.Driver" value="org.postgresql.Driver" />
            <property name="JDBC.ConnectionURL" value="jdbc:postgresql://localhost:5432/sampledb" />
            <property name="JDBC.Username" value="postgres" />
            <property name="JDBC.Password" value="postgres" />
            <property name="JDBC.DefaultAutoCommit" value="false" />
            <!-- コネクションプーリング(はっきりいってよく分からない部分なので書かないでおいたほうが無難かも。。) -->
            <property name="Pool.MaximumActiveConnections" value="10" />
            <property name="Pool.MaximumIdleConnections" value="5" />
            <property name="Pool.MaximumCheckoutTime" value="120000" />
            <property name="Pool.TimeToWait" value="10000" />
            <property name="Pool.PingQuery" value="select 1" />
            <property name="Pool.PingEnabled" value="false" />
            <property name="Pool.PingConnectionsOlderThan" value="0" />
            <property name="Pool.PingConnectionsNotUsedFor" value="0" />
        </dataSource>
    </transactionManager>

    <!-- sqlMapファイルの参照 -->
    <sqlMap resource="ibatis/dao/user.SqlMap.xml" />
</sqlMapConfig>

参考

iBATISでトランザクションする

iBATISのデフォルト設定だと自動コミットモードになっていて、細かなトランザクション処理ができません。なので、iBATISでトランザクションをできるようにしてみる。
設定・構成等はiBATIS入門と同じです。

自動コミットモードの解除

まずSqlMapConfig.xmlを編集して、自動コミットモードを解除しておきます。
大事なのは、「<property name=”JDBC.DefaultAutoCommit” value=”false” />」です。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
        "http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>
    <!-- DB接続設定 -->
    <transactionManager type="JDBC">
        <dataSource type="SIMPLE">
            <property name="JDBC.Driver" value="org.postgresql.Driver" />
            <property name="JDBC.ConnectionURL" value="jdbc:postgresql://localhost:5432/sampledb" />
            <property name="JDBC.Username" value="postgres" />
            <property name="JDBC.Password" value="postgres" />
            <property name="JDBC.DefaultAutoCommit" value="false" />
        </dataSource>
    </transactionManager>

    <!-- sqlMapファイルの参照 -->
    <sqlMap resource="ibatis/dao/user.SqlMap.xml" />
</sqlMapConfig>

実際に動かしてみる

sqlMap.startTransaction()でトランザクションを開始して、sqlMap.commitTransaction()でコミットする。
正常・異常終了に関わらずfinallyでsqlMap.endTransaction()をする。
トランザクション処理を行う場合はこのパターンが定型だと思われる。

package ibatis;

import ibatis.dto.User;
import com.ibatis.sqlmap.client.SqlMapClient;
import java.sql.SQLException;

public class Sample {

    public static void main(String[] args) {
        // SqlMapClientを生成
        SqlMapClient sqlMap = MyAppSqlConfig.getSqlMapInstance();

        try {
            // トランザクションを開始する
            sqlMap.startTransaction();

            // insert
            User user = new User();
            user.setId(4);
            user.setName("Tanaka");
            user.setAge(35);
            sqlMap.insert("insertUser", user);

            // delete
            sqlMap.delete("deleteUser", 1);

            // コミットする
            sqlMap.commitTransaction();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                // トランザクションを終了する
                // commitTransaction()まで行かず、エラーが発生した場合はロールバックを行う
                sqlMap.endTransaction();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

Javaでファイルを1行ずつ読み込む

  • Posted by: sinsengumi
  • 8:06 PM
  • Java

Javaでファイルを読み込み、1行ずつ出力する処理。よく書くので。

public void fileRead(String filePath) {
    FileReader fr = null;
    BufferedReader br = null;
    try {
        fr = new FileReader(filePath);
        br = new BufferedReader(fr);

        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            br.close();
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ホーム > Java

Search
Feeds
Meta

Return to page top