unhurried

コンピュータ関連ネタがほとんど、ときどき趣味も…

Procedure to Print with Google Cloud Print API

Recently printers connected to the Internet became common. As some of my web services required printing in the background process, I have researched Google Cloud Print API as one of printing measures.

(0) Get a client ID and a client secret in Google API Console

(1) Show an authorization page and get a grant from the user.

https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri={registered redirect URI}&
response_type=code&
client_id={issued client ID}&
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloudprint&
access_type=offline

(2) Receive an authorization code in the redirect URI and exchange it for an access token.

  • The browser will be redirected to the redirect URI with an authorization code in the code parameter.
  • Send the authorization code extracted from the URI to the token endpoint and get an access token.
Request

POST https://www.googleapis.com/oauth2/v4/token
Content-Type: application/x-www-form-urlencoded

code={authorization code}&
client_id={issued client ID}&
client_secret={issued client secret}&
redirect_uri={registered redirect URI}&
grant_type=authorization_code

Response

{
  "access_token": {access token},
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": {refresh token}
}

(3) Call the printer search API and get the printer ID.

Request

GET https://www.google.com/cloudprint/search
Authorization: OAuth {access token}

Response

{
 "printers": [
 {
  "id": {printer ID},
  "displayName": {display name of the printer},
  ...
 }]
  ...
}

(4) Call a printer job submit API and execute printing

  • e.g.) a request to print the web page by specifying a URL
POST https://www.google.com/cloudprint/submit
Content-Type: application/x-www-form-urlencoded

printerId={printer ID}&
title={print title}&
contentType=url&
content={URL to print}&
ticket={ticket object}
{"version":"1.0","print":{"vendor_ticket_item":[],"color":{"type":"STANDARD_MONOCHROME"},"copies":{"copies":1}}}

Reference

MongoDB Node.js Driver Connection Management

Points

  • Call MongoClient.connect only once, and reuse the instance.
  • Connection management is done by the driver and the number of connections can be specified in the option of MongoClient.connect.

Sample Code

  • db.js
// Keep the mongoDB connection while the application is running.
var db = null;
module.exports.initialize = co.wrap(function*() {
    db = yield MongoClient.connect("mongodb://...");
});

module.exports.getById = co.wrap(function*(id) {
var col = db.collection("collection");
    var row = yield col.findOne({_id:id});
    return row.property;
});
  • app.js
var db = require('./db');

co(function*(){
    db.initialize();
    var result = db.getById(0);
    ...
});

Reference

アメリカで購入できる胃薬

胃が弱いのでよく胃薬にお世話になります。 アメリカに来た当初は何を買えばよいかわからなかったので、定番を調べてみました。

  • Tums

    • 気軽に飲める制酸剤。カルシウムの補給用途にも使える。
  • Zantac

    • H2ブロッカーという胃酸分泌を抑制する薬。
    • 日本の薬局で購入できるガスター10と成分は異なるが同様の効果。
  • Nexium

  • Gax-X

    • 腹部膨満時に利用する消泡剤。
    • 日本でよく処方されるガスコンに似た成分が入っている。

JAX-RSアプリをHerokuにデプロイする

Javaで実装したREST APIをHerokuにデプロイするときに少し迷ったため、今後のためにひな形としてサンプルアプリを作成しました。

github.com

ポイント

ローカルで実行する

maven clean package
  • Web Runnerを起動する。
