yamicha.com's Blog - Presented by yamicha.com
Blog yamicha.com's Blog - 2018/12 の記事
[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] [31]

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
 垂オ訳ございませんが、現在このブログではトラックバックを受け入れていません。

 この記事に対してリンクされる場合には、こちらのURLをご利用ください。
http://void.yamicha.com/blog/blog.cgi?mode=view&number=764
 上記URLをトリプルクリックされますと、簡単にURL全体の選択が行えます。

※以下の記事がトラックバックされます。
口蹄疫に不見識な者は・・・
2010/05/23(Sun)22:11:10
 宮崎で口蹄疫が猛威を振るい、畜産業界に大打撃を与えています。ウイルスに感染した家畜の処分に加え、感染拡大防止のための周辺地域の牛や豚の処分、処分した家畜の埋立地の確保など課題は非常に多く、また長らく研究開発されてきた種牛も処分され、各地への子牛の供給も滞る恐れが出てくるなど、影響は相当な規模になりそうです。
 ひとまず、今回は今までほど風評被害が出ていない点が唯一の救いでしょう。これに関しては、県や政府の警戒に加え、あるいは今まで散々風評をあおってきたマスコミも多少は気を使っているようで、口蹄疫が「得体の知れないもの」とみなされてパニックを起こすような事態は避けられています。
 口蹄疫ウイルスは非常に感染力が強く、畜産業界にとっては恐ろしいウイルスですが、牛肉の主に危険部位から感染する疑いが濃厚なBSEと異なり、感染した牛や豚の肉を食べても何ら問題はありません。また、感染した家畜や食肉は処分されるため、市場に出回ることはまずありません。これも人間に対して害を与えるからではなく、感染拡大を防止するための措置とされています。「狂牛病」(BSEのかつての名称)と混同してしまっている人も一部には存在するようですが、BSEは(ウイルス関連説もあるものの)基本的には異常プリオンが原因とみられており、口蹄疫とは何の接点もありません。なお、非常に紛らわしいことに、似た名前の「狂犬病」はウイルスによる病気です。
 口蹄疫自体は必ずしも致命的な病気ではなく、実際に致死率はそれほど高くありませんが、これに感染した家畜は「売り物にならなくなる」点で非常に深刻で、畜産業界のダメージは相当なものとなります。感染力が極めて高く、問題が多数の農場に派生すると取り返しがつかない結果を招くため、徹底的な殺処分によってウイルスを封じ込め、根絶する作戦が採られます。
 鳥インフルエンザ問題で養鶏業界がダメージを受け、その後さらに口蹄疫問題とあっては、宮崎は非常に気の毒であるとしか言いようがありません。タレントから地政の世界に転身した東国原氏としても、まさに苦難の連続でしょう。ただ、本件で東国原氏が努力しているのは確かで、しかも知名度を利用した鳥インフルエンザ問題からの回復に加え、今回も口蹄疫問題に国民の目を向けさせるとともに、風評被害を抑制することにもある程度成功しており、タレント地方政治家として成功した稀有な例といえそうです。
 しかし、一方でマスコミや政治家の一部には不見識な者が存在しており、ただ珍妙なことを騒ぎ立てているだけならまだしも、下手をすると対策を妨害してしまう、あるいは間接的に邪魔になる可能性さえ否定できません。以前の記者会見では、マスコミの無思慮な言い分に対し、東国原氏が怒って退席する一幕がありましたが、あれなどはまさにマスコミの不見識が凝縮された場面でした。
 また、四日市市議の民主・諸岡氏は自身のブログで「(県は)あんな判りやすい病気を『ただの発熱』と処理した。バカじゃないかと」「県から要請を受けても放置していた国は同等のバカ」「腹を切って死ぬべきである」などと述べる有様で、不見識極まりないと言わざるを得ません。
 よく「風邪は万病のもと」と言いますが、何百何千という牛が一般的な風邪の症状を呈する中で、そのうちの1頭が数年あるいは数十年に一度といった程度の頻度で発生する口蹄疫であると特定するのが相当に難しいのは想像に難くありません。特に今回の口蹄疫は、発生当初は特徴的な症状が確認できなかったといいますので、なおさらです。また、そのような現場レベルの問題を県や国政レベルにすり替え、「バカ」「腹を切って死ぬべき」などというのは無茶にもほどがあります。その理屈でいけば、どこかの牛が発熱するたびに知事や農水相は即座に連絡を受けて陣頭指揮を執らなくては「バカ」で「腹を切って死」ななくてはならないはずですが、荒唐無稽とはまさにこのことです。
 今回は実に1000件もの抗議が寄せられ、記事は削除されたといいますので、さほど大きな問題は出ませんでしたが、仮にこのような言い分が広まってしまった場合に恐ろしいのは、政府や県といった関係者同士が責任のなすりあいを始めてしまうことです。
 本来、口蹄疫のような自然災害に悪者は存在しないはずですが、人々がやり場のない怒りや絶望感を抱くのは避けようがなく、ある関係者にほんの少しでも過失が見つかろうものなら、その人に災害の全責任が押し付けられてしまいます。そして、もしマスコミが諸岡氏のようなことを大々的に言い出していたならば、ほぼ確実に県と政府の責任合戦が始まっていたでしょう。
 無論、問題終息後に防疫体制の問題点を確認し、関係各所の責任を明確にし、それを次回の災害に生かすというのであれば、責任を確認する意義は十分にあります。しかし、現時点で関係各所が責任のなすりあいを始めれば、感染拡大阻止の足並みは確実に乱れますし、対策をダシにけん制しあう状況にもなりかねません。実際に一部では相手に責任を押し付けるような言動もあるようですが、1手遅れれば数万頭が犠牲になるのですから、明らかに争っていられる場面ではありません。
 また、もう1つ気になる点として、仮に県や国が即座に口蹄疫に対応し、大規模な殺処分作戦で感染を今よりも抑えられていたならば、一体マスコミは何を言い出したでしょうか。あれだけ不見識なマスコミのことですから、今度は「畜産農家を破壊した政府」「対策の所要額は数十億」と言い出すなど、別の批判を行っていた可能性は十分に考えられるのです。今でこそ口蹄疫の恐ろしさが認知され、英国が大量の殺処分を行った例も引き合いに出されるようになりましたが、これも今回の件が大事に至ったがためです。結局のところ、どう転んでもマスコミには「犯人」が必要なのです。
 畜産農家や行政などの関係者が口蹄疫と戦う際には、ウイルスと同時に風評被害や不見識とも戦わなくてはなりません。そして、ウイルスはともかく後の2つはいずれも人災で、状況次第ではウイルスより大きな被害をもたらしたり、ウイルスとの戦いを妨害したりします。十分な注意が必要です。

 前回は書評らしきプログラムのサーバー側実装を作成しましたが、今回は簡素なクライアント側実装を行ってみます。
 RESTですからいかなる言語を使用しても構いませんが、今回も例によってJSF 2.0を使用しています。RESTを使ってデータをやり取りし、JAXBによる変換を行っている部分を除けば、書き方はEJB + JPAを使用したJSFとさほど変わらないはずです。
 以下、下線部が追加部分です。
