B-Teck!

お仕事からゲームまで幅広く

TwitterのUser Streams API廃止について

Twitterは、8/16をもってUser Streams APIの提供を終了します。
移行先として、Acount Activity APIが提示されていますが、
ヘビーユーザーからは不満の声が上がっています。

今回は、なぜこれだけ騒がれているかを、知らない人向けにまとめてみようと思います。

そもそもAPIって何?

皆さんのツイートやリプライ、いいねやフォロー/フォロワーのリストなどは、
Twitterが持っています。
アプリケーションからそれらを利用したい場合に、システムから情報を取り出したり、
書き込んだりする仕組みをAPIといいます。
あなたがツイートボタンを押すと、書き込みAPIがTwitterのシステム内にツイートを書き込みます。
アプリケーションが、ツイート読み込みAPIでシステムからそのツイートを取り出すことで、
ツイートを表示することができます。

User Streams APIって?

User Streams APIは、これまでの間Twitterがユーザーに提供していた仕組みです。
一度、Twitterに情報を取りに行くと、
終了するまで下記の情報をリアルタイムで取得する事ができました。

  • タイムライン
  • ツイートの削除
  • DM の送信
  • 送信済み DM の削除
  • 他人からのフォロー
  • 自分のツイートの「お気に入り」登録
  • 公式 RT
  • リストへの登録・抹消
  • 自分のリストのフォロー / リムーブ

公式以外のTwitter向けアプリケーションでも、
タイムラインが快適に閲覧できるということで広く用いられていました。
これは、ユーザーにとって便利な反面、Twitter側にとっては情報を送り続けなければならない、
とてもコストがかかる仕組みでした。
また、広告等を配信することができないため、
Twitterにとってあまりメリットの有る形ではありませんでした。

Acount Activity APIって?

Twitter社が、User Streams APIを廃止する代わりに提供する仕組みです。
何が変わったのかというと、

  • リアルタイムでの情報配信を廃止し、取りに来たときだけ情報を渡すような仕組みに変更
  • タイムラインのツイートについては取得の代替案が提供されず、15分に15回の更新のみになる
  • User Streams APIが無料で利用できていたのに対して、こちらは実質有料
    • アプリケーションのユーザーが15人までの場合は無償
    • 16アカウントから250アカウントまではPremium版(339〜2899ドルの月額利用料金)
    • それ以上の利用の場合は「要問い合わせ」
      つまり、アプリケーション開発者に多くの負担がかかってくる形となります。

何が変わるの?

公式アプリケーション、Web、またはTweetDeck(Twitter社に買収されている)を除く、
多くのアプリケーションでツイート等の情報のリアルタイム読み込みが不可能になります。
公式以外では、15分に15回の更新以外に、タイムラインを更新する手段がなくなります。
今後の復帰もほぼ見込めないでしょう。

なぜ変わるの?

下記は推測半分なので読み飛ばしていただいても構わないのですが、おそらく

  • User Streams APIを維持するコストが無視できなくなった
  • User Streams APIでは広告を表示するのが難しいから

あたりだという説が有力です。

広告表示をせずTwitter社の収益とならない、
個人開発者のアプリケーションは締め出された形となります。

公式の説明としては、
こちらは1%未満の月間アクティブアプリで利用されているにとどまるため、本決定に至りました。
ということですので、今回のアップデートで混乱が起きている層は、
そもそもユーザーとしての対象外という結論であるのかも知れません。
Account Activity APIを全ての開発者の皆さんに公開

どうすればいいの?

現在は、Twitter公式アプリやwebがまともに時系列でタイムラインを表示してくれないので、
まともに並んだタイムラインを見たいのであれば、TweetDeck一択といった状況です。
TweetDeckは公式のアプリケーションなので、現在はツイートのリアルタイム表示にも対応しています。
今後のことを考えると安心はできませんが…。

参考:
Twitterサードパーティアプリは8月からリアルタイムのタイムライン取得が不可になる新API「Account Activity API」発表 - GIGAZINE

【Java/Kotlin】BufferedReaderの今風な書き方を調べてみた

Javaで書かれたBufferedReaderの処理をKotlin化する中で、
イマドキのJavaでの扱い方と、Kotlinの場合どう書くかを調べてみました。

サンプルはすべてsomeStream という入力を連結する場合の例です。

いにしえの書き方(Java)

BufferedReaderで入力が取れなくなるまでループする。

StringBuilder sb = new StringBuilder();
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(someStream, "UTF-8"));
while ( (line = br.readLine()) != null ) {
    sb.append(line);
}
br.close();
String result = sb.toString();

いまふうの書き方(Java)

Java 8から増えたBufferedReader.lines()でStreamとして取り出し、
Collectors.joining()で1つのStringにつなげる。
BufferedReaderはtry-with-resource文を使ってあげることで自動でcloseしてくれます。
いにしえの書き方よりだいぶシュッと書けます。

String result;
try (BufferedReader br 
    = new BufferedReader(new InputStreamReader(someStream, StandardCharsets.UTF_8))
) {
    result = br.lines().collect(Collectors.joining());
}

Kotlinで書くと…?

KotlinではInputStream.buferedReader()が生えているのでシュシュッと書けます。
BufferedReaderはcloseableなのでuseを使ってあげると自動でcloseしてくれます。

val result = someStream.bufferedReader().use { it.readText() }

参考:
java - Best way to use BufferedReader in Kotlin - Stack Overflow
bufferedReader - Kotlin Programming Language
use - Kotlin Programming Language
BufferedReader (Java Platform SE 8)

【Kotlin】KotlinでJava EEのBean Validationを使うときの注意点

Kotlinの場合のBean Validationのアノテーションの書き方

Kotlinでdata classをbean paramとして利用してBean validationを行う際、
下記のように書くと正しくvalidationされない。

  • パラメータが欠けると500エラーで死ぬ (?=fuga?hoge= など)
data class Test(
  @QueryParam("hoge")
  @NotNull
  val hoge: String?
)

これは、アノテーションがコンストラクタに付与されたとみなされており、
フィールド自体がvalidationされていないことが原因。
なので、明示的に@field:(または@get:)等をつけて、
Bean validationを利用できるようにする必要がある。

  • こっちだとOK
data class Test(
  @QueryParam("hoge")
  @field:NotNull
  val hoge: String?
)

参考 : KotlinでJSR303(Bean Validation)を使うときの注意 - mike-neckのブログ

@NotNullを付与したパラメータもNullableで受ける

アノテーションで@NotNullをつけている場合でも、
フィールドの型はNullableにする必要がある。
* これはNG

data class Test(
  @QueryParam("hoge")
  @field:NotNull
  val hoge: String
)
  • これはOK
data class Test(
  @QueryParam("hoge")
  @field:NotNull
  val hoge: String?
)

これは、一度パラメータを受け取ってフィールドに格納したあと検証するためで、
フィールドの方をNon Null型にしてしまうと、そもそも変数に格納できずエラーとなってしまう。