java -jar target/dependency/webapp-runner.jar target/*.war

MongoDB Node.JS Driver コネクション管理

Java + MySQLではどのフレームワークにも当たり前にあるコネクションプールのようなコネクション管理機能ですが、Node.js + MongoDBではどのように実装するのが常套手段なのかを調べました。

ポイント

  • MongoClient.connectは1度のみ呼び出し、databaseインスタンスを再利用する。
  • コネクション管理はDriverが行ってくれて、MongoClient.connectのオプションにコネクションプール数を指定できる。

サンプルコード

  • db.js
// Keep the mongoDB connection while the application is running.
var db = null;
module.exports.initialize = co.wrap(function*() {
    db = yield MongoClient.connect("mongodb://...");
});

module.exports.getById = co.wrap(function*(id) {
var col = db.collection("collection");
    var row = yield col.findOne({_id:id});
    return row.property;
});
  • app.js
var db = require('./db');

co(function*(){
    db.initialize();
    var result = db.getById(0);
    ...
});

参考

Callback地獄対策 (3) aa generator

今回は、Qiitaで人気のあるCallback地獄対策の記事で紹介されているaaについて調べてみました。

aaもcoと同様にGeneratorの仕組みを利用して簡単に並列・直列処理フローを記述できるようにするライブラリです。 aaはcoと比べるとthunkify/promisifyが同じライブラリにパッケージされていることと、thunkifyAll/promisifyAllでオブジェクト全体にかけれられるの良いところと思います。 一方で、co.wrapに相当する機能はなく、並列・直列処理フローを利用したyieldableな関数を作るときに少し不便と感じました。

const aa = require('aa');

// callbackを引数にとる関数を持つオブジェクト
var callbackObject = {
    func: function(message, timeout, callback) {
        setTimeout(function() {
            console.log(message);
            callback(null, message);
        }, timeout);
    }
};

// aa.promisifyAllはオブジェクト全体に対してpromisifyを適用する
// promisifyはcallbackを引数にとる関数をPromiseを返却する関数に変換する
// Promiseoにはgenerator内でyeild式を適用できる(yeildable)
var promisifiedObject = aa.promisifyAll(callbackObject);

// aa関数はcoと同様にGenerator(function*(){...})を渡すと、
// yeild式に指定されたPromiseの完了を待ってから処理を再開させる
aa(function*() {
    console.log('--- aa start ---');
    
    // 2つの関数を並列処理する
    // 並列処理をするにはyeildにArrayもしくはObjectを指定する
    var response = yield [
        promisifiedObject.funcAsync('aa two', 800),
        promisifiedObject.funcAsync('aa one', 600),
    ];
    console.log("response: " + JSON.stringify(response));

    // 2つの関数を直列処理する
    yield promisifiedObject.funcAsync('aa three', 200);
    yield promisifiedObject.funcAsync('aa four', 400);
    
    // aaを利用した関数の呼び出し(後述)
    yield wrappedFunction();

    console.log('--- aa end ---');

    // Generatorでreturnするとaa.then()に指定した関数が実行される
    return "Generator finished.";

    // いずれかのPromiseでreject関数が呼ばれると
    // aa.error()に指定した関数が実行される
    yield Promise.reject("An error happened.");

}).then(function(value){
    console.log('--- then start ---');
    console.log(value);

}).catch((error) => {
    console.log('--- error start ---');
    console.log(error);
});

// aaにはco.wrapに相当する機能がないため、
// yieldを利用した関数を定義するにはaa(function*(){})を返却する関数を作る
var wrappedFunction = function() {
    return aa(function* () {
        console.log('--- wrap start ---');

        var response = yield [
            promisifiedObject.funcAsync('wrap two', 800),
            promisifiedObject.funcAsync('wrap one', 600),
        ];
        console.log("wrap response: " + JSON.stringify(response));
        yield promisifiedObject.funcAsync('wrap three', 200);
        yield promisifiedObject.funcAsync('wrap four', 400);

        console.log('--- wrap end ---');

        return yield Promise.resolve(null);
    });
};

実行結果

$ node aa_generator.js
--- aa start ---
aa one
aa two
response: ["aa two","aa one"]
aa three
aa four
--- wrap start ---
wrap one
wrap two
wrap response: ["wrap two","wrap one"]
wrap three
wrap four
--- wrap end ---
--- aa end ---
--- then start ---
Generator finished.

参考

シリコンバレー周辺のお土産

最近にそれなりの量のお土産を買う機会があったので、お土産に良さそうなものを調べてみました。

探す条件

  • 多人数に配れるように個包装されている食べ物や飲み物
  • シリコンバレー周辺で購入できるもの
  • カリフォルニア、アメリカ、もしくは北米地域発祥で日本では入手しにくいもの

お土産リスト

  • Ghirardelli Chocolate

    • サンフランシスコ発祥の1852年から続く老舗チョコレートメーカー
    • 正方形のチョコレートが定番で色々なフレーバーがある
    • Great Mallにアウトレット、West Field Valley Fairに小さな販売ブースがある他、スーパーマーケット等でも購入できる
    • (アメリカの定番お土産になっているので新鮮味は少ないかも)
  • See's Candies

    • ロサンゼルスにて1921年に開業したチョコレート、キャンディメーカー
    • 棒つきのキャンディやチョコレートが人気がある
    • シリコンバレー周辺にお店が5,6店舗ある
  • Sugarfina

    • ロサンゼルスにて2012年に設立されたおしゃれなキャンディショップ
    • 箱に色々な種類のキャンディを組み合わせて詰めて
    • Santana Rowにお店がある
  • スーパーマーケットで購入できるお菓子(キャンディ、チョコレートなど)

    • Whole Foods、Trader Joe's、Safewayなどで購入できる
    • (Trader Joe'sのリテールブランドのお菓子は個包装のものが少ない)
  • DAVIDs TEA

    • カナダのトロントに2008年に開店した紅茶ショップ
    • アメリカにも多くの店舗を出店していて人気がある
    • Palo Altoにお店がある