WEB-INF
 /classes
  /com
   /yamicha
    /rs
     /server
      @Path BookReviewService.java
      @Entity Book.java
      @XmlElement Books.java
      @Entity Review.java
      @XmlElement Reviews.java
      @Stateless BookReviewAccess.java
     /client
       @ManagedBean BookBean.java
       @ManagedBean ReviewBean.java
  /META-INF
   persistence.xml
 web.xml
book.xhtml
review.xhtml
reviewForm.xhtml
 今回、「本を選択する」操作においてListDataModelを使用しているため、SessionScopeを使用しています。まずキーワードによって本を検索すると、booksプロパティに検索した本のデータが格納され、h:dataTableなどのforeach系統のタグによってそれが表示されます。ユーザーがその中から望みの本をクリックすると、クリックした本が何番目のものであるかが伝えられ、セッションに格納された本の中から選択された本が取り出される、という寸法です。
 しかし、せっかくそのような機構があるからと使ってはみましたが、実際のところ私はJSFのSessionScoped + DataModelが少々嫌いです。ユーザー側の表示とサーバー側のデータが食い違う可能性があるためで、例えばユーザーがまず"Java"で検索し、次に"SQL"で検索(ここでサーバーのbooksにはSQL本の検索結果が格納される)、その後ブラウザの「戻る」を使ってJavaの検索結果に戻り、何か本をクリックすると、(ユーザーにとっては)なぜかSQL本が表示されてしまいます。サーバーの状態からすれば当然の結果ですが、実際に発生すると意外に面食らいます。
