yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2017/11 の記事
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30]

yamicha.com's Blog
 諸事情により、現在更新休止中。ご了承ください。もし今後ブログを再開することがあるとすれば、その際にはこのブログスクリプトではなく、新しく開発したものによるかもしれません。
 当ブログ管理者についてはこちらをご参照。
開発魔法(737)
社会問題(733)
お知らせ(11)
質問・バトン回答(15)
ゲスト出演(8)
経済・知的財産(150)
ゲーム開発(182)
[Ada] 勝手に補足
- Note
- 金配りの次の一手


- Endless Ultimate Diary
- 銃世界

漢字バトン
- うるる雑記帳
- 漢字接力棒

ツキアイゲノムバトン
- ブログ@うにうに画像倉庫
- あぶ内閣

縺イ縺セ縺、縺カ縺励ヰ繝医Φ
- 月夜のボヤキ
- 騎士サーラバトン
パスワードを使う
名無し (2012/02/27)


開発者解放裁判
yamicha.com (2010/03/14)
Winnyに関しては、私も「純白」とまでは考えておりませんし、使用し..

開発者解放裁判
通りすがり (2010/03/08)
winnyに関しては「ダウンロードソフト板」なんてところを拠点に開発..

新型インフルエンザの恐怖
いげ太 (2009/11/03)
> C#などの「int Some(int , int)」は、F#では「(int * int) ->..

時効に関する思考
yamicha.com (2009/08/31)
>いげ太さんコメントありがとうございます。手元にドキュメントが少..
Homepage
Blog Top
Normal View
List View
Search
Calendar
Comment List
Trackback List
Blog RSS
Send Trackback
Phone Mode
Administrator
yamicha.com
Blog
るううるる。
Source
法令データ提供システム
FindLaw
Development
Java2 Platform SE 6
Java EE 6 API
MySQL Developer Zone
PHP Reference
MSDN Library
Ada Reference Manual
Objective Caml
Python Documentation
Erlang
Prolog Documents
ブログ - yamicha.com's Blog

 存在する記事 776 件の中から 16-20 件を表示しています。
辞任相当判定
2010/04/30(Fri)22:55:56
 不起訴処分となった小沢氏に対し、検察審査会が「起訴相当」の判断を下し、波紋が広がっています。小沢氏は続投の意思を見せているものの、党外ばかりか党内からも辞任を求める声が公然と噴出しており、このままでは確実に参院選にも影響するとあって、鳩山内閣はいっそうの窮地に立たされているようです。
 今まで批判をのらりくらりとかわしてきた小沢氏ですが、このような状況になったからには、おそらく氏は遅かれ早かれ幹事長を退くことを余儀なくされるでしょう。いくら権力に固執する小沢氏といえど、氏を取り巻く状況は最悪と言っても過言ではありませんし、そもそも内閣の方が小沢氏をかばいきれなくなりつつあります。状況が好転する見込みもない以上、地位を退かなくてはならないのは時間の問題です。
 そして、いずれ地位を退くことを余儀なくされるのであれば、最初からそうしておけば問題が拡大せずに済んだものを、今まで政治を大混乱させてきた民主党及び小沢氏の罪は重いと言わざるを得ません。特に、党内の異論を封じ込め、批判的な言を行う者を処分し(生方氏の副幹事長解任)、小沢独裁体制を認めてきた民主党執行部、鳩山内閣の責任は非常に重く、内閣の指導力に疑問符がつくのも当然です。
 そもそも鳩山内閣は、小沢氏が政治資金に関する疑惑のみならず、政治家としても国民に全く信任されていないこと、また内閣の二重権力状態に国民が強い疑念を抱いていることも、認識しなくてはなりません。仮に小沢氏が政治資金疑惑において潔白であったとしても、氏の手法や民主党の勢力状態には多くの国民が不信を抱いており、辞任が望まれている点に変わりはありません。
 実のところ、民主党は決して能力のない政党ではありません。鳩山内閣はひどい状態であるとしか言いようがありませんが、閣僚まですべて無能なわけではありません。また、民主党は候補者の公募にも取り組んでいましたので、党内には有能な人材を十分に抱えているはずです。これは、有力政治家の世襲議員を未だに平然と擁立し、公募をすれば杉村氏のような議員を集めるといった有様の自民党と比較し、大きな長所となり得ます。
 しかし、今の民主党は小沢氏の独裁体制にあり、有能な若手や中堅の声が封殺されている状況にあります。小沢氏ら民主党の実権を握っている人間は、もともと自民党から離党した者ばかりですので、これでは自民党がもう1つあるのと変わりません。対する「本物の」自民党も、体制を刷新しようという意思はほとんど持っていないらしいため、二大政党の両方が支持を失う状態につながっています。さらに、最近になって小政党が乱立していますが、これらの多くは自民党離党者によって設立されており、単なる小型自民党に他なりません。これでは政治が閉塞状態に陥るのも無理はありません。
 その上、二重権力状態の民主党において、小沢氏は無茶としか言いようのないことを閣僚に指示し、鳩山氏も勝手なことを公言するため、閣内は大混乱に陥っています。いかに有能な人間が閣内にいたとしても、これでは仕事に取り掛かるどころではありません。さらに、仮に成功を収めたとしても、その成果は国民から評価されるどころか、小沢氏への批判の中に埋もれてしまうのです。
 しかも民主党は、かつては消費税増税を政策に盛り込むなど、必ずしも「甘い汁」ばかりを訴えていたわけではありませんでしたが、小沢氏が権力を握ってからは変質してしまいました。金配りを行った自民党にすら「社会主義政策」とまで批判されるほどで、まがりなりにも負担増を訴えていた以前の民主党に比べ、その劣化を憂う人は少なくないはずです。
 民主党にとって、本来なら今の状況はこの上ない機会に他なりません。自身も支持を失ってしまってはいるものの、自民党は全く体質を変えるつもりがなく、そちらに支持が戻る様子はありませんし、乱立する小政党もほとんどが自民党の衛星政党、あるいはミニ自民党に過ぎません。しかも幸いなことに、民主党には民間から集めた人材も存在し、腐った部分を取り除いたとしても、身は十分に残っています。さらには参院選までが控えており、小沢氏が主導したバラマキ政策の見直しを公言したり、「苦い薬」も含めた現実的な政策を訴えるには事欠かない状態にあります。したがって、小沢氏を排除して独裁状態を終わらせ、若手や中堅の優秀な人材を中心に体制を編成すれば、いち早く「二大自民党及び多数の小自民党」状態から脱却できる可能性は十分にあるのです。
 小沢氏の処遇に関し、ここまで民主党は多くのミスをしてきました。すなわち、大連立の際には民主党を滅亡寸前にまで追い込んだ小沢氏を慰留すべきではありませんでしたし、代表選で小沢氏に近い鳩山氏を選んだのも失敗でした。また、今回も小沢氏を早めに解任しなかったことが、現在の状況につながっています。いずれの場合もその選択が何を意味するかはその時点で明らかに分かっていたはずであり、当時の民主党がそれを選択した結果、今の追い込まれた民主党があるのです。
 確かに小沢氏は豪腕でもあり、参院選の大勝も小沢氏による部分がありますので、むげに扱えないという立場は分からなくもありませんが、それが今の「試合に勝って(選挙での大勝)、勝負に負けた(政策をまともに実現できていない段階での支持率低下と参院選敗北の危機、下手すると党の離散)」状況につながっているのであれば、全く意味がありません。
 ここまでの状況ともなれば、小沢氏が地位を退くのはもはや時間の問題なのですから、民主党は早く始末をつけるべきでしょう。それすら不可能な程度の政党であるならば、自党もろとも退くことになっても文句はいえません。

 前回まででJAX-RSの使い方が分かりましたので、今回はごく簡単な(名前とメッセージを送るとデータベースに発言が登録される)チャットのサーバー側を作成してみます。まさかJava EEでJDBCを直接使ってデータベースの読み書きをするわけにもいきませんので、JAX-RS + EJB + JPAの構成となります。
 クライアント側に関しては、XMLさえ読み書きできれば言語・実行環境は問いませんが、JSF 2.0のAjaxで実装する意図から、web.xmlにはJSF関連の記述を加えてあります。ただし、今回の記事ではサーバー側の実装しか行っていません。
/WEB-INF
 /classes
  /com
   /yamicha
    /rs
     /server
      @Path SimpleChat.java
      @Entity ChatMessage.java
      @XmlElement ChatMessages.java
      @Stateless ChatMessageAccess.java
  /META-INF
   persistence.xml
 web.xml
 アノテーションのおかげで一目瞭然ですが、SimpleChat.javaがリクエストを受け取り、ChatMessageAccess.javaを使ってデータベースに書き込みます。
 前述の通り、今回のweb.xmlにはJSF関連の記述を行っています。
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>

<display-name>JAX-RS Servlet</display-name>
<description>JAX-RS Servlet</description>

<servlet>
<servlet-name>jax-rs</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.yamicha.rs.server</param-value>
</init-param>
</servlet>

<servlet>
<servlet-name>jsf20</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>jax-rs</servlet-name>
<url-pattern>/restserver/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>jsf20</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
 データベースを使用するとなれば、用意が必要なのがpersistence.xmlです。
<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="MySQL" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/MySQL</jta-data-source>
    <properties>
      <property name="eclipselink.jdbc.driver"
        value="com.mysql.jdbc.Driver" />
      <property name="eclipselink.ddl-generation"
        value="create-tables" />
      <property name="eclipselink.ddl-generation.output-mode"
        value="database" />
      <property name="eclipselink.target-database" value="MySQL" />
      <property name="eclipselink.logging.level" value="FINE"/>
    </properties>
  </persistence-unit>
