Clickを使ってみる

$formとか$tableで表示できるってところに誘われてClickを見てたら、使いたくなってきたのでちょっと勉強。


まず、EclipseTomcatプロジェクトを作ったあと、click-blank.warを解凍して上書き。
これでClickの環境が完成!!

何をすればいいのかよくわからないので、http://click.sourceforge.net/をみて勉強。


まず、自動的にmappingするため(?)、click.xmlのpagesタグを変更する必要があるみたい。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<click-app>
    
  <pages package="sample.page" automapping="true">
    <!--
    <page path="index.htm" classname="Home"/>
    -->
  </pages>
  
  <headers>
    <header name="Pragma" value="no-cache"/>
    <header name="Cache-Control" value="no-store, no-cache, must-revalidate, post-check=0, pre-check=0"/>
    <header name="Expires" value="1" type="Date"/>
  </headers>
  
  <mode value="development"/>
  
</click-app>


英語は全然ダメだから、この辺でみるのをやめる。実践あるのみ。


でも何からはじめればよいかわからないから、IntroductionのLoginを真似てみる。
まずは必要となるDTOから

package sample.dto;

public class UserDto {
	
	private String username;
	
	private String password;

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

次は、ちょっとだけ変更したPageクラス

package sample.page;

import net.sf.click.Page;
import net.sf.click.control.Form;
import net.sf.click.control.PasswordField;
import net.sf.click.control.Submit;
import net.sf.click.control.TextField;
import sample.dto.UserDto;
import sample.service.LoginService;
import sample.service.impl.LoginServiceImpl;

public class Login extends Page {

    private Form form = new Form("form");
    
    private LoginService login;
    
    public Login() { 
        form.add(new TextField("username", true));
        form.add(new PasswordField("password", true));
        form.add(new Submit("ok", "   OK   ", this, "onOkClicked"));
        addControl(form);
        
        login = new LoginServiceImpl();
    }

    public boolean onOkClicked() {
        if (form.isValid()) {
            UserDto user = new UserDto();
            form.copyTo(user);
            if (login.execute(user)) {
                getContext().setSessionAttribute("user", user);
                setRedirect("secure.htm");
            } else {     
                form.setError(getMessage("authentication-error"));           
            }
        }
        return true;
    }

}

そして実際のログインできるかを判断するLoginServiceのインターフェースと実装

package sample.service;

import sample.dto.UserDto;

public interface LoginService {
    
    public boolean execute(UserDto dto);

}
package sample.service.impl;

import sample.dto.UserDto;
import sample.service.LoginService;

public class LoginServiceImpl implements LoginService {

    public boolean execute(UserDto dto) {
        return dto.getUsername().equals(dto.getPassword());
    }

}

入力されたusernameとpasswordがいっしょだったらOKで違ってたらNGという単純な作り。


そして、login.htmと

<html>
  <body>
    <h2>Login</h2>
    $form
  </body>
</html>

結果を表示するsecure.htm

<html>
  <body>
    <h2>Hello $session.user.username</h2>
  </body>
</html> 

そしてTomcatを実行して、http://localhost:8080/click-sample/login.htmでログイン画面が表示できたー。


でも、、、ちょっと触ってみるといろいろと問題が。。。

  • まず何もせずOKボタンをクリックするとエラーメッセージが表示されるんだけど????となってる
  • ログインエラーになるように異なるUsernameとPasswordを入力するとError Pageが表示される
  • ログインするために同じUsernameとPasswordを入力するとPage Not Foundとなる


一番下のは簡単そうだなー。もしかして対応するPageクラスがないからかも。
ためしに下のような空のPageクラスを作って

package sample.page;

import net.sf.click.Page;

public class Secure extends Page {

}

再度ためしたらうまくいった。1つ解決残り2つ。


ログインエラーのも簡単になおりそう。
おぉ!!Error Pageのリンクをクリックしたら、エラーの詳細がソースつきで表示される。この機能は重宝しそう。


エラーの原因はリソースファイルにauthentication-errorが定義されていないからみたい。ってことで、Loginクラスと同じ場所にLogin.propertiesを

authentication-error=authentication error.

として作成。うむうむうまくいった。getMessage()を利用する場合はPageクラスごとにpropertiesを用意するってことかな(はやとちりかも)。あと1つ。



????となるのはやっぱり文字コードを指定してないからだろなー。でもVelocityも今まで使ったことないしよくわからない。。。
そういえば、click.xmlにheader情報を定義しているところがあったな。。。
ためしにclick.xmlのheadersタグに下のを追加してみたら、

    <header name="Content-Type" value="text/html; charset=UTF-8"/>

うまくいった。
でも、ここで定義してもいいのかなー。ダウンロードがどうなるのか心配だけど、そのときに悩むことにしよう。とりあえずはこれでOKと。



これで最初に思いついた問題はすべて解決したけど、
よく考えたら(よく考えなくても)日本語を入力したら文字が化けるかも。。。
やっぱり化けた。

Filterを追加すべきかなー。click.dtdをみるとclick-appにcharset属性がある。click.xmlで定義してみる。
おー、うまくいった。
もしかしてheaderで定義したContent-Typeは不要かも。。。はずして実行してみたら、エラーメッセージがきちんと表示された!!
結局click.xmlのclick-app charsetを定義すればよいってことなのかな。


はやとちりと勘違いはまだたくさんありそうだけど、最初の第一歩としては良い印象。
初めてStrutsを利用したときよりかは楽に入れた感じがする。6年間の成長か、それともTagLibとVelocityの差か、、、
でも、本当の良さはもっと使わないとわからないなー。