// BookBean.java
package com.yamicha.rs.client;

import javax.faces.bean.*;
import javax.faces.context.*;
import javax.faces.model.*;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import java.io.*;
import java.net.*;
import java.util.*;
import com.yamicha.rs.server.*;

@SessionScoped @ManagedBean public class BookBean
	implements java.io.Serializable{
	public final static String REST_SERVER = 
		"(アプリケーションの URL)/restserver/book/";

	private String word;

	private ListDataModel<Book> books;
	private Book book;

	public BookBean(){
		word = "";
		books = new ListDataModel<Book>();
	}

	public String getWord(){
		return word;
	}
	public void setWord(String s){
		word = s;
	}

	public void readBooks() throws Exception{
		if(word == null || word.isEmpty())
			return;

		JAXBContext jc = JAXBContext.newInstance(Books.class);

		HttpURLConnection c = (HttpURLConnection)
			new URL(REST_SERVER + "books/" +
			URLEncoder.encode(word , "UTF-8")).
			openConnection();
		c.setRequestMethod("GET");
		c.setRequestProperty("Content-Type" , "application/xml");

		c.connect();

		InputStream is = c.getInputStream();

		Unmarshaller u = jc.createUnmarshaller();
		setBooks(new ListDataModel(((Books)u.unmarshal(is)).
			getBooks()));

		is.close();

		c.disconnect();
	}
	public ListDataModel<Book> getBooks(){
		return books;
	}
	public void setBooks(ListDataModel<Book> l){
		books = l;
	}

	public void setSelectedBook(){
		book = books.getRowData();
	}
	public void readBook(int id) throws Exception{
		JAXBContext jc = JAXBContext.newInstance(Book.class);

		HttpURLConnection c = (HttpURLConnection)
			new URL(REST_SERVER + "book/" + id).
			openConnection();
		c.setRequestMethod("GET");
		c.setRequestProperty("Content-Type" , "application/xml");

		c.connect();

		InputStream is = c.getInputStream();

		Unmarshaller u = jc.createUnmarshaller();
		book = (Book)u.unmarshal(is);

		is.close();

		c.disconnect();
	}
	public void refreshBook() throws Exception{
		readBook(book.getId());
	}
	public Book getBook() throws Exception{
		return book;
	}
}

// ReviewBean.java
package com.yamicha.rs.client;

import javax.faces.bean.*;
import javax.faces.context.*;
import javax.faces.model.*;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import java.io.*;
import java.net.*;
import java.util.*;
import com.yamicha.rs.server.*;

