Works by

Ren's blog

@rennnosuke_rk 技術ブログです

【Java】AdoptOpenJDK 11がLTSをサポート

Javaのサポートについて

OracleJavaへのサポート体制の変更が波紋を呼んでいます。

qiita.com

www.orangeitems.com

Oracle JDK 11の有償化

Oracle Java SE サポート・ロードマップ

事の発端は、OracleJava 11の提供を有償化する声明を出したことでした。

Oracleは今まで、Javaのバージョンを約3年ごとにリリースし、約5年ごとのサポート期間を設けていました(Long Term Support、LTS)。
例えば、

  • Java 6 (Update 10)・・・2008年10月22日にリリース
  • Java 7 ・・・・2011年7月28日にリリース(約5年後の2015年4月30日にサポート終了)

となっています。

しかし、Oracleは2017年9月にリリースされたJava9以降6ヶ月ごとにリリースを行うスタイルに変更します。 同時に、次回verがリリースされるのと同時に、前回verのサポートを打ち切る方針に転換しました(Feature Release Model)。

  • Java9 ・・・2017年9月21日にリリース(2018年3月にサポート終了)
  • Java10・・・2018年3月20日にリリース(2018年9月にサポート終了)

すなわち、Oracle Javaを今後使っていく人は早いサイクルでアップデートをし続けなくてはならない、という流れになりつつありました。 本来であれば、セキュリティや新機能実装の観点からこまめなアップデートは推奨されるべきなのですが・・・。 中~大規模なシステムだとアップデート作業やテスト、デグレ解消に結構な工数がかかるので、長期間安定して使えるJDKが欲しいというのが実情だと思います。

ところが2018年9月、OracleJava 11がリリースを決定したのですが、Java 11 の商用利用を有償化し、同時にLTSとすると発表したのです。
システム運用等の業務でJavaを使っている人からすれば長期サポートは嬉しいのですが、いきなりの有償化宣告に対応する余裕はありません。
なんとかして無償でJavaを使い続けられる環境を維持したいものです。

ちなみにJava8はサポート期限が2019年1月とJava9よりもあとまでのサポートとなっています。
期間的にはだいぶ長めですが、来年頭にはサポートが切れるので同様の対応が必要になります。

f:id:rennnosukesann:20180624000254p:plainOracle 公式より引用)

Java8~10の刻々と迫るサポート期間、Java11 LTS の有償化にJava界隈がざわついていました。

OpenJDK

OpenJDK

OpenJDKはその名の通り、Javaプラットフォームをオープンソース化したものです。
OpenJDKの実装にはOracleも参画しており、商用にも耐えうる実装であると考えられます。実際、OracleはOpenJDKの2018年の最新バイナリをOracle JDKに統合した上で、今後のOracle JDKを運用していく旨を発表しています。またオラクルの声明では以降無償Javaを利用するにはOpenJDKを使ってねとも言っています。

こちらのJDKであれば無償で使うことができますね!

・・・と思いきや、OpenJDKはLTSをサポートしていません。
つまり、OpenJDKを利用する場合、6ヶ月ごとにJDKのバーションをアップデートしなければならなくなります。 ここで再びFeature Release Modelの問題が発生します。
無料で、かつLTSなJDKが欲しい・・・!

AdoptOpenJDK 11

そんな中、AdoptOpenJDKが興味深いサポートライフサイクルを提示していました。

adoptopenjdk.net

AdoptOpenJDKはIBMRedHat、SAP、オラクル等に所属するメンバーが参画するOpenJDKコミュニティーです。 OpenJDKのビルドを提供します。 彼らの提供するJava 11のJDKは、無償かつLTSとのことでした。

adoptopenjdk.net

12以降はどうなるかわかりませんが、少なくともJava 11を3年間サポートを受けながら使えるようですね。素晴らしいです!

ただ、公式のgithubのissueでビルドできないとの報告も上がっており、少々不安も感じさせます。

github.com

OpenJDK でも Java 11 をLTS化?

orangeitemsさんの記事に最新情報があがっていました。

