Home About
Micronaut , JQuery , JavaScript

Part 2: テスト用に json を POST して json を返す ウェブサービスをつくる

デバッグのためのテストとして json を POST して json を返すウェブサービスを Micronaut でつくる話。

Micronaut

前回同様に myapp というプロジェクトの雛形を作成します。

$ mn create-app myapp --build=gradle --lang=groovy
$ cd myapp
$ mn create-controller item

ここで雛形として生成されたコントローラのクラス( src/test/groovy/myapp/ItemControllerSpec.groovy )を以下のように変更します。

package myapp

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body

@Controller("/item")
class ItemController {
    @Post(uri="/", consumes=["application/json"], produces="application/json")
    def index(@Body def contents) {
        println contents
        [hello:'world']
    }
}

consumes で 受け取るデータの MIME Type を指定、produces で 返すデータの MIME type を指定しています。

それでは、変更を保存して、サーバを起動。

$ ./gradlew run

curl を使って作動を確かめます。

$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 128000 }' -H "Content-Type: application/json"
{"hello":"world"}

サーバを起動したコンソールの方に、POSTした json がSTDOUTされています。

{ "name": "mac mini", "price": 128000 }

サーバで受け取ったのは contents について調べてみます。 さらに ItemController を修正:

package myapp

import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import io.micronaut.http.annotation.Body

@Controller("/item")
class ItemController {
    @Post(uri="/", consumes=["application/json"], produces="application/json")
    def index(@Body def contents) {
        println "${contents.getClass()} / ${contents}"
        [hello:'world']
    }
}

再度サーバを起動して、curl で作動確認。

$ ./gradlew run
$ curl -X POST "http://localhost:8080/item/" -d '{ "name": "mac mini", "price": 128000 }' -H "Content-Type: application/json"
{"hello":"world"}

サーバを起動したコンソールの方を確認します。

com.fasterxml.jackson.databind.node.ObjectNode / { "name": "mac mini", "price": 128000 }

となりました。

つまり、サーバ側で受け取った contents は com.fasterxml.jackson.databind.node.ObjectNode のインスタンスです。 したがって、name 値や price 値を取り出すには、以下のようにして取り出せます。

contents.name.textValue()
contents.price.intValue()

jquery で試す

curl でうまくいったので、今度は ブラウザ上から jquery を使って意図通り作動するか試してみます。

以下のような index.html を準備.

<html>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(function() {
  var contents = JSON.stringify({
      name: 'MacMini',
      price: 128000});

  $.ajax({
    url: 'http://localhost:8080/item/',
    type:'post',
    contentType:'application/json',
    data: contents,
    dataType:'json',
    success: function (data) {
      console.log('OK: '+JSON.stringify(data));
    },
    error: function (xhr) {
      console.log("err: " + xhr);
    }
  });
});
</script>
</body>
</html>

これをブラウザ(chrome)で実行して、コンソールを見ると:

Access to XMLHttpRequest at 'http://localhost:8080/item/' from origin 'null' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

CORS がなんとか、というエラーが出ている。 サーバ側でクロスオリジンを許可する必要があるらしい。

自分の雑な理解では、サーバが返すヘッダで Access-Control-Allow-Origin: * を含めることでクロスオリジンが通るようになるはず。

Micronaut ではこの設定は src/main/resources/application.yml に cors の設定を追加すればよい。

micronaut:
  application:
    name: myapp
  server:
    cors:
      enabled: true

この設定をした上で、再度 ./gradlew run を実行して、ブラウザをリロード:

今度は意図通りコンソールにサーバから来た json 表示されました。

OK: {"hello":"world"}

まとめ

CORS の部分でつまづきましたが、なんとか HTML 上の javascript から Micronaut に json を POST して json を受け取る作動、できました。