@SessionScoped @ManagedBean public class ReviewBean
	implements java.io.Serializable{
	@ManagedProperty(value="#{bookBean}") private BookBean bookBean;
	private String name;
	private String message;

	private ListDataModel<Review> reviews;
	private Review review;

	public ReviewBean(){
	}

	public String getName(){
		return name;
	}
	public String getMessage(){
		return message;
	}
	public ListDataModel<Review> getReviews(){
		return reviews;
	}
	public BookBean getBookBean(){
		return bookBean;
	}

	public void setName(String s){
		name = s;
	}
	public void setMessage(String s){
		message = s;
	}
	public void setReviews(ListDataModel<Review> r){
		reviews = r;
	}
	public void setBookBean(BookBean b){
		bookBean = b;
	}

	public String showReviews() throws Exception{
		// 選択された本を book プロパティにセット
		bookBean.setSelectedBook();

		// book のレビューデータを読み込む
		readReviews();

		return "review";
	}

	public void setSelectedReview(){
		review = reviews.getRowData();
	}

	// PUT 用レビュー投稿フォーム設定関数
	public String editForm(){
		// 選択されたレビューを review プロパティにセット
		setSelectedReview();

		name = review.getName();
		message = review.getMessage();

		return "reviewForm";
	}
	// POST 用
	public String postForm(){
		review = null;

		name = "";
		message = "";

		return "reviewForm";
	}

	// bookBean.book プロパティのレビューリストを取得
	public void readReviews() throws Exception{
		JAXBContext jc = JAXBContext.newInstance(Reviews.class);

		HttpURLConnection c = (HttpURLConnection)
			new URL(BookBean.REST_SERVER + "book/reviews/" +
			bookBean.getBook().getId()).openConnection();
		c.setRequestMethod("GET");
		c.setRequestProperty("Content-Type" , "application/xml");

		c.connect();

		InputStream is = c.getInputStream();

		Unmarshaller u = jc.createUnmarshaller();
		reviews = new ListDataModel(((Reviews)
			u.unmarshal(is)).getReviews());

		is.close();

		c.disconnect();
	}

	// 任意のレビューを取得
	public void readReview(int id) throws Exception{
		JAXBContext jc = JAXBContext.newInstance(Review.class);

		HttpURLConnection c = (HttpURLConnection)
			new URL(BookBean.REST_SERVER + "review/" +
			id).openConnection();
		c.setRequestMethod("GET");
		c.setRequestProperty("Content-Type" , "application/xml");

		c.connect();

		InputStream is = c.getInputStream();

		Unmarshaller u = jc.createUnmarshaller();
		review = (Review)u.unmarshal(is);

		is.close();

		c.disconnect();
	}
	// 現在選択中のレビューを再読み込み
	public void refreshReview() throws Exception{
		readReview(review.getId());
	}

	// レビューを投稿
	public String sendReview() throws Exception{
		Review r = review;

		String method = null;
		if(r == null){
			method = "POST";
			r = new Review();
		}else{
			method = "PUT";
		}

		r.setName(name);
		r.setMessage(message);
		r.setBookId(bookBean.getBook().getId());

		JAXBContext jc = JAXBContext.newInstance(Review.class);

		HttpURLConnection c = (HttpURLConnection)
			new URL(BookBean.REST_SERVER +
			"review").openConnection();
		c.setRequestMethod(method);
		c.setDoOutput(true);
		c.setRequestProperty("Content-Type" , "application/xml");

		c.connect();

		OutputStream os = c.getOutputStream();

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

		os.close();

		InputStream is = c.getInputStream();
		is.read();
		is.close();

		c.disconnect();

		readReviews();	// レビューリストを再読み込み

		name = "";
		message = "";

		review = null;

		return "review";
	}
	// レビューを削除
	public void removeReview() throws Exception{
		// 削除するよう選択されたレビューを取得
		setSelectedReview();

		HttpURLConnection c = (HttpURLConnection)
			new URL(BookBean.REST_SERVER + "review/" +
			review.getId()).openConnection();
		c.setRequestMethod("DELETE");

		c.connect();

		InputStream is = c.getInputStream();
		is.read();
		is.close();

		c.disconnect();

		readReviews();	// レビューリストを再読み込み
	}
}
 RESTですから、取得はGET、作成はPOST、更新はPUT、削除はDELETEです。
 book.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">

<h:head>
  <title>JAX-RS Book Review</title>
</h:head>

