JSONとは?

  1. 多言語間でオブジェクトをやりとりするときに、オブジェクトを表記するための中立的な表記法
  2. 現在、多言語間でオブジェクトをやりとりするためのプロトコルとしてはXMLが広く使われはじめてきている
  3. ところが、オブジェクトをシリアライズ(文字列化)するのに、マークアップ言語であるXMLを使うのはキモい
  4. ということで「Java Scriptオブジェクトの内部表記方法を使おう!」というのがJSON
    Java Scriptでは、以下のようにオブジェクトを定義することが出来る。
     var obj =
      {
      “key1” : “val1” ,
      “key2” : { “key21” : “val21” , “key22” : “val22” } ,
      “key3” : [ “val31” , “val32” , “val33” ]
      }
    
  5. この表記法を多言語間のオブジェクトのやりとりに使うのが、JSON = Java Script Object Notation
    json.png

JSON RPC JAVA ORB とは?

  1. ClientサイドにあるJava Scriptから、ServerサイドのJavaオブジェクトを呼び出す方法
    jsonrpc1.png
    • RPC(Remote Procedure Call)
      • 異なるマシンに処理を依頼すること
    • ORB(Object Request Broker)
      • CORBAで出てきた概念。異なるマシン上に分散して存在するオブジェクトに処理を依頼する仕組み。
    • JSON RPC JAVA ORB
      • ClientサイドからJSON RPC BridgeにJava Script Objectで処理を依頼すると、ServerサイドでJava Classが呼ばれる。
      • 勝手にJava Script ObjectとJava Objectを変換してくれるのでユーザプログラムからは特に意識する必要はない。
  2. もうちょっと詳しく言うと
    jsonrpc2.png

JSONのインストール

  1. JSON-RPC-Java-ORB公式サイトから、json-rpc-java-1.0rc2.zip をダウンロードして展開します。
  2. Eclipse Sysdeo で、Tomcatプロジェクトを作成します。
  3. JSON-RPC-Java-ORBをTomcatプロジェクトに配置します。
    jsonprj.png
    • jsonrpc.jar${Context Root}\WEB-INF\lib に配置します。
    • jsonrpc.js${Context Root} に配置します。
  4. web.xmlの作成
    JSONPRCServletをWebアプリに登録します。
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
      <servlet>
        <servlet-name>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-name>
        <servlet-class>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>com.metaparadigm.jsonrpc.JSONRPCServlet</servlet-name>
        <url-pattern>/JSON-RPC</url-pattern>
      </servlet-mapping>
    </web-app>

JSONサンプルプログラム

JSON-RPC-JAVA-ORB のほとんどの機能を検証できる練習プログラムを作りました。

jsonexam.png

JSON Bridgeの初期化

最初に、JSON Bridgeを初期化して、クライアント(Webブラウザ)とサーバ(J2EEコンテナ)で通信が出来るようにします。

 

(HelloJSON.jsp)

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
 
 <jsp:useBean id="JSONRPCBridge" scope="session"
      class="com.metaparadigm.jsonrpc.JSONRPCBridge" />
 <% JSONRPCBridge.registerObject("hello", new com.snail.web.json.HelloJSON() ); %>
 
 <html>
 <head>
 
 <title>JSON-RPC-Java Hello</title>
 <script type="text/javascript" src="jsonrpc.js"></script>
 <script language="javascript">
 <!--
 function init(){
   jsonrpc = new JSONRpcClient("JSON-RPC");
 }
 …(その他のJavascriptプログラム)…
 
 //-->
 </script>
 
 </head>
 <body bgcolor="#ffffff" onLoad="init();">
 
 <h2>JSON-RPC-Java Examinations</h2>
 
 …(HTML)…
 
 </body>
 </html>
  1. サーバ側での動作
    • Sessionに、JSONRPCBridgeを登録し、そこにサーバ側で動作するJavaオブジェクトを登録します。
  2. クライアント側での動作
    • Webページの、onLoadイベントで JSONRpcClient? を初期化します。
    • 以降、JSONRpcClient? を通じてJava Script側から、JSONRPCBridgeに登録したJavaオブジェクト(ここでは com.snail.web.json.HelloJSON )を呼び出す事が出来ます。

Hello JSON

  1. 機能
    とりあえず、クライアント側から文字列を送って、サーバ側から戻ってきた文字列を表示するプログラムです。
    • 実行画面
      helloJson.png
    • 実行結果
      helloJsonReturn.png
  2. サーバプログラム(HelloJSON.java)
      public String sayHello(String name) {
        return "Hello " + name + "!";
      }
    
  3. クライアントプログラム(HelloJSON.jsp)
     function clickHello(){
       var whoNode = document.getElementById("who");
       var result = jsonrpc.hello.sayHello(whoNode.value);
       alert("The server replied: " + result);
     }
    