</persistence>
 今回はシンプルなチャットですので、テーブルの構成自体は非常に簡単で、IDの他には名前、発言、発言日時を保管するカラムしかありません。
package com.yamicha.rs.server;

import javax.sql.*;
import java.util.Date;
import javax.persistence.*;
import javax.xml.bind.annotation.*;

@Entity @Table(name="rest_chatmessage" , schema="yamicha")
	@XmlRootElement
	public class ChatMessage implements java.io.Serializable{
	private int id;
	private String name;
	private String message;
	private Date date;

	public ChatMessage(){
		id = 0;
	}
	public ChatMessage(String n , String m){
		this();
		name = n;
		message = m;
	}

	@Id @Column(name="id") @GeneratedValue @XmlElement
		public int getId(){
		return id;
	}
	@Column(name="name") @XmlElement public String getName(){
		return name;
	}
	@Column(name="message") @XmlElement public String getMessage(){
		return message;
	}
	@Column(name="date") @Temporal(TemporalType.TIMESTAMP) @XmlElement
		public Date getDate(){
		return date;
	}

	public void setId(int i){
		id = i;
	}
	public void setName(String s){
		name = s;
	}
	public void setMessage(String s){
		message = s;
	}
	public void setDate(Date d){
		date = d;
	}
}
 ChatMessages.javaはJAXB用です。
package com.yamicha.rs.server;

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
	public class ChatMessages implements java.io.Serializable{
	private List<ChatMessage> messages;

	public ChatMessages(){
		messages = new ArrayList<ChatMessage>();
	}
	public ChatMessages(List<ChatMessage> msgs){
		messages = msgs;
	}

	@XmlElement public List<ChatMessage> getMessages(){
		return messages;
	}
	public void setMessage(List<ChatMessage> msgs){
		messages = msgs;
	}
}
 ChatMessageAccess.javaでは、発言日時順に任意の数の発言を取得するメソッド、発言を登録するメソッドの2つを実装しています。
package com.yamicha.rs.server;

import javax.ejb.*;
import javax.annotation.*;
import javax.persistence.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;

@Remote @Stateless(name="ChatMessageAccess" ,
	mappedName="ejb/ChatMessageAccess")
	public class ChatMessageAccess{
	@PersistenceContext(unitName="MySQL") private EntityManager em;

	public ChatMessages getMessages(int max){
		Query q = em.createQuery(
			"SELECT c FROM ChatMessage c ORDER BY c.date DESC");
		if(max != -1)
			q.setMaxResults(max);

		// 結果を ChatMessages にラップして返す
		return new ChatMessages((List<ChatMessage>)
			q.getResultList());
	}
	public void writeMessage(ChatMessage msg){
		// 発言日時を現在時刻に設定する
		msg.setDate(new Date());

		em.persist(msg);
	}
}
 残るはRESTリクエストをさばくSimpleChat.javaなのですが、実はJAX-RS(の仕様なのかJerseyの仕様なのか、はたまた単に先行リリースゆえの未実装であるだけなのかは不明)、EJBのDIを受け付けてくれません。DIしたい変数にアノテーションをつけておいても、注入が一切なされないため、nullになってしまいます。
 仕方がないのでInitialContextから取っていますが、基本的に注意が必要なのはここだけです。
package com.yamicha.rs.server;

import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ejb.*;
import javax.naming.Context;
import javax.naming.InitialContext;

@Path("chat") public class SimpleChat{
	private ChatMessageAccess ma;

	public SimpleChat() throws Exception{
		Context c = new InitialContext();
		ma = (ChatMessageAccess)c.lookup(
			"java:global/rs/ChatMessageAccess");
	}

	@POST @Path("write")
		public void writeMessage(ChatMessage message){
		ma.writeMessage(message);
	}

	@GET @Path("all") public ChatMessages readMessages(
		@QueryParam("max") @DefaultValue("20") String smax){
		int max = 20;
		try{
			max = Integer.parseInt(smax);
		}catch(NumberFormatException e){
		}

		return ma.getMessages(max);
	}
}
 この時点では、データを登録するにはXMLをPOSTする必要がありますが、単に動作を確認するだけであれば、データベースに適当なデータを登録しておいて「/restserver/chat/all」をブラウザで開くだけです。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

新倒壊革
2010/04/24(Sat)05:33:26
 自民党の敗北後より、水面下で不穏な動きを見せていた舛添氏ですが、このほどようやく「舛添新党」の道を選ぶことが明らかになりました。舛添氏ら3氏が改革クラブに合流し、これを衣替えして「新党改革」に変更、舛添氏が党首に就任するという形式を取るようです。一方、舛添氏に反発した2名が同党から離脱し、同党の保有議席は5から6に1つ増えるにとどまります。
 改革クラブ自体が2007年の参院選における民意を裏切って結党された政党であり、民主党のものとして与えられたはずの議席にただ乗りして政党交付金を確保しようとする、大義に乏しい党であることは同党の結党時にも述べましたが、舛添氏がそのような体質の政党に合流し、結果として同党が同様の行為を再び繰り返そうとするのは、皮肉であるとしか言いようがありません。しかも舛添氏は自民党の比例代表として当選しているのですから、こちらは真の意味で自民党の議席にただ乗りしています。
 与謝野氏や舛添氏らのような大物が離党している状況でありながら、ほとんどの自民党議員が呼応しない点からしても、多くの自民党議員は新党騒ぎを非常に冷めた目で見ているようです。事実、舛添氏が引き連れて入党となった議員も3名に過ぎず、独自の新党では政党要件さえも満たせないか、もし満たせたとしても苦しい状況となります。しかし、改革クラブを媒体として使用すれば、引き続き政党交付金も受け取れます。一方、改革クラブは二大政党や各新党の狭間への埋没に危機感を抱いているはずで、自分の党の「色」を犠牲にし、所属議員2名を失ってまで舛添氏を党首に受け入れたのは、まさにそれを打破する意図があるからこそでしょう。すなわち、どうしても実現したい共同の理念があるからというより、両者の利害が一致した結果が、この衣替え新党と見るのが妥当です。
 このようなやり方に対しては、「政党交付金を受け取るのは道理に合わない」との批判が出てくるのは当然ですが、舛添氏は「我々は金のかかる政治と決別したい」などと言っておきながら、政党交付金への批判に対しては「企業や労組から金を受け取れば、彼らは口も出す。我々は政党交付金でやるから国民全体をみている」と意味不明な論理を持ち出して正当化しています。この状況下で政党交付金を受け取るのは道理に合わないから批判が出るのであって、ここでは企業や労組などは全く関係がありません。団体献金を受け取らない姿勢は大いに結構ですが、これでは「政党交付金を受け取るのは道理に合わない」という疑問への説明になっていません。
 そもそも、私が舛添氏を信用しない理由の1つに、氏があまりにも自分勝手でご都合主義、あるいはその場限りの言い分を用いることが挙げられます。例えば、舛添氏が厚生労働相に就任していた時期、年金の記録の散逸が問題になった際には、どう考えても守りようのない期限を自ら掲げた挙句、案の定実現できないと分かったら、今度は開き直りをはじめました。また、自民党の大敗後には「今の自民党に必要なのは、民主党の小沢代表以上の独裁者」などと言っておきながら、後から谷垣体制を批判した際には「批判のない政党は独裁政党」と称して自らの行為を正当化する有様で、まるで発言の整合性が取れていません。今回の「新党改革」の件にしても、まさに当の舛添氏が真っ先に「金目当て」などと批判しそうなやり方ですし、手段を選ばず政党交付金を受け取る行為も「政治とカネ」の問題の一分類に他ならず、これもまた国民の政治不信の一因となっている事実を忘れてはいけません。
 一方、自民党は高い人気を誇る舛添氏を失い、衆院選大敗及びその後の混乱に続いて大きな痛手をこうむっているはずですが、ここは「自ら手を下すまでもなく厄介払いができた」と前向きに考え、党の再生を図るべきでしょう。与謝野氏にせよ、舛添氏にせよ、実際のところ彼らの離党は痛手などではなく、膿が排出されたと考えるべきです。
 舛添氏がここまで新党結成を先延ばしにしたのは、自民党総裁の座を狙っていたと考えるのが妥当です。しかも、国民からの高い人気を背景に、自民党議員の満場一致、円満譲渡のような形で総裁の座に就くことを狙っていたと考えられます。氏が今回離党に踏み切ったのも、谷垣氏や自民党が代表の座を譲渡しようとする気配を見せなかったためでしょう。
 しかし、このまま舛添氏が離党をしていなければ、いずれ自民党は「国民の声」に押しつぶされ、どうしても氏を総裁にせざるを得なくなった可能性が十分にあります。そして、仮に氏が自民党総裁に就任していれば、それこそ自民党ばかりか日本が大混迷に陥ったであろうことは想像に難くありません
 舛添氏は「はっきり物を言う」とみなされている人物であり、それが実直あるいは明快な印象を与え、国民の人気を獲得しているものと考えられます。さらに、マスコミは人気のある人物の批判を避けようとするため、氏の数々の暴言や問題はほとんど報道されておらず、結果として氏を政界の救世主でもあるかのように翼賛する報道ばかりが目立っています。しかし、仮に二大政党の片方を占める大政党の代表に就任したとなれば、氏も口当たりの良い発言ばかりはしていられませんし、問題発言があればマスコミといえど隠し通すのは困難です。
 すなわち、氏が代表就任後も「はっきり物を言う」姿勢を続けるならば、無賃残業合法化など氏が強硬に主張している政策、あるいはこれまで散々繰り返してきたものの、ほとんど報道されてこなかった暴言なども、それからはすべて白日の下にさらされる結果となり、国民の人気を失うのは時間の問題です。一方、氏がその姿勢をある程度改め、二枚舌政治を行うならば、今度は「舛添氏も他の政治家と変わらなかった」という印象を国民に与える結果となるでしょう。
 そして、仮にひとたび舛添氏の人気が落ち始め、マスコミが氏に遠慮しなくなれば、氏の体制が破綻するのは時間の問題です。なぜなら、氏は「小人のざれ言に付き合う暇はない」「バカ市長と言わないだけマシ」などといった暴言を吐いたり、かつて自らが「みなし役員」などの問題を管轄とする省のトップにありながら、「残業代が出なくなれば、みんな早く帰って家庭だんらんができる」などという、およそ実態とかけ離れた理由によって無賃残業合法化を強く推進したり、無賃残業合法化を「家庭だんらん法案」と言い換えさえすれば国民をだませると考えていたりと、実際には人格的・政策的にほとんど見るべき点のない人物であるためです。
 今のところはマスコミが批判的な報道を控えているため、これらの火種は表面化せずに済んでいますが、もしマスコミが手のひらを返し、国民も舛添氏の人格・政策について関心を持てば、まるで螺旋階段を転がり落ちるかのような勢いで、舛添氏は一気に支持を失ってしまうでしょう。もしそうなれば、自民党もただでは済みません。単に支持を失うばかりか、今度こそ壊滅的な打撃を受ける可能性さえ否定できません。
 その舛添氏が自ら党を去ったのですから、これは本来なら自民党にとって「願ってもない話」なのです。確かに自民党は国民からの支持を失っており、かなり苦しい状況にありますが、国民は雨後のたけのこのごとく湧き出る新政党にもほとんど期待してはいません。現在の自民党には、未だに堂々と世襲を続けたり、人気者の世襲議員を重用したりといった問題点もあるものの、民主党も落語家を擁立するなど、負けず劣らずの暴挙に出ています。せっかく与謝野氏や舛添氏のような懸念材料も消えたのですから、これらの点を改善しようと努力し、くだらない人気取りをやめ、「苦い薬」も含めて実直に政策を訴えるようにすれば、党を立て直せる可能性は十分にあります。
 そして当然のことながら、自民党総裁の可能性は当面は薄まったとはいえ、舛添氏の動向には今後とも十分に注意が必要です。現在の閉塞した政治状況において、政界再編が必要であるとする意見は理解できますが、それは舛添氏以外の手によって行われなくてはなりません。

 JAX-RSでは自動的にJAXBの変換を行ってくれるため、特にこれといった変換操作をしなくても、普通にオブジェクトを扱うかのように操作が可能であることは前回に試しました。
 しかし、JAX-RSで自動的に行えるのは、何もJAXBの変換だけではありません。あのいまいましいAjaxのせいで注目されてしまった技術・JSONすら変換できてしまいます。しかも、JSON用に特別なJavaBeanを用意したり、JSON化及び復元するためのコードを書かなくても、XMLをやり取りするのと同様の書き方をしておけば、それでJSONにしたり戻したりする変換が自動的に行われるというのです。
 そうであるならば、何らかの操作について「XMLでのやり取り」と「JSONでのやり取り」の両方を提供するのも非常に容易になりますし、場合によってはAjaxから直接アクセスするといった使い方も考えられます。いずれにしても、かなり面白そうな機能には違いありません。
 今回はとりあえず、前回の計算プログラムをJSONでも使えるよう拡張してみるものとしました。
