uokadaの見逃し三振は嫌いです

ここで述べられていることは私の個人的な意見に基づくものであり、私が所属する組織には一切の関係はありません。

3分間DNS基礎講座を読んだ。

3分間DNS基礎講座

3分間DNS基礎講座

3分間DNS基礎講座:書籍案内|技術評論社

DNS周りで有耶無耶にしてきた知識を簡単に復習したいというう意味合いで本書を読んだ。 DNSの仕組み、レコードの種別、やりとりされるデータの中身などエンジニアが利用者として必要になる知識を覚えたいのであればこの本を読むだけで十二分な知識が得られる。

bind, unboundのような具体的なDNSサーバーの運用に関しては全く書かれていないのでそういったものを期待するならオライリーDNS本を読むのが良い。

また、個人的に印象に残ったのがTCPのウインドウサイズやフロー制御にもふれている部分があってそれを学べる本があったのは意外だった。

シリーズの他の本は電子版が出ているんだがこの本だけ電子版になっておらず身近な本屋さんにもなかったためブックオフで見つけてきた。 本書の後半でFTP, Telnetに関してふれられているがモダンな環境では使われるものではないのでその部分を簡素化・再編して電子版が出版されてもいいように感じた。

JavaのAutoCloseableを使ってみた

【Java】try-with-resources構文について - TASK NOTES

Java7 AutoCloseableを使ってスマートにリソース解放する - ほげにっき

import java.io.IOException;

public class App {

    public static void main(String[] args) {
        try (JCLOSEFile jcloseFile = new JCLOSEFile()) {
            jcloseFile.getX();
        } catch (IOException e) {
             e.printStackTrace();
        }
    }

    public static class JCLOSEFile implements AutoCloseable {

        public void getX() throws IOException {
            System.out.println("throw exception from getX");
            throw new IOException("my exception");
        }

        @Override
        public void close() throws IOException {
            System.out.println("close Method is Called!");
            throw new IOException("from close method");
        }
    }
}
% <Java>
throw exception from getX
close Method is Called!
java.io.IOException: my exception
    at io.github.yuokada.App$JCLOSEFile.getX(App.java:19)
    at io.github.yuokada.App.main(App.java:9)
    Suppressed: java.io.IOException: from close method
        at io.github.yuokada.App$JCLOSEFile.close(App.java:25)
        at io.github.yuokada.App.main(App.java:10)

出力結果を確認するとgetX() から例外を投げられて呼び出されたclose()メソッドからも例外が投げられてます。
それをcatch節で捕まえてます。SuppressedExceptionsにはclose()から投げられた例外がセットされています。

簡単に全ての例外を捕まえられるのでAutoCloseableは使っていきたいですね。

やっぱり、実際に実装すると理解が深まりますね。

swagger-codegenをやってみた。

github.com

仕事でWebAPIを作る必要があってせっかくだからswaggerをやっている。 本当はgrpcかthriftみたいなバイナリプロトコルでやりとり出来るものがやりたいんだけどリクエスト数も少なくブラウザからリクエストすることもありそうなので素直にHTTPでやりとり出来るWebAPIを作っている。

thrift, grpcなら定義ファイル自体がドキュメントになるんだがWebAPIのドキュメントを書くとなるとメンテナンス性なども考えることが出てくる。 WebAPIを長期間運用したことがあるけどいろいろな理由をつけてドキュメントの更新は後回しになりがちなのでそうならないようにちょっとswaggerでドキュメントの生成とさらにコードの生成を自動化したいなと思い使ってみている。

今はSwagger Editorのサンプルコードを動かしつつswaggerがどういったものかの理解を進めている。

Swagger Editor

それに合わせてyamlを更新したら簡単に成果物を生成したかったのでgradleの設定を書いている。

plugins {
    id 'org.hidetake.swagger.generator' version '2.12.0'
}

group 'io.github.yuokada'
version '1.0-SNAPSHOT'

apply plugin: 'groovy'
apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    jcenter()
    mavenCentral()
}

dependencies {
    swaggerCodegen 'io.swagger:swagger-codegen-cli:2.3.1'
    swaggerUI 'org.webjars:swagger-ui:3.10.0'

    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    compile 'org.codehaus.groovy:groovy-all:2.3.11'

    testCompile group: 'junit', name: 'junit', version: '4.12'
}

swaggerSources {
    petstore {
        inputFile = file('src/main/resources/swagger/v1.yaml')
        code {
            language = 'spring'
            configFile = file('src/main/resources/swagger/config.json')
            outputDir = file('output')
            // Generate only models and controllers
            components = ['models', 'apis']
            dependsOn validation

            doLast {
                copy {
                    from "${code.outputDir}/src/main/java/io/github/yuokada/swagger/demoapi"
                    // from 'output/src/main/java/io/github/yuokada/swagger/demoapi/impl/*.java'
                    into "src/main/java/io/github/yuokada/swagger/demoapi"
                }
            }
        }
        ui {
            doLast {
                copy {
                    from 'index.html'
                    into outputDir
                }
            }
        }
    }
}

github.com

これでyamlを更新したら適宜コード生成をする環境が整ったのでガンバっていけそう。

デジタルマーケターとWeb担当者のためのGoogle&Yahoo!タグマネージャーの教科書を読んだ