いろいろな引数でJSON Bridgeを呼び出す

  1. Mapを送る
    1. 機能
      • 実行画面
        jsonArgHandling.png
      • 実行結果
        jsonSendMap.png
    2. サーバプログラム(HelloJSON.java)
        public String setMap(Map map) {
          String name = (String) map.get("Name");
          String age = (String) map.get("Age");
          String father = (String) map.get("Father");
          String mother = (String) map.get("Mother");
       
          return name + " is " + age + " years old. His father is " + father
              + " and mother is " + mother + ".";
        }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickSendMap(){
         try{
          var age    = document.getElementById("age").value;
          var name   = document.getElementById("name").value;
          var father = document.getElementById("father").value;
          var mother = document.getElementById("mother").value;
          
          var jsonMsg = 
            {"javaClass" : "java.util.HashMap",
             "map": {"Age": age, "Name": name, "Father": father, "Mother": mother} 
            };
          
          alert( jsonrpc.hello.setMap(jsonMsg) );
         }catch(e){
           alert(e);
         }
       }
      
  2. Beanを送る
    1. 機能
      • 実行画面
        jsonArgHandling.png
      • 実行結果
        jsonSendBean.png
    2. サーバプログラム(HelloJSON.java)
        public String setBean(ExampleBean bean) {
          String name = bean.getName();
          int age = bean.getAge();
          String mother = bean.getMother().getName();
       
          return mother + " brought " + name + " into the world " + age
              + " years ago.";
        }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickSendBean(){
         try{
          var age    = document.getElementById("age").value;
          var name   = document.getElementById("name").value;
          var father = document.getElementById("father").value;
          var mother = document.getElementById("mother").value;
       
          var jsonMsg = 
             {"javaClass": "com.snail.web.json.ExampleBean",
              "age": age, 
              "name": name,       
              "father": 
                {"javaClass": "com.snail.web.json.ExampleBean",
                 "name": father},
              "mother": 
                {"javaClass": "com.snail.web.json.ExampleBean",
                 "name": mother}
             };
       
          alert( jsonrpc.hello.setBean(jsonMsg) );
         }catch(e){
           alert(e);
         }
       }
      
  3. Listを送る
    1. 機能
      • 実行画面
        jsonArgHandling.png
      • 実行結果
        jsonSendList.png
    2. サーバプログラム(HelloJSON.java)
        public String setList(List list) {
          return "Argument List is" + list;
        }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickSendList(){
         try{
          var age    = document.getElementById("age").value;
          var name   = document.getElementById("name").value;
          var father = document.getElementById("father").value;
          var mother = document.getElementById("mother").value;
       
          var jsonMsg = 
             {"javaClass": "java.util.LinkedList",
              "list": [age,name,father,mother] };
       
          alert( jsonrpc.hello.setList(jsonMsg) );
         }catch(e){
           alert(e);
         }
       }
      

いろいろな返値をJSON Bridgeから受け取る

  1. Mapを受け取る
    1. 機能
      • 実行画面
        jsonReturnMap.png
      • どうやらLinkedHashMap?を使っても、要素の順番は保存されない模様
    2. サーバプログラム(HelloJSON.java)
         public Map sayMap() {
           Map<String, String> m = new LinkedHashMap<String, String>();
           m.put("FirstElement", "Enterprise");
           m.put("SecondElement", "Constitution");
           m.put("ThirdElement", "Yamato");
           m.put("FourthElement", "Melbourne");
       
           return m;
         }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickGetMap(){
          var ret = jsonrpc.hello.sayMap();
          document.getElementById("jsonMsg").innerHTML=toJSON(ret);
          document.getElementById("javaClass").innerHTML=ret.javaClass;
          document.getElementById("obj").innerHTML=
            "FirstElement= " + ret.map.FirstElement  + ", " +
            "SecondElement=" + ret.map.SecondElement + ", " +
            "ThirdElement= " + ret.map.ThirdElement  + ", " +
            "ForuthElement=" + ret.map.FourthElement;
       }
      
  2. Beanを受け取る
    1. 機能
      • 実行画面
        jsonReturnBean.png
    2. サーバプログラム(HelloJSON.java)
         public ExampleBean sayBean() {
           ExampleBean father = new ExampleBean();
           father.setName("Bob");
           father.setAge(34);
       
           ExampleBean mother = new ExampleBean();
           mother.setName("Alice");
           mother.setAge(32);
       
           ExampleBean me = new ExampleBean();
           me.setName("Kent");
           me.setAge(5);
           me.setFather(father);
           me.setMother(mother);
       
           return me;
         }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickGetBean(){
          var ret = jsonrpc.hello.sayBean();
          document.getElementById("jsonMsg").innerHTML=toJSON(ret);
          document.getElementById("javaClass").innerHTML=ret.javaClass;
          document.getElementById("obj").innerHTML=
           "Name = "  + ret.name + ", " +
           "Age ="    + ret.age  + ", " +
           "Father= " + ret.father.name  + ", " +
           "Mother="  + ret.mother.name;
       }
      
  3. Listを受け取る
    1. 機能
      • 実行画面
        jsonReturnList.png
    2. サーバプログラム(HelloJSON.java)
         public List sayList() {
           List<String> list = new LinkedList<String>();
       
           list.add("linux");
           list.add("apache");
           list.add("php");
           list.add("mysql");
       
           return list;
         }
      
    3. クライアントプログラム(HelloJSON.jsp)
       function clickGetList(){
          var ret = jsonrpc.hello.sayList();
          document.getElementById("jsonMsg").innerHTML=toJSON(ret);
          document.getElementById("javaClass").innerHTML=ret.javaClass;
          
          var str = "";
          for( cnt = 0 ; cnt < ret.list.length ; cnt++ ){
            str = str + cnt + " " + ret.list[ cnt ] + ", ";
          }
          document.getElementById("obj").innerHTML=str;
       }
      