また、Redhatの姿勢が明らかになっています。2018/6/4に、RedHat社は、OpenJDK8のサポート終了後は、OpenJDK11をリリースしこれをLTS(長期サポート)すると明言しました。
Red Hat OpenJDK 11 Advice - Red Hat Customer Portal
RHELでOpenJDK8を動かしているのであれば、11への移植をお勧めします。
https://www.orangeitems.com/entry/2018/02/08/152022 より引用

どうやら、RedHatが公式にOpenJDK 11をLTS化することを発表したようです。
リンク先の記事を参照したかったのですが、subscription専用なので読み進められない・・・

これが本当であれば、今後の無償JavaOracleの声明どおりOpenJDK一択となりそうです。

参考

www.publickey1.jp

www.orangeitems.com

Oracle Java SE サポート・ロードマップ

qiita.com

OpenJDK

【OAuth】Twitter OAuthでのWhite ListにCallback URLを登録する

Twitter 認証APIの仕様変更

6/12-13(?)ごろ、Twitter 認証用APIの仕様が変更され、パラメータとして指定されたcallback_urlがApplication Manager上で登録されていない場合、HTTP 403 エラーを返す仕様となりました。

これを受け、Tiwtter連携を扱うサービスのログインなどで一部不具合が見られました。

企業が提供するアプリはもちろんのこと、個人で開発しているアプリでも同様の現象が発生しうるので、今回はそれらの対応方法について書きます。

Application Managerの設定を変更する

Twitter Application Managerページに移動します。アプリを管理するアカウントにログインする必要があるので、ログインしていない方は予めログインしてください。

apps.twitter.com

次に、設定するアプリ名をクリック。

f:id:rennnosukesann:20180620171401p:plain

「Service」タブをクリックします。

f:id:rennnosukesann:20180620171543p:plain

「Callback URLs」という欄があるので、入力フォームにCallbackURLを入力し、「add a Callback」をクリックしてください。CallbackURLは最低2つ入力する必要があります。

f:id:rennnosukesann:20180620171651p:plain

あとは画面一番下の「Update Setting」を押して完了です!

余談

Twitter連携で認証・認可後、利用したいユーザデータにemailを含めたい場合は「Permissions」タブ->「Additional Permissions」欄のチェックマークにチェックを入れることで可能となります。

参考

Callback URL — Twitter Developers

【Watson】Watson Studio でMNIST手書き文字認識を行う①【Watson Studioセットアップ】

Watsonとは

www.ibm.com

IBM Watsonは、IBMが提供するAIサービスです。
主に自然言語処理系の機械学習を行うAIを提供しており、文章のカテゴライズや文章と音声間の変換などをサポートします。 また自然言語処理だけでなく、画像認識の機能の提供も行っています。

Watson Studioとは

www.ibm.com

Watson Studioは、機械学習を用いたデータの統合開発・分析環境です。
従来のWatsonが提供するAIサービスにとらわれず、機械学習のためのモデル作成や学習を柔軟に行うことができます。
今までpythonを使ってTensorflowやChainerなどをゴリゴリ書いていた人も、Watson Studioを使えば簡単にモデルを構築でき、パラメータ調整やモデルアーキテクチャの構成に集中できそうです!

今回はWatson Studioを使って、手書き文字データセットであるMNISTをクラス分類する実験を行いたいと思います!

MNIST

Usage

それでは、Watson Studioを使ってみましょう!

使用にはIBM Cloud アカウントが必要なので、アカウントがない人は先に取得を行いましょう。

↓の記事に従うと、ライト・アカウントを取得することができます。

rennnosukesann.hatenablog.com

IBM Cloud Watson Studioを導入する

IBM Cloudライト・アカウントを手に入れたら、ダッシュボード画面に入ります。

ダッシュボード画面に入ったら、画面右上の「リソースの作成」ボタンをクリック。

f:id:rennnosukesann:20180619213849p:plain

するとサービス一覧が掲載されたカタログが展開されるので、スクロールして"Watson"の欄を探し、右下の「Watson Studio」をクリックします。

f:id:rennnosukesann:20180619213954p:plain