/WEB-INF
 /classes
  /com
   /yamicha
    /rs
     /server
      @XmlRootElement Calc.java
      @Path CalcService.java
     /client
      @WebServlet CalcServlet.java
 web.xml
calcForm.htm
calcAjax.htm
 今回はあくまで「JSON対応にする」だけですので、web.xmlとCalc.javaの内容は前回と全く同様です。すなわち、データを保持するJavaBeanには全く手を加える必要がないことを意味します。JSONとして用いる場合でも、そのまま使えてしまいます。
 CalcService.javaは以下の通り拡張しました。
package com.yamicha.rs.server;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("calc") public class CalcService{
	public CalcService(){
	}

	// 計算用メソッド
	private Calc executeCalc(Calc calc){
		try{
			int answer = 0;

			int v1 = Integer.parseInt(calc.getValue1());
			int v2 = Integer.parseInt(calc.getValue2());
			String operator = calc.getOperator();

			if("+".equals(operator))
				answer = v1 + v2;
			else if("-".equals(operator))
				answer = v1 - v2;
			else if("*".equals(operator))
				answer = v1 * v2;
			else if("/".equals(operator))
				answer = v1 / v2;
			else if("**".equals(operator))
				answer = (int)Math.pow(v1 , v2);
			else
				return calc;

			calc.setAnswer(String.valueOf(answer));
		}catch(NumberFormatException e){
		}

		return calc;
	}

	// パラメータを取り、結果を XML 形式で返す
	@GET @Path("query/xml") @Produces("application/xml")
		public Calc queryToXml(
		@QueryParam("value1") String v1 ,
		@QueryParam("operator") String op ,
		@QueryParam("value2") String v2){
		Calc calc = new Calc();
		calc.setValue1(v1);
		calc.setValue2(v2);
		calc.setOperator(op);

		return executeCalc(calc);
	}

	// XML を取り、XML を返す
	@POST @Path("xml/xml") @Consumes("application/xml")
		@Produces("application/xml")
		public Calc xmlToXml(Calc calc){
		return executeCalc(calc);
	}

	// JSON を取り、XML を返す
	@POST @Path("json/xml") @Consumes("application/json")
		@Produces("application/xml")
		public Calc jsonToXml(Calc calc){
		return executeCalc(calc);
	}

	// JSON を取り、JSON を返す
	@POST @Path("json/json") @Consumes("application/json")
		@Produces("application/json")
		public Calc jsonToJson(Calc calc){
		return executeCalc(calc);
	}

	// XML を取り、JSON を返す
	@POST @Path("xml/json") @Consumes("application/xml")
		@Produces("application/json")
		public Calc xmlToJson(Calc calc){
		return executeCalc(calc);
	}
}
 見ての通りですが、XMLを取ってXMLを返すメソッド、JSONを取ってXMLを返すメソッド、XMLを取ってJSONを返すメソッド、JSONを取ってJSONを返すメソッドの各実装は、いずれも全く同じです。すなわち、Calcを受け取ってCalcを返しています。
 CalcServlet.javaは次のように変更しました。今回はコントロールの機能に特化しています。このServletでは、queryToXml、xmlToXml、jsonToXmlの3種類のメソッドを呼び出せるようにしています。
package com.yamicha.rs.client;

import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.servlet.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.*;
import com.yamicha.rs.server.*;

@WebServlet(name="calcservlet" , urlPatterns={"/client/calc/*"})
  public class CalcServlet extends HttpServlet{
  private final static String REST_SERVER =
    "(このプログラムのURL)/restserver/calc/";

  public void doPost(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    doGet(request , response);
  }
  public void doGet(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    response.setContentType("text/plain");
    PrintWriter out = response.getWriter();

    String path = request.getParameter("path");

    Calc calc = new Calc();
    calc.setValue1(request.getParameter("value1"));
    calc.setValue2(request.getParameter("value2"));
    calc.setOperator(request.getParameter("operator"));

    try{
      HttpURLConnection c = null;
      JAXBContext jc = JAXBContext.newInstance(Calc.class);

      if("query/xml".equals(path)){
        // GET 方式でパラメータを送り、XML を受け取る
        c = (HttpURLConnection)
          new URL(REST_SERVER + path +
          "?value1=" + URLEncoder.encode(calc.getValue1() , "UTF-8") +
          "&value2=" + URLEncoder.encode(calc.getValue2() , "UTF-8") +
          "&operator=" + URLEncoder.encode(calc.getOperator() , "UTF-8"))
          .openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);

        c.connect();
      }else if("xml/xml".equals(path)){
        // XML を送り、XML を受け取る
        c = (HttpURLConnection)
          new URL(REST_SERVER + path).openConnection();
        c.setRequestMethod("POST");
        c.setDoOutput(true);
        c.setRequestProperty("Content-Type" , "application/xml");

        c.connect();

        OutputStream os = c.getOutputStream();

        Marshaller m = jc.createMarshaller();
        m.marshal(calc , os);

        os.close();
      }else if("json/xml".equals(path)){
        // JSON を送り、XML を受け取る
        c = (HttpURLConnection)
          new URL(REST_SERVER + path).openConnection();
        c.setRequestMethod("POST");
        c.setDoOutput(true);
        c.setRequestProperty("Content-Type" , "application/json");

        c.connect();

        OutputStream os = c.getOutputStream();

        PrintWriter pw = new PrintWriter(os);
        pw.print("{"value1" : "" + calc.getValue1() +
          "" , "value2" : "" + calc.getValue2() +
          "" , "operator" : "" + calc.getOperator() +
          ""}");
        pw.close();

        os.close();
      }else{
        throw new Exception("path 引数が正しくありません。");
      }

      InputStream is = c.getInputStream();

      Unmarshaller u = jc.createUnmarshaller();
      Calc result = (Calc)u.unmarshal(is);

      is.close();
      c.disconnect();

      out.println(result.getValue1() + " " + result.getOperator()
	+ " " + result.getValue2() + " = " + result.getAnswer());

      out.close();
    }catch(Exception e){
      throw new IOException(e.toString());
    }
  }
}
 このServletは、calcForm.htmから呼び出します。
<html>
<head></head>
<body>

<form action="./client/calc" method="POST">