Kindleでセールしているのをみかけてこの辺のバックエンド・システムを作っていたこともありポチってみた。

感想をざっくりと箇条書き。

  • 業務ではじめて右も左もわからないなら1章を読んで次に4章から読み始めるのが良いだろう。
  • 4章はタグマネージャーの導入と運用に関する章でどういう指針でタグマネージャーを選ぶか、運用の目的に合わせたタグマネージャーの選び方を説明してくれている。
  • そして、4章を読んで運用方針が決められたらその次に利用するタグマネージャーごとの章(2章、3章)を読んでいく。
  • GTM, YTMの機能の紹介を読んで足りない機能があるのであれば両方共使うという選択肢を選ぶのもあり。
  • エンジニアは4章のあとに裏側のシステムであるビーコンから集計のシステムのところを読むのが良い。
    • ビーコンの解説はあまりみないので貴重。
    • また、ビーコンが飛ばずに集計が出来ないときのデバッグのテクニックも掲載されているので読んでおけば実運用が始まったときには絶対に役に立つ

以上、ざっくりとした感想でした。

Sphinxの環境をpython3対応した話

昨日、github-pagesの生成に使っているSpinx環境を python3.6に移行した。

使っているライブラリを最新のバージョンにあげるだけで問題なかったが1つだけpython3に対応していないものがあってそれがsphinxtogithub

sphinxtogithub · PyPI

このライブラリはsphinxで生成したページのcssなどのリンクを_staticからstaticに変えるというライブラリです。

_staticだとgithub-pageでcssにアクセスさせてくれずstaticに変える必要がありこのライブラリがないというのは結構致命的にな問題であった。

対応策を探すためにライブラリのgithubリポジトリをみていたところpython3対応のPRがすでに出されていた。

Added Python 3 compatibility, without breaking Python 2.7 by proycon · Pull Request #9 · michaeljones/sphinx-to-github

このPRは3年ほど放置されていてマージが期待出来なかったのでPR作者のリポジトリからライブラリを取るようにしてpython3対応を完了させた。

pipで次のようにすればPRもとからライブラリをインストール出来ます。

% pip3.6 install -e "git+git://github.com/proycon/sphinx-to-github.git#egg=sphinx-to-github"

requirements.txtに書くときは下のようにするとインストール出来ます。 自分は上のpipコマンドでインストールしてpip freezeした結果をrequirements.txtに記述しているのでコミットのハッシュを含んだ値をセットしています。

# sphinxtogithub==1.1.0
-e git://github.com/proycon/sphinx-to-github.git@9b61be70ccfbec99724544c3e94ed1c43fb5295c#egg=sphinxtogithub

こんな感じで1時間ほどでpython3移行を完了することが出来ました。 python3移行を数年放置してたんですが思ったよりも簡単だったのでみなさんもちょっとした空き時間にやってみると良いのではないでしょうか。

エキスパートPythonプログラミング改訂2版

エキスパートPythonプログラミング改訂2版

メモ書き, Mavenでno dependency information availableエラーが出来た時の対処法

% ./mvnw clean compile package
/path/to/presto-sample-udf
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building presto-sample-udf 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[WARNING] The POM for org.eclipse.jetty:jetty-alpn-java-client:jar:9.4.6.v20170531 is missing, no dependency information available
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.108 s
[INFO] Finished at: 2018-02-11T14:14:08+09:00
[INFO] Final Memory: 15M/50M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project presto-sample-udf: Could not resolve dependencies for project io.github.yuokada:presto-sample-udf:jar:1.0-SNAPSHOT: The following artifacts could not be resolved: com.sun:tools:jar:1.8, org.eclipse.jetty:jetty-alpn-java-client:jar:9.4.6.v20170531: Could not find artifact com.sun:tools:jar:1.8 at specified path /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/../lib/tools.jar -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

JDK9でビルドでしていたのが原因でエラーになっていたみたい。 Macだとこんな感じでJDK8を使うように環境変数を設定してやると上手くうごくようになる。

export JAVA_HOME=`/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -v "1.8"`

Java8-mavenを使ったユニットテストでTimezoneを指定する

手元のMacbook Proで通っていたユニットテストTravis-CI上で実行したら失敗したので原因を探っていたところ、 Travis-CI上だとタイムゾーンの設定が違っていることが分かった。

stackoverflowmave-surefire-pluginを使って指定する方法があったのでそれを試してみた。

Maven Surefire Plugin – Introduction

maven-surefire-pluginを下のような形でsystemPropertyVariables -> user.timezone をセットする。
たった、これだけでTimezoneを上書き出来る。

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20.1</version>
                <configuration>
                    <systemPropertyVariables>
                        <user.timezone>Asia/Tokyo</user.timezone>
                    </systemPropertyVariables>
                </configuration>
            </plugin>

仕事で作ったPrestoプラグインで試してみたらZoneId.systemDefault()の戻り値が指定した値に上書きされてユニットテストが通るようになった。

Change GregorianCalendar to ZonedDateTime by yuokada · Pull Request #3 · yahoojapan/presto-audit

ただ、stackoveerflowの記事をよく読むとうまくいかない的なことが書いてあるんだがうまく動いた理由はなんでだろう?

疑問は残りつつも一旦これで対応完了としたい。