Watson Studioサービスの詳細画面に遷移します。 内容を確認したら「作成」をクリックします。

f:id:rennnosukesann:20180619214735p:plain

Watson Studioサービスが作成されました!
「Get Started」を押し、サービスを開始しましょう!

f:id:rennnosukesann:20180619214555p:plain

ちなみにこちらの WML(Watson Machine Learning)サービスインスタンスも作成してください!

f:id:rennnosukesann:20180621223343p:plain

続き

rennnosukesann.hatenablog.com

参考

dataplatform.ibm.com

【IBM Cloud】IBM Cloud ライト・アカウントを取得する

IBM Cloudとは

www.ibm.com

IBM Cloudとは、IBMが提供するビジネス用クラウドソーシングサービスです。
IaasからSaaSに渡るビジネス向けのサービスを多く取り揃えているのが特徴です。そのためAWSやAzuleのような個人デベロッパーやスタートアップによく使われるクラウドとは対象的に、企業におけるビジネス活用が目立つクラウドです。

AIサービスで有名なWatsonも、IBM Cloudのサービスとして組み込まれています。

今回はWatsonのようなサービスを個人でも利用できるようにするため、IBM Cloudライト・アカウント登録のフローを紹介します。

Usage

IBM アカウントの作成

IBM Cloud用のアカウントを作成するためにはIBM アカウントが必要なので、先にこちらから取得を行います。

IBM Cloudのページにアクセスし、画面右上の人物アイコンをクリックしてプルダウンを表示、その後「サインイン」ボタンを押します。

f:id:rennnosukesann:20180618213639p:plain

するとサインイン画面に遷移しますが、アカウントがないので「IBMidを作成します」をクリック。

f:id:rennnosukesann:20180618213852p:plain

すると名前等を入力する欄があるので、それぞれに記入し「次へ」をクリック。

f:id:rennnosukesann:20180618214056p:plain

アカウントプライバシーについて同意を求められるので、確認しつつ「Proceed」をクリック。

f:id:rennnosukesann:20180618214249p:plain

これでIBM アカウント自体の登録は完了です(メールも届いたと思います)。
また登録後、人物アイコンのプルダウンがログイン状態になっていることも確認できます。

f:id:rennnosukesann:20180618214514p:plain

IBM Cloud ライト・アカウントの作成

次にIBM Cloudのライト・アカウント(無料)の作成を行います。
最初に、画面右上の「マーケットプレイス」をクリック。

f:id:rennnosukesann:20180618214645p:plain

マーケットプレイス内の「IBM Cloud」をクリック。

f:id:rennnosukesann:20180618214753p:plain

IBM Cloudの商品ページに遷移するので「無料評価版を始める」をクリックします。

f:id:rennnosukesann:20180618215122p:plain

遷移先のページでライト・アカウントの案内があるので、「ライト・アカウントを今すぐ登録」をクリック。

f:id:rennnosukesann:20180618215217p:plain

ライト・アカウント登録フォームが表示されるので、先程IBMアカウントに登録したメールアドレスをクリック。

f:id:rennnosukesann:20180618215442p:plain

すると登録メールアドレスに確認用メールが届くので、メール内の確認ボタンを押します。
確認後遷移した画面にログインボタンがあるので押し、ログインが成功すれば登録完了です。

f:id:rennnosukesann:20180618215655p:plain

f:id:rennnosukesann:20180618215952p:plain

参考

www.ibm.com

【React Native】Native Base でiOS/AndroidのUIを構築する

Native Base

nativebase.io

NativeBaseはReact Nativeで使うことのできるプラットフォームUIコンポーネントです。 iOS/Androidそれぞれに適切なUIを提供します。

例えば、iOS用のヘッダーには下図のような平坦なデザインが多いのですが、Androidではマテリアルデザインを踏襲したヘッダーが主流です。

f:id:rennnosukesann:20180618205049p:plain:w300

f:id:rennnosukesann:20180618205235p:plain:w300

Native Baseではこのような差異を吸収した共通のUIコンポーネントを提供してくれます。

それでは、早速使ってみましょう!

Usage

何はともあれ、インストールします。