計算式:<br />
<input type="text" name="value1" size="10" value="1" /> 
<input type="text" name="operator" size="3" value="+" /> 
<input type="text" name="value2" size="10" value="1" />
<br />
<br />

リクエストを送りたいサービスのパス:<br />
<input type="radio" name="path" value="query/xml"
 checked="checked" />query/xml 
<input type="radio" name="path" value="xml/xml" />xml/xml
<input type="radio" name="path" value="json/xml" />json/xml
<br />
<br />

<input type="submit" value="計算" />
</form>

</body>
</html>
 正しく動作した場合、3つあるラジオボタンのどれを使用しても表示される結果は同じですが、query/xmlであればGET方式を用い、引数の形でデータを送信しますし、xml/xmlならXML形式で、json/xmlならJSON形式でデータを送信します。いずれの場合もXMLが返され、ServletがそれをJAXBで解析、計算結果をテキスト形式として表示します。
 calcAjax.htmは、xmlToJson、jsonToJsonの2種類のメソッドを呼び出します。こちらはServletなどを使用せず、RESTサーバーに直接アクセスしています。
<html>
<head>
<script language="JavaScript"> 
function createHttpRequest(){
	try{
		return new ActiveXObject("Microsoft.XMLHTTP");
	}catch(e){
		return new XMLHttpRequest();
	}
}

var request = null;
function getResult(){
	var path = "";

	for(var i = 0; i < calc.path.length; i++){
		if(calc.path[i].checked){
			path = calc.path[i].value;
			break;
		}
	}

	var value1 = calc.value1.value;
	var value2 = calc.value2.value;
	var operator = calc.operator.value;

	var senddata = "";
	var ctype = "";

	if(path == "json/json"){
		// JSON 形式でデータを送信
		ctype = "application/json";

		senddata = '{"value1":"' + value1 +
			'" , "value2":"' + value2 +
			'" , "operator":"' + operator +
			'"}';
	}else if(path == "xml/json"){
		// XML 形式でデータを送信
		ctype = "application/xml";

		senddata += '<?xml version="1.0"?>';
		senddata += '<calc>';
		senddata += '<value1>' + value1 + '</value1>';
		senddata += '<value2>' + value2 + '</value2>';
		senddata += '<operator>' + operator +
			'</operator>';
		senddata += '</calc>';
	}else{
		return;
	}

	if(request == null)
		request = createHttpRequest();
	else
		request.abort();

	request.onreadystatechange = function(){
		if(request.readyState == 4 && request.status == 200){
			var calc = eval("(" + request.responseText + ")");
			var str = calc.value1 + " " + calc.operator +
				" " + calc.value2 + " = " + calc.answer;
			document.getElementById("result").innerHTML = str;
		}
	};

	request.open("POST" , "./restserver/calc/" + path , true);
	request.setRequestHeader("Content-type" , ctype);
	request.send(senddata);
}
</script>
</head>

<body>

<form name="calc" onsubmit="getResult();return false">

計算式:<br />
<input type="text" name="value1" size="10" value="1" /> 
<input type="text" name="operator" size="3" value="+" /> 
<input type="text" name="value2" size="10" value="1" />
<br />
<br />

サービスのパス:<br />
<input type="radio" name="path" value="json/json"
 checked="checked" />json/json
<input type="radio" name="path" value="xml/json" />xml/json
<br />
<br />

<input type="submit" value="送信" />

<div id="result">(ここに結果が表示されます)</div>
</form>

</body>
</html>
 json/jsonとxml/jsonのどちらをチェックしても、返されるデータはJSON形式ですので、evalでJavaScriptにそれを解釈させるだけで復元が完了します。

 後は次のURLを開き、いずれのチェックを選択した場合でも正しく動作すれば成功です。

(アプリケーションのURL)/calcForm.htm
(アプリケーションのURL)/calcAjax.htm

 いずれの場合も結果は全く同じですが、CalcServlet.javaとcalcAjax.htmの実装の通り、やり取りされているデータ形式はそれぞれ全くの別物です。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

全日本有名人人気投票
2010/04/18(Sun)23:44:24
 今度は民主党が参院選候補として落語家を擁立することが明らかとなりました。民主党は以前にもニュースキャスターを擁立する動きを見せており、それに続くタレント候補となります。その他、自民党や乱立小政党などの他党も有名人を擁立したり、あるいは擁立することを検討、もしくは広告塔に用いるなどしており、参院選には様々な有名人が出馬あるいは登場する可能性が出てきました。
 一体民主党は何を考えているのでしょうか。かつて民主党は「さくらのパパ」なる有名人を擁立したことがありますが、この人は後に賭博が発覚して問題となり、民主党の印象にダメージを与えました。他党の例を出せば、自民党が料理研究家を当選保障で擁立した際には、小選挙区で落選するも比例1位のため復活当選し、その後には「料理番組」を理由に郵政の採決を欠席、批判を浴びています。また、事実上自民党に擁立されて出馬、落選した堀江氏は後に逮捕され、自民党は氏が無所属で出ていた事実を利用し、しっぽ切りに走りました。この通り、有名人を擁立したところで、ろくな結果にならないのは見えています。どうやら民主党は先の教訓から全く何も学んでいなかったようです。
 その上、日本には「世の中を変えなくてはならない」という志を持って勉学に励み、政治家を目指している人も少なからず存在します。客寄せパンダの席を1つ用意するたびに、志ある者の席が1つ減少することを考えれば、タレントを擁立するなどという行為はあまりにバカげており、とても容認できるものではありません。
 ただ、民主党の行動があまりに愚かである点は疑いようもありませんが、これは民主党だけの責任というより、現行の日本政治の責任、ひいては日本国民の責任であることも、指摘しないわけにはいきません。
 2005年の衆院選時、自民党は広告会社スリードの選挙戦略に基づき、具体性を伏せた上で「郵政」のみをひたすら訴え、あらゆる説明責任を意図的に放棄、さらには料理研究家や堀江氏のような有名人を擁立し、話題性によって大量の議席を取得しました。私はこの衆院選の最中、国民は自民党のあまりの侮辱に必ず怒り、その怒りは自民党を揺るがすであろうと考えていましたが、結果は失望に終わりました。
 失望を抱いたのは民主党議員も同じであるらしく、2009年の衆院選でおよそ意味の分からない政策を言い出したのも、2005年の衆院選で消費税増税などの「苦い」政策を掲げたところ、低IQ選挙戦略と有名人擁立を行った自民党に大敗し、まじめに公約を作っても全く無駄であると知らされたため、甘言を言い立てるよりなかったとの事情もあるようです。自分が作った公約が守れずに苦しんでいるのですから、「自業自得」の一言で片付けたくもなりますが、各党が理想論を並べ立てるだけの不健全な選挙がなされる責任の一端は、確かに国民にもあるはずです。
 また、自民党は2005年の衆院選以後にも、タレントの郷ひろみ氏や宮崎県知事の東国原氏を擁立しようとしたり、自分が事実上の解雇にしたはずの文民統制違反者・田母神氏を擁立しようとしたり、「美人すぎる市議」を擁立する動きを見せたりと、姑息な手段を繰り返しています。自民党がこのような擁立を繰り返すため、対抗上民主党も同様の行為に走らなくてはならないのであれば、自民党が悪いともいえますが、もとはといえばそのようなタレントを支持したり、政治家に侮られるような行動ばかり取る国民に問題があるのです。
 2009年の衆院選の際には、新聞コラムなど一部に「国民は前回衆院選のイメージ選挙に懲りた」との見解を表明する者も存在しましたが、実際にはほとんど変化はありません。麻生内閣時に散々世襲議員が批判されたにもかかわらず、逆風の中で小泉進次郎氏があっさり当選した上、同氏の定員50人のツアーに5000人もの応募があったことからも、それが伺えます。世の中、なぜか小泉氏を過大評価する早とちりな人も存在するようですが、有名な元首相・小泉氏の世襲であるがために目立ってはいるものの、就任からの日数を考えれば当然ながら、小泉氏は今のところ答弁を無難にこなす程度の実績しかなく、客観的には特に高く評価できるだけの結果を残してはいません。もし答弁が上手く、人気があるのが良い政治家であるというのなら、麻生氏はその両方を満たしていたはずです。
 さらには、タレント選挙は大政党だけにとどまらず、小政党の間にまで広がってしまう恐れがあります。2005年の衆院選より、自民党はなりふり構わず有名と見た人物を擁立しようとしていますし、民主党もそれに対抗してか、それとも起死回生のためか、今回の参院選では有名人の擁立を進めています。また、小政党も力の弱さをカバーするために話題性が必要であるからと、有名な知事らを広告塔に使おうとするなどしており、今の日本は政策本位の政治が最も必要な状況でありながら、選挙がまたもタレントの人気投票状態になり始めています。二大政党がくだらないタレント選挙を行っており、小政党がそのような選挙に疑問を呈しているならまだしも、これでは小政党も民主・自民と何ら変わるところがありません。
 また、国民の上記のような態度は、人格も政策もおよそ政治家の器に程遠いながら、なぜか人気だけはある舛添氏のような人物をのさばらせる原因ともなっています。無賃残業合法化にあれほど大反対し、政治家の些細な問題発言や空約束にあれほど荒れ狂う世論が、無賃残業合法化を強力に推進するばかりか、これを「家庭だんらん法案」と言い換えれば通ると発言するほど国民を愚弄し、各種暴言や空約束を行っている舛添氏を支持するのは、いかに少なくない国民が政策や人格を見ようとせず、「人気」を見ているかを体現しています。
 いずれにせよ、国民の態度がタレント選挙を生み出しており、タレント選挙がろくな結果を生まないことだけは、これまでの例からもはっきりしています。日本が座礁域の真っ只中にある状況で、果たしてタレントの人気投票で船長を決めてしまうのが正しいやり方なのか、十分に考える必要があります。
 政党の側も同様です。もし民主党が本気で今後の政権運営を行う意思を持っており、国民に理解と支援を求めたいのであれば、同党は今からでもタレントや落語家の擁立を撤回すべきです。小沢代表以後の変質を正し、タレントを擁立するような姑息な真似もやめれば、それが自動的に自民党との差別化にもつながりますし、分かっている人からは支持が得られるに違いありません。
 自民党の側も、例えば小泉進次郎氏を広告塔として利用すれば、確かに短期的にはある程度の人気が得られるでしょう。しかし、同党がこのような世襲を容認している限り、同党が「保守政党の経済政策」として「機会の平等」を唱えても、支持が得られるわけがありません。まして、仮に小泉氏がそれを唱えるようなことがあれば、説得力はゼロに等しいと言わざるを得ません。また、2005年の選挙では政策の長短をしっかり説明せず、低IQ戦略及びタレント選挙に持ち込んだため、案の定襲ってきた「存在しないはずの」副作用によって支持を失い、これが後の敗北の土壌となりました。これの二の舞を演じるつもりがなければ、いい加減にこのような姑息な方法を用いるのはやめるべきです。

 ただ単に結果を返すだけでもServletより簡単なJAX-RSですが、単純にパスやパラメータを受け取って文字列を返すだけでは、せいぜい「簡略化されたServlet」でしかありません。RESTを標榜するからには、XMLによるデータのやり取りも必要となるでしょう。
 JavaによるXMLといえば、今のところSAX、DOM、StAX、JAXBが有名どころです。しかし、前者3つはそれこそ自分でXMLを解析していかなくてはならず、これではServletで処理するのと全く変わりません。そもそもパース処理がコードのほとんどを占める状況にもなりかねず、開発が大変面倒になります。ここはWebServiceでも用いたJAXBを使用するのがよさそうです。
 そして実際、JAX-RSはXMLのオブジェクト化及びオブジェクトのXML化を自動的に行う仕組みを提供しています(マニュアルの記述によれば、String、byte[]、JAXB、JSONなど、様々な形式を普通に読み書きできるようになっているとのこと)。しかもその使い方といえば、引数や返り値に任意の型を用いるだけであるというのです。これが本当であれば、何とも簡単です。
 以下、簡単な計算機を実装しています。RESTの処理を行うクラスに加え、JAXBで変換を行う@XmlRootElementクラスが1つ、それにXMLリクエストを送受信する動作テスト用Servletが1つで、クラスは3つとなりました。