<h:body>
  <b>JAX-RS Book Review</b>

  <h:form>
    本の検索<br />
    <h:inputText value="#{bookBean.word}" />
    <h:commandButton action="#{bookBean.readBooks}" value="Search" />
  </h:form>

  <h:form>
    <h:dataTable border="1" value="#{bookBean.books}" var="book">
      <h:column>
        <f:facet name="header">書名</f:facet>

        <h:commandButton action="#{reviewBean.showReviews}"
          value="書評" />
        <h:outputText value="#{book.title}"/>
      </h:column>

      <h:column>
        <f:facet name="header">著者</f:facet>
        <h:outputText value="#{book.author}"/>
      </h:column>

      <h:column>
        <f:facet name="header">出版</f:facet>
        <h:outputText value="#{book.publisher}"/>
      </h:column>
    </h:dataTable>
  </h:form>
</h:body>

</html>
 review.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">

<h:head>
  <title>JAX-RS Book Review</title>
</h:head>

<h:body>
  <b>JAX-RS Book Review</b>
  <hr />

  <table border="1">
    <tr>
      <td><b>書名</b></td>
      <td><h:outputText value="#{bookBean.book.title}" /></td>
    </tr>
    <tr>
      <td><b>著者</b></td>
      <td><h:outputText value="#{bookBean.book.author}" /></td>
    </tr>
    <tr>
      <td><b>出版社</b></td>
      <td><h:outputText value="#{bookBean.book.publisher}" /></td>
    </tr>
    <tr>
      <td><b>価格</b></td>
      <td><h:outputText
        value="#{bookBean.book.price}" /> 円</td>
    </tr>
  </table>

  <h:form>
    レビュー:
    <c:choose>
      <c:when test="${reviewBean.reviews.getRowCount() > 0}">
        <h:dataTable border="1" value="#{reviewBean.reviews}"
          var="review">
          <h:column>
            <f:facet name="header">投稿者</f:facet>
            <h:outputText value="#{review.name}"/>
          </h:column>

          <h:column>
            <f:facet name="header">内容</f:facet>
            <h:outputText value="#{review.message}"/>
          </h:column>

          <h:column>
            <f:facet name="header">投稿日時</f:facet>
            <h:outputText value="#{review.date}"/>
          </h:column>

          <h:column>
            <f:facet name="header">編集</f:facet>
            <h:commandLink action="#{reviewBean.editForm}">
              編集
            </h:commandLink>
          </h:column>

          <h:column>
            <f:facet name="header">削除</f:facet>
            <h:commandLink action="#{reviewBean.removeReview}">
              削除
            </h:commandLink>
          </h:column>
        </h:dataTable>
      </c:when>
      <c:otherwise>
        <br />
        レビューは投稿されていません。<br />
        <br />
      </c:otherwise>
    </c:choose>

    <h:commandButton action="#{reviewBean.postForm}"
      value="レビューの新規投稿" /><br />
    <br />

    <h:commandButton action="book" value="戻る" />
  </h:form>
</h:body>

</html>
 reviewForm.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">

<h:head>
  <title>JAX-RS Book Review</title>
</h:head>

<h:body>
  <b>JAX-RS Book Review</b><br />
  <br />

  「<b><h:outputText
    value="#{bookBean.book.title}" /></b>」へのレビュー

  <h:form>
    <table border="1">
      <tr>
        <td><b>投稿者名</b></td>
        <td><h:inputText value="#{reviewBean.name}" /></td>
      </tr>
      <tr>
        <td><b>コメント</b></td>
        <td><h:inputText value="#{reviewBean.message}"
          size="60" /></td>
      </tr>
    </table>

    <h:commandButton action="#{reviewBean.sendReview}"
      value="この内容を投稿" /><br />
    <br />

    <h:commandButton action="review" value="戻る" />
  </h:form>
</h:body>

</html>
 後は適当なキーワードで検索し、レビューを書くなり更新するなり削除するなり任意の捜査を行うだけです。前回の実装ではサーバー側のReview.messageプロパティにCLOBを使っていないため、文字数はMySQLだと255文字までです。
 次のURLが検索フォームです。

(アプリケーションのURL)/book.jsf

 ぽち出版はともかく、麻斐閣の本は面白そうです。
カテゴリ [開発魔法][社会問題] [トラックバック 0][コメント 0]
<- 前の記事を参照 次の記事を参照 ->

- Blog by yamicha.com -