最初は、create-react-native-app を使ってReact Nativeのプロジェクトを作成しましょう。

$ create-react-native-app native-base-app

create-react-native-appをまだインストールしていない方は下記記事を参考にしてください。

rennnosukesann.hatenablog.com

次に、作成したプロジェクトにnative-baseを入れていきます。

$ npm install --save native-base

これで準備完了です!

Source

iOSAndroid、それぞれの端末でUI/UXが異なるのを確認すべく、

  • ヘッダー
  • フッダー
  • ボタン
  • DatePicker
  • 入力フォーム

を試しに配置してみました。

import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { Container, Header, Left, Body, Right, Button, Icon, Title, Text, Footer, Content, Card, CardItem, DatePicker, Form, Item ,Label, Input} from 'native-base';
export default class GeneralExample extends Component {
  render() {
    return (
      <Container style={styles.container}>
        <Header style={styles.header}>
          <Left>
            <Button transparent>
              <Icon name='arrow-back' />
              <Text>Back</Text>
            </Button>
          </Left>
          <Title>Header</Title>
          <Right>
            <Button transparent>
              <Icon name='menu' />
            </Button>
          </Right>
        </Header>

        <Content style={styles.content}>
          <Button >
            <Text>
              Button
          </Text>
          </Button>

          <Card>
            <CardItem>
              <Body>
                <Text>
                  Card
                </Text>
              </Body>
            </CardItem>
          </Card>

          <DatePicker
            defaultDate={new Date(2018, 4, 4)}
            minimumDate={new Date(2018, 1, 1)}
            maximumDate={new Date(2018, 12, 31)}
            locale={"en"}
            timeZoneOffsetInMinutes={undefined}
            modalTransparent={false}
            animationType={"fade"}
            androidMode={"default"}
            placeHolderText="Select date"
          />

          <Form>
            <Item fixedLabel>
              <Label>Input..</Label>
              <Input />
            </Item>
          </Form>

        </Content>

        <Footer style={styles.footer}>
          <Text>Footer</Text>
        </Footer>
      </Container>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    width: "100%",
    height: "100%",
  },
  content: {
    padding: 30,
  },
  header: {
    alignItems: "center",
    justifyContent: "center"
  },
  footer: {
    alignItems: "center",
    justifyContent: "center"
  }
});

Demo

iPhone

f:id:rennnosukesann:20180618203812g:plain:w300

Android

f:id:rennnosukesann:20180618202639g:plain:w300

iOSはデフォルトUIのデザイン、Androidマテリアルデザインで表示されているのがわかりますね!

今まではReact Nativeで「iOSAndroid、どちらでも"動く"」アプリは作れましたが、
Native Baseをつかうことで一つのアプリで別々のUIを提供できるようになりました! (Native Base の提供する範囲内に限っての話ですが。。。)

これでクロスプラットフォームアプリ制作がはかどります!

参考

nativebase.io

【Yarn】Yarnをインストールする

Yarnとは

f:id:rennnosukesann:20180616080607p:plain:w300

YarnはFacebookが開発したパッケージマネージャです。Yarnは、Nodel.js上で用いられるパッケージマネージャであるnpmを代替します。

yarnpkg.com

前回の記事でも触れましたが、npmは昨今のWeb開発では頻繁に用いられています。一方で、npmはパッケージインストール時のエラーに悩まさえることが少なくありません。

またFacebook曰く、npm自体、現行の企業のアプリ開発業務の規模に耐えられなくなりつつあるようです。

そこでFacebookは新しいパッケージマネージャとしてのYarnを開発しました。Yarnはnpmにない新しい機能・規模感・安定性を提供するパッケージマネージャとして、少しずつ広まりつつあるようです。

今回はYarnを実際にインストールし、その機能を見ていきます。

Yarnの特徴

オフラインインストール

パッケージがダウンロード済みの場合、何度でもインストールできます。ローカルにパッケージがキャッシュされます。

npmと環境を共存できる

npmと同じnode_modules内でパッケージを管理でき、package.jsonで依存関係の管理も行うので、npmからの移行が簡単です。

高速

