scala：XMLRPCクライアントを試す（郵便番号から住所を取得）

Javaの知識があれば簡単なことかもしれないが、、

Javaに挫折（肌に合わず）して、Scalaを始めるユーザーもいるはず。そして詰まる。。

XMLRPCなんて今どきじゃないかもしれないけど、そのための備忘録として。


## 環境

- Windows7Pro64bit
- ScalaVersion:2.11.8
- typesafe-activator-1.3.12


- XMLRPCサーバーとしてyubin.senmon.net様を使わせていただいた。公開系のXMLRPCサービスが少ないのでありがたかった。


## コード

```build.sbt

libraryDependencies ++= Seq(
  "org.apache.xmlrpc" % "xmlrpc-client" % "3.1.3"
)

```

```xmlrpc.scala
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
import org.apache.xmlrpc.client.XmlRpcSunHttpTransportFactory
import org.apache.xmlrpc.client.XmlRpcLocalTransportFactory

import java.net.URL;

trait Xmlrpc {

  //コンフィグの初期化
  val config = new XmlRpcClientConfigImpl()

  //拡張機能を有効にする
  config.setEnabledForExtensions(true);

  config.setServerURL(new URL("http://yubin.senmon.net:80/service/xmlrpc"))

  //文字コード
  config.setEncoding("UTF-8");

  //接続タイムアウト値を設定
  config.setConnectionTimeout(10000)

  //clientの初期化
  val client = new XmlRpcClient()

  //clientにconfigを読み込ませる
  client.setConfig(config)

}

```
```yubin.scala
import scala.collection.JavaConverters._

object Yubin extends Xmlrpc {

    //xmlrpc問合せ
    def fetchAddressByPostcode(postCode:String):Either[String,Array[Object]]={

      //API名
      val api= "yubin.fetchAddressByPostcode"

      //XMLRPCのINPUTパラメータ設定
      val params=Seq(
        "%s".format(postCode) //郵便番号
      ).asJava

      try {
        val resultPrams = client.execute(api,params).asInstanceOf[Array[Object]]
        Right(resultPrams)
      }catch{
        case e:Exception=>{
          Left("%s".format(e))
        }
      }

    }
}

```

```main.scala
import java.util.HashMap

//問い合わせ結果を格納するケースクラス Address
case class Address(
  postCode:String,
  pref:String,
  city:String,
  town:String
)

object MainObject {

  def main(args: Array[String]){

    //住所を検索したい郵便番号
    val postCode="1010032"

    //暗黙の型変換
    implicit def postcode2Address(f:HashMap[String,Object]):Address={
      Address(
        f.get("postcode").toString,
        f.get("pref").toString,
        f.get("city").toString,
        f.get("town").toString
      )
    }

    //Option[Address]で取得
    val address:Option[Address]=Yubin.fetchAddressByPostcode(postCode) match{
      case Right(resultParams)=>{
        Some(resultParams(0).asInstanceOf[HashMap[String,Object]])
      }
      case Left(e)=>{
        println(e)
        None
      }
    }

    address match {
      case Some(x) =>{
       println("%s:あなたの住所は %s%s%s ですね！".format(x.postCode,x.pref,x.city,x.town))
      }
      case None =>{
      }
    }

   }

}


```

## 結果サンプル

### 郵便番号 1010032　で検索した場合

```
1010032:あなたの住所は 東京都千代田区岩本町 ですね！
```

### 郵便番号 101003　で検索した場合

```
org.apache.xmlrpc.XmlRpcException: postcode 101003 is invalid.
```

### 郵便番号 1019999　で検索した場合

```
org.apache.xmlrpc.XmlRpcException: fetchAddressByPostcode: 1019999 not found
```


#余談：XMLを入れ子にする場合

- 以下はサンプルでフォーマット自体に意味はありません。

```
    val params=Seq(
      "%s".format("東京都"), 
      "%s".format("千代田区"),
      Seq(
        Seq(
          "%s".format("岩本町"), 
          "%s".format("1010032") 
        ).asJava
      ).asJava
    ).asJava
```