/WEB-INF
 /classes
  /com
   /yamicha
    /rs
     /server
      @XmlRootElement Calc.java
      @Path CalcService.java
     /client
      @WebServlet CalcServlet.java
 web.xml
 アノテーションのおかげで役割分担が明白です。
 web.xmlは前回と全く同様です。Servletは@WebServletで必要な情報を指定していますので、ここでは特に何も書いていません。
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>
  <display-name>JAX-RS Servlet</display-name>
  <description>JAX-RS Servlet</description>

  <servlet>
    <servlet-name>jax-rs</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.yamicha.rs.server</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>jax-rs</servlet-name>
    <url-pattern>/restserver/*</url-pattern>
  </servlet-mapping>
</web-app>
 Calc.javaはデータ保持用のクラスだけに、中身は完全にJavaBeanです。左辺値、右辺値、演算子、答えの4つのデータを保持できるようにしています。
package com.yamicha.rs.server;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="calc") public class Calc{
	private String value1;
	private String value2;
	private String operator;
	private String answer;

	public Calc(){
	}

	@XmlElement(name="value1") public String getValue1(){
		return value1;
	}
	@XmlElement(name="value2") public String getValue2(){
		return value2;
	}
	@XmlElement(name="operator") public String getOperator(){
		return operator;
	}
	@XmlElement(name="answer") public String getAnswer(){
		return answer;
	}

	public void setValue1(String s){
		value1 = s;
	}
	public void setValue2(String s){
		value2 = s;
	}
	public void setOperator(String s){
		operator = s;
	}
	public void setAnswer(String s){
		answer = s;
	}
}
 CalcService.javaはこれを解析して処理を行うクラスなのですが、XMLとの相互変換はJerseyが勝手にやってくれるため、かなりシンプルな記述で済んでいます。同じJAXBでも、WebServiceを書く際にはそれなりに苦労した記憶がありますが、こちらは全く難しい要素がありませんでした。
package com.yamicha.rs.server;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("calc") public class CalcService{
	public CalcService(){
	}

	// 動作テスト用
	// ブラウザからでも結果 XML の取得が可能
	@GET @Path("query") @Produces("application/xml")
		public Calc queryCalc(
		@QueryParam("value1") String v1 ,
		@QueryParam("operator") String op ,
		@QueryParam("value2") String v2){
		Calc calc = new Calc();
		calc.setValue1(v1);
		calc.setValue2(v2);
		calc.setOperator(op);

		return jaxbCalc(calc);
	}

	// XML を受け取り、計算結果を記入した XML を返す
	@POST @Path("jaxb") @Produces("application/xml")
		public Calc jaxbCalc(Calc calc){
		try{
			// プロパティはいずれも String 型であるため
			// double として扱っても文字列の連結処理をしても
			// 構わないのだが、今回は int として計算している
			int answer = 0;

			int v1 = Integer.parseInt(calc.getValue1());
			int v2 = Integer.parseInt(calc.getValue2());
			String operator = calc.getOperator();

			// 使用できる演算子として
			// とりあえず + , - , * , / , ** を実装
			if("+".equals(operator))
				answer = v1 + v2;
			else if("-".equals(operator))
				answer = v1 - v2;
			else if("*".equals(operator))
				answer = v1 * v2;
			else if("/".equals(operator))
				answer = v1 / v2;
			else if("**".equals(operator))
				answer = (int)Math.pow(v1 , v2);
			else
				return calc;

			calc.setAnswer(String.valueOf(answer));
		}catch(NumberFormatException e){
		}

		return calc;
	}
}
 今回は「POSTでXMLを受け取り、計算結果を格納したXMLを返す」メソッドも実装しているため、クライアント側となるServletも実装しました。名前はCalcServlet.javaとしました。Jerseyにはテスト用の機能も付属しているらしいのですが、どうもJersey固有の機能らしいため、ここではHttpURLConnectionでごく普通に処理を行っています。
package com.yamicha.rs.client;

import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.servlet.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.*;
import com.yamicha.rs.server.*;

@WebServlet(name="calcservlet" , urlPatterns={"/client/calc/*"})
  public class CalcServlet extends HttpServlet{
  private final static String REST_SERVER = 
    "(このアプリケーションの URL)/restserver/calc/";

  public void doPost(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{
    doGet(request , response);
  }
  public void doGet(HttpServletRequest request ,
    HttpServletResponse response) throws IOException{

    if(request.getParameter("operator") == null){
      // 計算(右辺値・左辺値・演算子)入力フォーム
      response.setContentType("text/html;charset=Shift_JIS");
      PrintWriter out = response.getWriter();

      out.println("<html><head></head><body>");
      out.println("<form method="POST">");
      out.println("<input type="text" name="value1" size="10" value="1" /> ");
      out.println("<input type="text" name="operator" size="3" value="+" /> ");
      out.println("<input type="text" name="value2" size="10" value="1" />");
      out.println("<input type="submit" value="計算" />");
      out.println("</form>");
      out.println("</body></html>");
    }else{
      // 入力されたデータを XML 化して送り、計算結果を受け取って表示
      try{
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();

        // Calc を作成
        Calc calc = new Calc();
        calc.setValue1(request.getParameter("value1"));
        calc.setValue2(request.getParameter("value2"));
        calc.setOperator(request.getParameter("operator"));

        // JAXBContext を作成
        JAXBContext jc = JAXBContext.newInstance(Calc.class);

        // HttpURLConnection を作成
        // Content-type は application/xml
        // データを POST するので、setDoOutput(true) が必要
        HttpURLConnection c = (HttpURLConnection)
          new URL(REST_SERVER + "jaxb").openConnection();
        c.setRequestMethod("POST");
        c.setDoOutput(true);
        c.setRequestProperty("Content-Type" , "application/xml");

        c.connect();

        // XML を POST する処理
        OutputStream os = c.getOutputStream();

        // Calc を XML に変換してストリームに書き込む
        Marshaller m = jc.createMarshaller();
        m.marshal(calc , os);

        os.close();

        // 結果を受け取る
        InputStream is = c.getInputStream();

        // ストリームから XML を読み取り、Calc に変換
        Unmarshaller u = jc.createUnmarshaller();
        Calc result = (Calc)u.unmarshal(is);

        is.close();
        c.disconnect();

        // 結果を表示
        out.println(result.getValue1() + " " + result.getOperator() + " " +
          result.getValue2() + " = " + result.getAnswer());

        out.close();
      }catch(IOException e){
        throw e;
      }catch(Exception e){
        throw new IOException(e.toString());
      }
    }
  }
}
 無論、これは別に無理にJavaで書く必要はなく、PerlやPHPなどのスクリプト言語からリクエストを送ったり、あるいは通常のクライアントサイドのアプリケーションからリクエストを送るなどしても、XMLさえ正しく作成及び解析できているのであれば、同様に動作するはずです。
 後は実際に実行してみるだけです。せっかくCalcService.javaにGETの場合の処理も書いたことですし、どのようなXMLが生成されるかをチェックしておくのも面白そうですので、ひとまずブラウザから開くことにしました。

(アプリケーションのURL)/restserver/calc/query?value1=左辺値&operator=演算子&value2=右辺値

 今回の実装では、左辺値と右辺値はintの範囲の整数である必要があります。また、演算子には+、-、*、/、**が使用できます。ただ、JAX-RSを使用するような開発者にいちいち断る必要はなさそうですが、URLは当然エンコードしなくてはなりません。+記号は%2B、-は%2D、*は%2A、/は%2Fです。
 実際に以下のURLを開いてみたところ、

(アプリケーションのURL)/restserver/calc/query?value1=5&operator=%2D&value2=3

 次のような結果が得られました。
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<calc>
  <answer>2</answer> 
  <operator>-</operator> 
  <value1>5</value1> 
  <value2>3</value2> 
</calc>
 次はServletですが、こちらは@WebServletアノテーションの記述の通り、以下のURLにマッピングされています。

(アプリケーションのURL)/client/calc

 フォームに必要事項を入力し、正しく計算が行えれば成功です。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

たちどまる日本
2010/04/09(Fri)22:50:48
 与謝野氏や平沼氏などを中心として、新党「たちあがれ日本」が発足となりました。届出上の代表は平沼氏ですが、与謝野氏は同格の共同代表のポストに就任し、参加者は5名で政党要件も満たしています。参院選においては、比例を中心に10名以上の擁立を検討しているようです。
 ところが、新党が標的としている現政権党からの批判ならまだしも、自民党総裁の谷垣氏からも「与謝野氏は小選挙区敗北での復活当選であるが、それなのに離党するのはおかしい」と評されるなど、自民党内にも批判的な見方が多く存在する上、構成人員がベテラン議員ばかり(平均年齢70歳近く)であることを理由として、「シルバー新党」「立ち枯れ日本」と揶揄されたりと、国民や政党の間で支持を集められるかは不透明な情勢です。
 私は麻生政権下の大混迷の時期より、与謝野氏の手腕に一定の期待を持っており、麻生氏失脚後は与謝野氏が自民党を立て直して復帰させ、日本に二大政党制が定着することを期待していましたが、どうやら私は与謝野氏を買いかぶりすぎていたようです。かつて谷垣氏に期待した際には、「和魂党」や田母神氏擁立問題、また理念なき欠席戦術などで大変失望させられましたが、与謝野氏の器も谷垣氏と同じかそれ以下であると評するよりありません。
 与謝野氏の理念の乏しさについては、以前に指摘している通りです。すなわち、与謝野氏は「(鳩山内閣で)普段なら内閣が倒れるような事件が起きているにもかかわらず、自民党の評価が高まっていないことには、深い反省、思いを抱かないといけない」と発言し、谷垣体制のやり方のまずさを批判していますが、相手の過失をあげつらったところで自分の支持が回復するわけではないのは当然です。もし自民党が支持を取り戻したいのであれば、他人の過失に付け込むのではなく、自分の悪い点を改善するよう努め、支持を得られない原因を解消しなくてはなりません。上記の発言から察するに、与謝野氏はそれを自覚できていないらしいため、私は与謝野氏の新党構想に強い懸念を抱いていました。
 そして今回、その懸念は現実のものとなりました。与謝野氏は自身の勉強会の会合で、新党について「自民党を分裂させるためではない。徹底的な反民主党を貫く。捨て石になったつもりで頑張る」と発言していますが、まさに「新党」が新党として意味を成さないことを証明するかのような発言です。
 通常、「政党」は何らかの政策を実現させるための組織ですし、そうであるからこそ選挙では政策を掲げ、その政策に賛同した国民の支持により国会に議席を有し、国の政策決定に参加する仕組みとなっています。したがって、仮に新党が掲げた政策に自民党が反発し、民主党は賛同しているような場合、相手が民主党だからという理由で政策実現を拒否するようなことがあれば、まず道理に合いません。
 しかし、与謝野氏は新党について「反民主党を貫く」と発言しており、完全に手段と目的が逆転しています。どうしても実現しなくてはならない理念があり、自民党の理念では実現できないから党を去るというならまだしも、党の目的が「反民主党」とは、理念や政策以前にあまりにも子どもじみており、あきれて物も言えません。これが本当に「ベテラン」と呼ばれる議員の行動でしょうか。
 このような子どもだましの新党が、自民党にも民主党にも愛想をつかした人を取り込めると本気で考えているなら、与謝野氏や平沼氏はあまりに国民を愚弄しています。ここまで独自の理念を持たない政党となれば、おそらく当面は自民党の衛星政党として機能することになるはずですが、それでいて自民党に失望した人の受け皿になろうとは、自民党に今までの責任をすべて押し付け、自分はおいしいところだけを取ろうとしていると批判されても仕方がありません。
 つくづく、ベテランと呼ばれる人であっても、また手腕に期待できそうな人であっても、実像は分からないものです。当初は与謝野氏に期待していた私も、今となっては「このような理念も正当性もない人間が自民党総裁にならなくて良かった」の一言しかありません。自民党の側も、与謝野氏や平沼氏の行動と連鎖反応に戦々恐々とするよりは、むしろ自分で処置するまでもなく膿が排出されたと好意的に解釈し、党再生に弾みをつけた方が建設的です。
 また、これは平沼・与謝野両氏の新党に限りませんが、私は最近の政治状況に強い危機感を覚えています。小泉氏の次男がもてはやされることに始まり、自民党は自らが事実上の退職処分にしたはずの田母神氏を擁立しようと試みたり、「美人すぎる市議」を立てようとしてみたり、その他様々なタレントや有名人を起用しようとしています。対する民主党も、有名なキャスターを擁立しようとするなど、程度の差こそあれ、やっていることは自民党とほとんど変わりません。さらには首長連合などの小規模集団も、その弱さを有名人の話題性に求めようとしており、各党が大小競い合って人気投票に持ち込もうとしているような状態です。これでは政権交代の定着どころか、時計の針が郵政解散時まで逆戻りしてしまいます。この混迷の状況下で、タレントの人気投票によって国の行方が決まるようなことが許されるのでしょうか。
 そして何より気がかりなのは、舛添氏のように人気だけが先行し、思想や理念が伴わない人物の動向です。これまでの発言や主張内容、主張政策からすれば、明らかにそれにふさわしい人物でないのは明白でありながら、先の世論調査では首相にふさわしい人の1位に舛添氏が挙げられており、どうしても懸念を抱かないわけにはいきません。平沼・与謝野新党がまるで理念の存在しない、ただ自民党の看板を外しただけの政党である以上、ここが第三極として受け皿になる可能性は非常に低いだけに、舛添氏が第三極として名乗りを上げた場合の影響は相当大きくなると予想されるため、強い警戒が必要です。

 Java EE 6には「JAX-RS」なる新たな機能が導入されています。これはJava EEでRESTを実装するためのもので、Webサービスを実装するJAX-WSとは近い関係にあります。APIリファレンスを読む限り、アノテーションがかなり多用されており、EJB 3.0以降のスタイルで容易に開発できるであろうことが想像できます。
 ところで、「REST」とは一体何なのでしょうか。定義は色々考えられますが、厳密な答えを出すのは困難です。なぜなら、当初は意味が厳密に決まっていたものの、途中で意味が拡大解釈されて収拾がつかなくなり、最終的に意味があいまいになってしまった、いわゆる「バズワード」の典型であるためです。
 Wikipediaを開いてみると、以下のように記述してあります。
RESTは、初めはアーキテクチャの原則と制約の集まりを指していたが、次第に、XMLやHTTPを使った簡易なウェブベースのインターフェイスのうち、WebサービスのSOAPプロトコルのような MEP(Message Exchange Pattern; SOAPノード相互のメッセージ交換のパターンを確立するための雛型)ベースの特別な抽象化をしないもののことを、大まかに意味する用語として使われるようになった。RESTは次に述べるように2つのやや異なる意味で使われている。
  • FieldingのRESTアーキテクチャスタイルの原則に合わせたWebサービスシステム。
  • RPCスタイルに合わせた簡易な XML+HTTP インターフェイスを採用したシステム(SOAPは使わない) 。
 すなわち、困ったことに定義が複数存在し、しかも定義の境界があいまいである(これはRESTだが、これはRESTではない、と定めるのが難しい)というのです。
 ひとまず、Java EE 6では主に以下のような操作が提供されているようです。
  • GET、POST、PUT、DELETEなど、任意のメソッドに応じた処理の呼び出し。
  • 拡張パス及びクエリに応じた処理の呼び出し。
  • 送信データを任意の形式(クエリ文字列、単純な文字列、XML、JSONなど)で受け取り、また返却する処理。
  • その他、クッキー周りなど付加的な処理。
 念のために書いておくと、メソッドのうちGETとPOSTは有名ですが、もともとGETはデータ取得、POSTはデータの登録、PUTはデータの更新、DELETEはデータの削除を意図して作られたものです。
 今回はとりあえず、「特定のURLにGETでアクセスすると、任意の結果を文字列で返す」だけのRESTを書いてみます。実際にはPOSTでもPUTでもDELETEでも、またXMLでもJSONでも何でも受け付けてくれますが、もともとRESTは利用者のブラウザと対話するというより、あるサービスが別のサービスに対する操作を行う(例えば、あるブログは関連する書籍を表示する機能を有している。ユーザーがブログにアクセスすると、ブログはRESTを使って書籍検索システムにアクセスし、検索結果を取得する。それをユーザーの画面に表示する)側面が強いため、少し複雑なものになるとXMLなどを送信したりしなくてはならず、単純にブラウザを使ってテストするのが難しくなり、アクセスする側のプログラムもセットで書く必要が出てきて、本来関係のないコードが増えてしまうためです。
 まずは単純明快に、引数も何も受け取らず、ただ単にメッセージを返すだけのものを作成してみます。いわゆるHello Worldです。
 今回用意したのは、単純明快に以下の2つのファイルのみです。
/WEB-INF
 /classes
  /com
   /yamicha
    /rs
     /server
      Hello.java
 web.xml
 上記2つのファイルを用意するだけで、まがりなりにもJAX-RSを利用できるのですから、その簡単さは容易に想像できます。この技術がもしEJB 3.x以前に発表されていたら、おそらく地獄を見たでしょう。
 まずはweb.xmlですが、これはほとんど「お約束」でしょう。事実、以下のXMLもほぼSunのサンプルの丸写しです。
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>
  <display-name>JAX-RS Servlet</display-name>
  <description>JAX-RS Servlet</description>

  <servlet>
    <servlet-name>jax-rs</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.yamicha.rs.server</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>jax-rs</servlet-name>
    <url-pattern>/restserver/*</url-pattern>
  </servlet-mapping>
</web-app>
 やや重要なのがinit-paramで、ここで処理の対象とするパッケージ名を指定しなくてはならないようです。この場合では、com.yamicha.rs.serverパッケージが対象となります。
 また、Sunのサンプルによれば、アプリケーションのクラスを指定する記述として
<init-param>
  <param-name>javax.ws.rs.Application</param-name>
  <param-value>com.example.ClassName</param-value>
</init-param>
 なるものも存在するようです。むしろ、前者のパラメータ名がcom.sun.jersey.config.property.packagesなのに比べ、後者はjavax.ws.rs.Applicationですから、後者の方が標準的な方法であって、前者はJerseyの独自拡張と考えた方が正しいかもしれません。
 servlet-mappingのurl-patternとしては、今回は/restserver/*を用いましたが、当然ながら好きなように記述して構いません。
 Hello.javaは以下の通りです。
package com.yamicha.rs.server;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("hello") public class Hello{
	@GET @Path("message") public String sayHello(){
		return "Hello JAX-RS!";
	}
}
 何とごく普通のServletより簡単です。むしろ、これで本当に動くのかが不安になってきます。
 後はこれをデプロイし、ブラウザから次のURLにアクセスするだけです。

(このアプリケーションのURL)/restserver/hello/message

 restserverはweb.xmlで定めたurl-patternに基づくもので、helloはクラスの@Pathアノテーションに基づきます。また、messageはメソッドの@Pathアノテーションに基づきます。

 いくら簡単なのが良いこととはいえ、これだけではあまりにも面白くありませんので、ついでに「拡張パスとして文字列を受け取り、それをそのまま表示する実装」と「パラメータとしてv1とv2を受け取り、足し算して返す実装」も追加してみるとしましょう。
package com.yamicha.rs.server;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("hello") public class Hello{
	public Hello(){
	}

	@GET @Path("message") public String sayHello(){
		return "Hello JAX-RS!";
	}

	@GET @Path("say/{msg}") public String sayMessage(
		@PathParam("msg") String msg){
		return msg;
	}
	@GET @Path("calc") public String calc(
		@QueryParam("v1") String v1 , @QueryParam("v2") String v2){
		try{
			return String.valueOf(
				Integer.parseInt(v1) + Integer.parseInt(v2));
		}catch(NumberFormatException e){
			return "正しい数字ではありません。";
		}
	}
}
 非常に簡単な上、見た目からして意味も明白です。
 後は以下のURLにアクセスするだけです。

(文字列表示)
(アプリケーションのURL)/restserver/hello/say/Hello

(計算)
(アプリケーションのURL)/rs/restserver/hello/calc?v1=16&v2=32

 アノテーションの導入で大きく変わったJava EEですが、いずれもせいぜい「XMLの代わりにアノテーションを使えるようにして、XMLを削減する」程度の消極的なものが多い印象でした(もともとXML前提の仕様がアノテーションでも書けるようになったものであるので当然ですが)。しかし、JAX-RSでようやくそのような消極的なアノテーションから、「XMLなどの記述を不要にするとともに、コードの意味を分かりやすくする」という積極的なアノテーションに転じてきたようです。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

代理十票
2010/04/04(Sun)08:25:19
 参院自民党の若林氏が、何と隣席の青木氏の投票ボタンを本人退席中に勝手に操作したことが発覚し、大問題になっています。民主党は若林氏への懲罰動議を提出しましたが、自民党が若林氏に圧力をかけたこともあってか、氏は自ら議員辞職願を提出して議員辞職、謝罪を行いました。
 このようなことがまさか本当に発生するとは、驚愕を禁じ得ないとしか言いようがありません。しかも、例えば杉村氏のような不見識な「チルドレン」がそれを行ったのならともかく、「良識の府」として被選挙権が衆院より厳しく設定されている参院において、しかも75歳のベテランである若林氏がこのような大失態を犯したのですから、なおさら唖然とさせられます。
 本件に対する反応を見てみると、さすがに社説などでは若林氏を擁護するものは見当たりませんが、中にはなぜか民主党などへの責任転嫁を図ろうとしている内容のものもあり、大変理解に苦しみます。また、個人レベルでは「なぜここまで大騒ぎしなくてはならないのか」といった意見もごく一部に存在しますが、いくら個人の意見であるとはいえ、あまりにも不見識過ぎるとしか評しようがありません。
 本件について、民主党の姿勢を批判したり、あるいは党議拘束について批判したりする意見に関しては、それはそれとして意義のあるものではありますが、その種の議論は本件とは別の議論として行うべきです。なぜなら、仮に民主党の姿勢が評価できるものではなかったり、党議拘束が矛盾のある制度であったとしても、勝手に他の議員の投票を決定する行為の罪はいささかも軽減されず、何の言い訳にもならないためです。氏のような行動は、党議拘束が存在しようがしまいが、民主党がいかなる状況であろうが、等しく重大行為として評価されなくてはならず、民主党がどうこうといったことは何の免罪符にもならない、全く無関係の事柄です。
 ましてや、本件を大した問題でないと評する人間に対しては、唖然とする以外にありません。もし本件のような問題がほとんど、あるいは全く問題視されずに終わってしまえば、他の幾人もの議員が勝手に他人の投票権を行使したり、あるいは欠席・退席する議員が他の議員に代理投票を頼んだりといった行為が日常的に横行し、日本の議会制度が大混乱に陥り、根底から崩壊してしまう状況にもなりかねません。だからこそ、本件における若林氏の行為が最大限の非難を浴びるのは当然ですし、議員辞職でもあがないきれないほど重い問題なのです。
 一方、自民党の「タガの緩み」に原因を求める声もありますが、本件はもはや「タガの緩み」以前の問題です。本件について自民党に責任がないかといえば、全くのゼロであるとまでは言い切れませんが、これまでにも自民党内で同様の行為が横行していたならまだしも、そうでないなら基本的には議員個人の資質や自覚の問題です。タガが緩もうが緩むまいが、他人の分の投票を勝手に行ってはいけない程度のことは、数百分の一もの投票権を行使できる国会議員どころか、一億分の一程度の投票権しか行使できない一般国民でも知っています。
 また、自民党に関しては、衆院選敗北後の首相指名選挙では若林氏に投票する方針として氏を立てておきながら、本件が問題になると「トカゲの尻尾切り」のごとく若林氏を見限って批判に回り、議員辞職に追い込んだ同党の姿勢を批判する意見も一部に存在するようです。
 確かに、党内の都合でこのような不見識な人物を担ぎ上げ、可決はされないにせよ首相にまで指名した点は、自民党にも問題があります。安部氏や麻生氏を担いで失敗した図式そのままで、しかも自民党はその後も田母神氏を立てようとしてみたり、「美人過ぎる市議」なるもので話題づくりに励んだりと、全く反省がありません。自民党に対してそのようなやり方への反省を求めるのは、極めて妥当な意見でしょう。
 しかし、問題発覚後の自民党の厳しい対応は、決して非難されるべきものではありません。本件において自民党が若林氏をかばったのであれば、同党が代理投票行為を「取るに足らない問題」と評価したことになり、そちらの方が大問題であるためです。この問題は議員辞職でも足りないほど重いものですから、もし自民党がその肩を持っていたらと考えるとぞっとしますし、当然ながら許されざる行為です。
 それにしても不思議で仕方ないのが、本件が「若林氏の長男の出馬に影響を与えるかもしれない」という報道です。小泉氏の次男といい、自民党はいつまで時代遅れの世襲行為を繰り返せば気が済むのでしょうか。自民党は「民主党政権は社会主義」などとえらそうなことを言ったりしていますが、元首相の子が世襲し、首相に指名しようとした人物の子まで世襲する以上、少なくとも自民党に「機会の平等」を唱える権利はありません。また、世襲は世襲でも「子に政治家としての実力があり、親がたまたま議員であった」場合の世襲にまで文句をつけるつもりはありませんが、それなら親の議員としての失態がなぜ子に関係するのでしょうか。親の議員としての悪評が子の出馬や選挙に影響するならば、親の知名度や評判もまた子に影響することになりますので、これは世襲者のスタートラインが非世襲者と明らかに異なるという裏づけになります。いずれにせよ大変意味不明で、全くわけが分かりません。
 本件は若林氏というあまりにも非常識な議員が起こした問題であり、しかも自民党は氏をかばっているわけでもなく、その責任の多くを自民党に求めるのには無理があります。しかし、代理投票の問題についてはともかく、これほどまでに非常識な人間を首相にまで指名したこと、また未だに平然と世襲を行っている事実が知れ渡ったことにより、自民党の責任が問われたり、評価を落とすのは仕方のないところでしょう。

 ここまででJSF 2.0のcompositeタグの大部分を使用してみましたが、まだactionSourceやvalueHolderといったものが残っています。何やら少々分かりづらそうなタグですが、ひとまず使用してみなくてはなりません。
 JSF 2.0のAPIドキュメントは非常に不親切で、タグの説明を見ただけでは何が何だか分からない場合が大多数であるため、特に初見のタグを使う場合は開発効率も非常に悪くなりがちなのですが、これらについては例外的にそれなりに親切なサンプルが付加されており、概要をつかむことができます。
 actionSourceのサンプルでは、呼び出し側よりf:actionListenerが渡されており、f:actionListenerとセットで使用できるものであることが読み取れます。f:actionListenerはその名の通りActionListenerを用いるタグですから、actionSourceはリスナにかかわる操作が行えるものであると容易に理解できます。
 valueHolderはf:converterとセットで使用されていますが、実際にはconverterの他にvalidator系統も使用できます。このタグを用いれば、以前に行ったようなスマートでないバリデータの渡し方は回避できそうです。
 以下は、これらのタグを用いた検索プログラム(ただし検索の動作は未実装)のサンプルです。
/resources
 /comp
  searchForm.xhtml
/WEB-INF
 /classes
  /com
   /yamicha
    /custom
     SearchBean.java
     SearchListener.java
     TextValidator.java
 web.xml
customSearchForm.xhtml
searchResult.xhtml
 SearchListenerはActionListenerを実装したクラスで、f:actionListenerで用います。TextValidatorはクラスバリデータで、こちらはf:validatorで使用しています。
 web.xmlは例によって前回と同様です。
<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>

  <display-name>JSF 2.0 Custom Component Servlet</display-name>
  <description>JSF 2.0 Custom Component Servlet</description>

  <servlet>
    <servlet-name>jsf20custom</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>jsf20custom</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
</web-app>
 SearchBean.javaはいくつかのデータを保持する他、ActionListener実装クラスのインスタンスを保持するbindingA及びbindingBプロパティ、同じくValidatorの実装クラスのインスタンスを返すasciiValidatorプロパティを用意しています。
package com.yamicha.custom;

import javax.ejb.*;
import javax.annotation.*;
import javax.faces.validator.ValidatorException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.application.FacesMessage;
import javax.faces.component.html.HtmlInputText;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

@ManagedBean @RequestScoped public class SearchBean
	implements java.io.Serializable{
	private String word;
	private String type;
	private SearchListener bindingA;
	private SearchListener bindingB;

	public SearchBean(){
		bindingA = new SearchListener("Binding A");
		bindingB = new SearchListener("Binding B");
	}

	public String getWord(){
		return word;
	}
	public String getType(){
		return type;
	}

	public SearchListener getBindingA(){
		return bindingA;
	}
	public SearchListener getBindingB(){
		return bindingB;
	}

	public void setWord(String w){
		word = w;
	}
	public void setType(String t){
		type = t;
	}

	public void setBindingA(SearchListener s){
		bindingA = s;
	}
	public void setBindingB(SearchListener s){
		bindingB = s;
	}

	public TextValidator getAsciiValidator(){
		return new TextValidator((char)0x0 , (char)0x7F);
	}
}
 SearchListener.javaには、検索ボタンが押された際の動作を記述しています。
package com.yamicha.custom;

import javax.ejb.*;
import javax.annotation.*;
import javax.faces.context.ExternalContext;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

public class SearchListener implements ActionListener{
	private String type;

	public SearchListener(){
		this("Default");
	}
	public SearchListener(String t){
		type = t;
	}

	public void processAction(ActionEvent event)
		throws AbortProcessingException{
		ValueHolder word = (ValueHolder)
			event.getComponent().findComponent("word");
		ExternalContext ec = FacesContext.
			getCurrentInstance().getExternalContext();
		Map<String , Object> request = ec.getRequestMap();

		if(word != null){
			String w = (String)word.getValue();
			if(!w.isEmpty()){
				SearchBean sb = (SearchBean)
					request.get("searchBean");
				if(sb == null)
					sb = new SearchBean();

				sb.setType(type);
				sb.setWord(w);

				request.put("searchBean" , sb);

				try{
					ec.dispatch("searchResult.jsf");
				}catch(java.io.IOException e){
				}
			}
		}
	}
}
 processActionの呼び出しがあると、まずfindComponent("word")で"word"というidを持つコンポーネント(xhtml内部で記述)を取得、それが空でない場合にはSearchBeanのwordプロパティにそれを書き込み、typeプロパティにはSearchListenerが保持するtype文字列を書き込みます。さらにsearchResult.jsfにディスパッチし、結果表示画面を表示するようにします。一方、wordが空の場合には何も行いません。
 TextValidator.javaは単純なバリデータの実装で、単に「文字列の中に指定範囲外のものが見つかったらValidatorExceptionを投げる」だけのものです。
package com.yamicha.custom;

import javax.faces.validator.*;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.application.FacesMessage;
import javax.faces.bean.*;
import javax.faces.event.*;
import java.util.*;

public class TextValidator implements Validator{
	char min;
	char max;

	public TextValidator(char min , char max){
		this.min = min;
		this.max = max;
	}

	public void validate(FacesContext context ,  UIComponent component ,
		Object object) throws ValidatorException{
		String str = (String)object;

		for(int i = 0; i < str.length(); i++){
			if(str.charAt(i) < min || str.charAt(i) > max){
				throw new ValidatorException(
					new FacesMessage(
"入力された文字列の中に、制限の範囲外の文字があります。"));
			}
		}
	}
}
 actionSource及びvalueHolderを使用している、肝心のsearchForm.xhtmlは次の通りです。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

  <composite:interface>
    <composite:attribute name="size" />
    <composite:attribute name="buttonLabel" default="Search" />
    <composite:valueHolder name="word" />
    <composite:actionSource name="searchEvent" />
  </composite:interface>

  <composite:implementation>
    <h:inputText id="word" size="#{cc.attrs.size}" />
    <h:commandButton id="searchEvent" value="#{cc.attrs.buttonLabel}" />
  </composite:implementation>
</html>
 これを使用しているのがcustomSearchForm.xhtmlです。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
</h:head>

<h:body>
  <h:form>
    <b>サンプル検索フォーム(type)</b><br />
    <cc:searchForm buttonLabel="検索(type)">
      <f:actionListener for="searchEvent"
        type="com.yamicha.custom.SearchListener" />
    </cc:searchForm>
  </h:form>

  <!-- テキストボックスに入力がなければエラー -->
  <h:form>
    <b>サンプル検索フォーム(type/validateRequired)</b><br />
    <cc:searchForm buttonLabel="検索(type/validateRequired)">
      <f:actionListener for="searchEvent"
        type="com.yamicha.custom.SearchListener" />
      <f:validateRequired for="word" />
    </cc:searchForm>
  </h:form>

  <!-- 0x00 から 0x7F の範囲外の文字が送信されたらエラー -->
  <h:form>
    <b>サンプル検索フォーム(type/CustomValidator)</b><br />
    <cc:searchForm buttonLabel="検索(type/CustomValidator)">
      <f:actionListener for="searchEvent"
        type="com.yamicha.custom.SearchListener" />
      <f:validator for="word" binding="#{searchBean.asciiValidator}" />
    </cc:searchForm>
  </h:form>

  <h:form>
    <b>サンプル検索フォーム(binding A)</b><br />
    <cc:searchForm buttonLabel="検索(binding A)">
      <f:actionListener for="searchEvent" binding="#{searchBean.bindingA}" />
    </cc:searchForm>
  </h:form>

  <h:form>
    <b>サンプル検索フォーム(binding B)</b><br />
    <cc:searchForm buttonLabel="検索(binding B)">
      <f:actionListener for="searchEvent" binding="#{searchBean.bindingB}" />
    </cc:searchForm>
  </h:form>
</h:body>

</html>
 f:actionListenerのリスナ指定方法には2種類があり、typeの場合にはクラス名を指定します。この場合にはおそらくデフォルトコンストラクタが呼び出され、そうして生成されたインスタンスのprocessActionメソッドが呼び出されます。bindingの場合はリスナのインスタンスが格納されたプロパティを指定し、そのインスタンスのメソッドが呼び出されます。
 上記xhtmlのフォームは上から順に、f:actionListenerのtypeにてクラスの指定を行ったもの、type指定かつ標準バリデータであるf:validatorRequredで"word"をチェックするもの、type指定かつカスタムバリデータで"word"をチェックするもの、f:actionListenerにbindingAプロパティを渡すもの、同じくbindingBプロパティを渡すものの5種類となっています。
 後はリダイレクト先のsearchResult.xhtmlを残すのみです。これはサンプルですから検索は実装していませんが、実装の際にはSearchListenerに検索の動作を書き加え、searchResult.xhtmlで結果を表示すれば、おそらく正しく動作するでしょう。
<?xml version="1.0" encoding="Shift_JIS" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:c="http://java.sun.com/jsp/jstl/core"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:cc="http://java.sun.com/jsf/composite/comp">

<h:head>
  <title>JSF 2.0 Custom Component</title>
</h:head>

<h:body>
  <b>
    <h:outputText value="#{searchBean.type}" />
  </b>
  検索フォームにて
  <b>
    <h:outputText value="#{searchBean.word}" />
  </b>
  を検索しました。
</h:body>

</html>
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]

<-前のページ [1] [2] [3] [4] [5] [6] [7] [8] 次のページ->
- Blog by yamicha.com -