前述のオフラインインストールに加え、Yarnはインストール時のリクエストを効率的にキューイングすることでネットワークパフォーマンスの向上も達成しているようです。

Usage

Yarnのインストール

環境はMac OS X High Sierra 10.13.4 です。

ドキュメントにもある通り、brewまたはMacProtsでインストールできます。

# brew
$ brew install yarn
# MacPorts
$ sudo port install yarn

YarnをNodeなしでインストールできます。YarnはデフォルトでNodeとともにインストールされます。

$ brew install yarn --without-node

これでOKです!

Yarnを使ってプロジェクトを作成

結論を言ってしまうと、npmと使い方はほぼ全て同じです!

プロジェクト初期化はyarnコマンドで実行できます。yarn initでも可能です。

$ yarn
yarn install v1.7.0
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 0.08s.

yarn addで依存関係を追加できます。

$ yarn add [package] --dev
$ yarn add [package] --peer
$ yarn add [package] --optional

追加した依存関係をインストールしましょう!

$ yarn install

yarn install [package]で依存関係の追加を行わずにパッケージのインストールができます!

$ yarn install [package]

依存関係を削除するには、yarn remove [package]を使います。

$ yarn remove [package]

インストールしたパケージのまたアンインストールは下記で可能です。

$ yarn uninstall [package]

npmと全く一緒で乗り換え楽勝でした。

参考

yarnpkg.com

jp.techcrunch.com

【Java】JAX-WSでJSON Body Parameterをサーバ側でMapとして受け取る

JAX-WSとは

JAX-WSJavaのサーバサイドフレームワークであり、JavaクラスとAPIの構造をマッピングする機能を持ちます。
クラスやメソッドに対してアノテーションを付加することで、簡単にマッピングすることができます。
例えば、APIサーバがapi/hoge/getGETメソッドを提供したい場合、下記のように記述することができます。

import java.util.List;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import hoge.fuga.Request;
import hoge.fuga.Response;

@Path("hoge")
@Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8")
public class APIResource {

    @POST
    @Path("post")
    public Response post(Request request) {
        ...
        return result;
    }

}

クラス、及びメソッドがAPIの階層構造にマッピングされ、整然と記述することができます。

ボディパラメータ(application/json)を受け取る

以前より、application/json形式のリクエストボディをサーバが受け取れるようにするため、リクエストパラメータ受け取り用クラスをAPIごとに定義していました。

例えば、上記コードのpostメソッドの引数となっているRequest型変数には、JSON形式のリクエストボディをJavaオブジェクトに変換した結果が格納されています。この変数の型となっているRequestクラスは、上記postメソッドのリクエストボディを受け取るためだけに作られた専用のクラスになります。

Request.java
public class Request {
    private int id;
    private int label;
    private int page;
}

このやり方で進めてしまうと、JSONボディパラメータを受け取るAPIメソッド一つ作るたびに、専用のパラメータ受け取り用クラスを作成しなければなりません。

APIごとに類似したレスポンスを返すのであれば共通化・一般化したクラスを定義して使い回せばよいのですが、新たに受け取らなければ行けないパラメータが増えた場合、新たにクラスを定義する必要が出てきます。

対応策

Mapオブジェクトで受け取れました。。。

どうやらJAX-WSでは、ユーザ定義クラスに対するマッピングだけでなく、Mapクラスに対するオブジェクトマッピングも行ってくれるみたいです。

import java.util.List;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import hoge.fuga.Response;

@Path("hoge")
@Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8")
public class APIResource {

    @POST
    @Path("post")
    public Response post(Map<String, Object> request) {
        // Map内のパラメータを解体
                String name = (String)request.get("name");
                String label = (String)request.get("label");
                int page = (Integer)request.get("name");
                ....
        return result;
    }

}

ただし、MapのValue型が殆どの場合Objectになってしまうので、型変換が暗黙的になってしまうというデメリットはありますが。。。 ココらへんは、仕様書にきちんと記述するなり、コメントで記述するなりしっかりしておく必要があると思います。

JAX-WSの仕様を把握しきれていなかったというオチでした。。。