SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Cyber Luxeonで学ぶXMLDB入門

XMLDBとJavaAPI、JAXB2.0を活用したWebアプリケーション開発(実装編)

Cyber Luxeonで学ぶXMLDB入門 第6回


  • X ポスト
  • このエントリーをはてなブックマークに追加

商品データ(商品XML)検索処理

画面遷移

 商品情報 検索・一覧表示の画面遷移を以下の図に示します。

商品情報 検索・一覧表示の画面遷移
商品情報 検索・一覧表示の画面遷移

 「商品情報 新規登録」画面は、商品一覧の「商品名検索」テキストボックスに商品名を入力し「検索」ボタンを押下することによって、商品名に該当する商品の一覧が表示される画面です。

 「商品情報一覧」画面の初期表示処理は、ただ単にJSPを表示するだけですので、説明は割愛し「検索」ボタンが押下された場合のXMLデータ検索処理について説明します。

コントローラ(ItemCRUDServlet)

 コントローラとなるサーブレットでは、HTMLから「action="read"」というパラメータを受け取り、以下の順に処理を実行します。

  1. ItemDaoのfindByItemNameメソッドを呼び出す
  2. リクエスト属性に検索結果のListを保存する
  3. 商品一覧画面(list.jsp)にForwardする

 以下にItemCRUDServletのソースを示します。