JSON Bridgeによる例外の搬送

  1. 機能
    • 実行画面
      jsonException.png
  2. サーバプログラム(HelloJSON.java)
       public String sayErrId() throws Exception {
         throw new Exception("ERR01");
       }
    
  3. クライアントプログラム(HelloJSON.jsp)
     function clickErrMsg(){
      try{
        jsonrpc.hello.sayErrId();
      }catch(e){
        document.getElementById("eName").innerHTML=e.name;
        document.getElementById("eCode").innerHTML=e.code;
        document.getElementById("eMsg").innerHTML=e.message;
        document.getElementById("eStack").innerHTML=e.javaStack;
      }
     }
    
  4. JSON例外について
    • JSONの例外は、e.name、e.code、e.message、e.javaStack を含む
    • codeからは以下のようなシステム的な障害状況を判断することが出来る
      JSONRpcClient.Exception.CODE_ERR_PARSE = 590 
      JSONRpcClient.Exception.CODE_ERR_NOMETHOD = 591 
      JSONRpcClient.Exception.CODE_ERR_UNMARSHALL = 592 
      JSONRpcClient.Exception.CODE_ERR_MARSHALL = 593
    • ユーザプログラムから業務的な例外を搬送したいときには、
      Java側では、
      throw new Exception("エラーコード文字列");
      を使い、Java Script側では e.message で "エラーコード文字列" を受け取るようにするのが吉。

その他の機能

  1. Staticメソッドしかないんですけど・・・
     <jsp:useBean id="JSONRPCBridge" scope="session"
          class="com.metaparadigm.jsonrpc.JSONRPCBridge" />
     <% JSONRPCBridge.registerClass("myClass", myClass); %>
    
    registerObject() の代わりに registreClass() を使う
  2. 特にユーザ別にJavaユーザプログラムを分ける必要がないとき
     <% JSONRPCBridge.getGlobalBridge().registerObject("myObject", myObject); %>
     <% JSONRPCBridge.getGlobalBridge().registerClass("myClass", myClass); %>
    
    getGloablBridge?() で Singleton が得られる。
  3. Basic認証を通じてJSON RPC Servletを呼び出す
     var jsonrpc = new JSONRpcClient("JSON-RPC", user, pass)
    
    Java Script で、JSONRPCClient を初期化する際に ユーザ名とパスワードを第二引数、第三引数にいれる
  4. 非同期呼び出し
    JSONBridgeを呼び出す際に、第一引数に非同期呼び出し完了時にCall Backされる関数をいれる。Call Backされる関数の第一引数は返値、第二引数は例外。
    • 同期呼び出し版
       function clickHello(){
         var whoNode = document.getElementById("who");
         var result = jsonrpc.hello.sayHello(whoNode.value);
         alert( 'Synchronous Call Result :' + result);
       }
      
    • 非同期呼び出し版
       function clickHello(){
         var whoNode = document.getElementById("who");
         jsonrpc.hello.sayHello(cb, whoNode.value);
         alert( 'Called Remote Procedure Asynchronously' );
       }
       function cb(result, exception) {
         if( exception ){
           // exception != null
           alert( 'Asynchronous Call Failed :' + exception );
           return;
         }
         
         alert( 'Asynchronous Call Result :' + result );
       }
      

参考文献

  1. JavaScript?++かも日記, http://jsgt.org/mt/01/
  2. [翻訳]JSON入門, http://d.hatena.ne.jp/brazil/20050915/1126709945
  3. JSON-RPC-Java, http://oss.metaparadigm.com/jsonrpc/

Java#AJAX


添付ファイル: filejsonReturnMap.png 3099件 [詳細] filejsonrpc1.png 3426件 [詳細] filejsonSendList.png 2948件 [詳細] filejsonprj.png 3831件 [詳細] filehelloJson.png 3574件 [詳細] filejsonexam.png 3256件 [詳細] filejson.png 3987件 [詳細] filejsonArgHandling.png 3150件 [詳細] filehelloJsonReturn.png 3149件 [詳細] filejsonSendMap.png 2983件 [詳細] filejsonReturnBean.png 2979件 [詳細] filejsonReturnList.png 3052件 [詳細] filejsonSendBean.png 2901件 [詳細] filejsonException.png 3070件 [詳細] filejsonrpc2.png 3327件 [詳細] fileJSONExam.war 3553件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   sitemap
Last-modified: 2006-04-15 (土) 17:46:54 (6579d)
Short-URL: http://hondou.homedns.org/pukiwiki/pukiwiki.php?cmd=s&k=64bc5eed21
ISBN10
ISBN13
9784061426061