ItemCRUDServlet.java
}else if (action.equals("read")) {
    // 【商品検索】→一覧表示
    List itemList = null;
    try {
        // 検索処理
        itemList
          = itemDao.findByItemName( req.getParameter( "item_name" ) );
    } catch (Exception e) {
        e.printStackTrace();
        forwardToErrorPage(req, res);
        return;
    }
    req.setAttribute("itemList", itemList);
    forwardToJSP(req, res, "list.jsp");

Daoクラス

ItemDaoImplクラス

 次にサーブレットから呼ばれるItemDaoImplクラスの実装を説明します。ItemDaoImplクラスのfindByItemNameメソッドでは、以下の順でXQueryを実行しています。

  1. XQueryのテンプレートファイルで変換するパラメータをMapで作成
  2. LuxeonDaoクラスのexecuteXQueryメソッドを呼び出し、XQueryを実行
  3. XQueryの実行結果(List)を戻す

 以下にItemDaoImplクラスのfindByItemNameメソッドのソースを示します。

ItemDaoImpl.java
public List<Object> findByItemName(String itemName)
    throws IOException,JAXBException,Exception{
        
    Map<String, Object> templeteMap = new HashMap<String, Object>();
    Item item = new Item();
    item.setItemName( itemName );
    templeteMap.put( "item" , item );
        
    return LuxeonDao.executeXQuery(
        "items/item_container.bnd" ,
        TEMPLATE_RESOURCE_PATH + "Item_findByItemName.vm" , 
        templeteMap , Item.class        );
    }

LuxeonDaoクラス

 次に、ItemDaoImplクラスのfindByItemNameメソッドから呼ばれるLuxeonDaoクラスのexecuteXQueryメソッドを説明します。ここでは、以下の順でXQueryを実行しています。

  1. セッション、XMLStore、検索対象XML(バインダドキュメント)を順に取得
  2. Velocityを使用してXQueryのテンプレートとオブジェクト値をマージしてXQueryの文字列を取得
  3. XQueryの実行
  4. XQueryの実行結果(NodeList)をJAXBを使用してItemクラスのListに変換して戻す
  5. セッションを閉じる

 以下にLuxeonDaoクラスのexecuteXQueryメソッドのソースを示します。

LuxeonDao.java
public static List<Object> executeXQuery(
    String xmlName,
    String templateName,Map<String, Object> templateObjMap ,
    Class clazz )
        throws IOException,JAXBException,Exception{
    Session clientSession = null;
    try {
        // XMLストア
        clientSession = XlnClientSessionFactory.getSession();
        XMLStore xmlStore = clientSession.getXMLStore(XML_STORE_NAME);

        // バインダドキュメントの取得
        XMLDocument xmlDoc = (XMLDocument)xmlStore.getFile(xmlName);
        
        // XQuery文字列生成
        VelocityWrapper vw = new VelocityWrapper();
        vw.put( templateObjMap );
        String xqueryStr = vw.merge( templateName );

        // XQuery実行
        XQuery xQuery = clientSession.createXQuery( xqueryStr );
        xQuery.execute(xmlDoc);

        // XQuery結果の取得
        XQuerySequence results = xQuery.getResults();
        XQuerySequenceIterator iter = results.getIterator();
        
        JAXBContext jc = JAXBContext.newInstance( clazz );
        Unmarshaller u = jc.createUnmarshaller();
        
        // JAXB XMLデータ(Node)→オブジェクト変換
        List<Object> list = new ArrayList<Object>();
        while( iter.hasNext() ){
            XQueryItem xQueryItem = iter.nextItem();
            Node node = (Node)xQueryItem.getValue();
            list.add( u.unmarshal( node ) );
        }
        return list;

    } finally{
        if ( clientSession != null ) clientSession.release();+
    }
}

XQuery文字列のテンプレート変換

 LuxeonDaoクラスのexecuteXQueryメソッドの説明でも触れましたが、本稿のサンプルでは、XQueryの構文をVelocityのテンプレートファイルとして用意し、JavaオブジェクトとマージすることでXQuery文字列を生成しています。以下に、商品名検索で使用するXQueryを記述したテンプレートファイルを示します。

Item_findByItemName.vm
for \$item in /MultiDoc_Container/item
    where contains(\$item/item_name/text(),'$item.itemName')
    return \$item

 「$item.itemName」が画面で入力された商品名に変換されてXQuery文字列となります。なお「\$item」は「\」で$をエスケープしているだけですので、変換されず「$item」として出力されます。

 Velocityによる変換処理の詳細な説明については、別稿Jakarta Velocityでテンプレートを変換しメールを送信するに説明を委ね、ここではVelocityWrapperクラスのソースを示すのみにします。

VelocityWrapper.java
public class VelocityWrapper {

    /** Velocityエンジンにアクセスするためのクラス */
    private static VelocityEngine engine = null;

    /** テンプレート変換時に使用するオブジェクトを
* 格納するためのクラス
*/
private VelocityContext context = null; /**
* デフォルトコンストラクタ
*/
public VelocityWrapper() throws FileNotFoundException, IOException,Exception{ if ( engine == null ){ engine = new VelocityEngine(); Properties props = new Properties(); props.load( getClass().getResourceAsStream( "/velocity.properties" ) ); engine.init( props ); } context = new VelocityContext(); } /**
* @param templateObjMap
*/
public void put(Map<String, Object> templateObjMap){ Set keySet = templateObjMap.keySet(); for (Iterator iter = keySet.iterator(); iter.hasNext();) { String objName = (String) iter.next(); Object obj = templateObjMap.get( objName ); put( objName, obj ); } } /**
* @param key
* @param value
*/
public void put(String key, Object value) { context.put( key , value ); } /**
* @param templateResourceName
* テンプレートファイルのリソース名
* (クラスパスからスラッシュ区切り)
* @return マージ結果の文字列
*/
public String merge(String templateResourceName) throws ResourceNotFoundException,ParseErrorException, MethodInvocationException,Exception{ // テンプレートの取得 Template template = engine.getTemplate( templateResourceName ); StringWriter sw = new StringWriter(); template.merge( context , sw ); return sw.toString(); }

次のページ
商品データ(商品XML)更新処理

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Cyber Luxeonで学ぶXMLDB入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 佐藤 治夫 (株式会社ビープラウド)(サトウ ハルオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1452 2008/08/19 20:41

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング