胃が弱いのでよく胃薬にお世話になります。 アメリカに来た当初は何を買えばよいかわからなかったので、定番を調べてみました。
Tums
Zantac
Nexium
- プロトンポンプ阻害薬(PPI)というH2ブロッカーより強力に胃酸分泌を抑制する薬。
- 日本では処方箋が必要だが、アメリカでは薬局で購入できる。
Gax-X
胃が弱いのでよく胃薬にお世話になります。 アメリカに来た当初は何を買えばよいかわからなかったので、定番を調べてみました。
Tums
Zantac
Nexium
Gax-X
Javaで実装したREST APIをHerokuにデプロイするときに少し迷ったため、今後のためにひな形としてサンプルアプリを作成しました。
Herokuのドキュメントに紹介されているWebapp Runnerを使ってアプリケーションを実行する。
参考:https://devcenter.heroku.com/articles/java-webapp-runner
JerseyではJAXB(JSONのシリアライズ・デシリアライズ)のライブラリにMOXyをを推奨しているが、Moxyは内部クラスやHashMapへのデシリアライズができないためJacksonを利用する。
参考:https://jersey.java.net/documentation/latest/media.html#json.moxy
http://stackoverflow.com/questions/29322605/how-to-return-a-json-object-from-a-hashmap-with-moxy-and-jersey
ResourceクラスやObjectMapperの設定はResourceConfigでできる。
(/src/main/java/com/example/ResourceConfig.java)
ResouceConfigクラスはweb.xmlのinit-param(javax.ws.rs.Application)で指定する。
JDKをインストールする。
参考:http://qiita.com/ko2a/items/69fa8a5366d7449500ca
Mavenをインストールする。
参考:http://qiita.com/ko2a/items/15343ea8fae4233e9438
アプリをビルドする。
maven clean package
java -jar target/dependency/webapp-runner.jar target/*.war
Java + MySQLではどのフレームワークにも当たり前にあるコネクションプールのようなコネクション管理機能ですが、Node.js + MongoDBではどのように実装するのが常套手段なのかを調べました。
// 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; });
var db = require('./db'); co(function*(){ db.initialize(); var result = db.getById(0); ... });
今回は、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
See's Candies
Sugarfina
スーパーマーケットで購入できるお菓子(キャンディ、チョコレートなど)
DAVIDs TEA
The second countermeasure of Callback Hell is using co. co is a library which utilizes Generator mechanism and make it easy to write serial and parallel flows.
const co = require('co'); const thunkify = require('thunkify') // a function which has a callback in its argument var callbackFunction = function(message, timeout, callback) { setTimeout(function() { console.log(message); callback(null, message); }, timeout); }; // thunkify converts a function with a callback to one returning a thunk. // yield can be applied to thunk in generator. (yeildable) var thunkifiedFunction = thunkify(callbackFunction); // a function which returns a Promise var promiseFunction = function(message, timeout) { return new Promise(function(resolve, reject){ setTimeout(function() { console.log(message); resolve(message); }, timeout); }); }; // When a Generator (function*(){...}) is passed to co, // co will proceed the process of the Generator until a yeild statement appear, // and resume the process after the Promise object is finished. co(function*() { console.log('--- co start ---'); // Process two functions in parallel. // Specify an array or an object to yeild. var response = yield [ thunkifiedFunction('co two', 800), promiseFunction('co one', 600), ]; console.log("response: " + JSON.stringify(response)); // Process two functions serially. yield thunkifiedFunction('co three', 200); yield promiseFunction('co four', 400); // Functions defined using co.wrap can be used in co generator. yield wrappedFunction(); console.log('--- co end ---'); // When return is called, co.then() is executed. return "Generator finished."; // When a reject function is called in one of Promise objects, // co.error() is executed. // 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); }); // Functions using co generator can be defined by using co.wrap. // They are also yieldable because they also return a Promise object. var wrappedFunction = co.wrap(function* () { console.log('--- co.wrap start ---'); var response = yield [ thunkifiedFunction('co.wrap two', 800), thunkifiedFunction('co.wrap one', 600), ]; console.log("co.wrap response: " + JSON.stringify(response)); yield thunkifiedFunction('co.wrap three', 200); yield thunkifiedFunction('co.wrap four', 400); console.log('--- co.wrap end ---'); return yield Promise.resolve(null); });
$ node co_generator.js --- co start --- co one co two response: ["co two","co one"] co three co four --- co.wrap start --- co.wrap one co.wrap two co.wrap response: ["co.wrap two","co.wrap one"] co.wrap three co.wrap four --- co.wrap end --- --- co end --- --- then start --- Generator finished.
Callback地獄対策の2つ目はcoについてまとめました。
coはGeneratorの仕組みを利用して簡単に並列・直列処理フローを記述できるようにするライブラリです。
const co = require('co'); const thunkify = require('thunkify') // callbackを引数にとる一般的な関数 var callbackFunction = function(message, timeout, callback) { setTimeout(function() { console.log(message); callback(null, message); }, timeout); }; // thunkifyはcallbackを引数にとる関数をthunkを返却する関数に変換する // thunkにはgenerator内でyeild式を適用できる(yeildable) var thunkifiedFunction = thunkify(callbackFunction); // Promiseを返却する一般的な関数 var promiseFunction = function(message, timeout) { return new Promise(function(resolve, reject){ setTimeout(function() { console.log(message); resolve(message); }, timeout); }); }; // co関数にGenerator(function*(){...})を渡すと、 // co関数はGeneratorの処理をyeild式まで進め、 // yeild式に指定されたPromiseの完了を待ってから処理を再開させる co(function*() { console.log('--- co start ---'); // 2つの関数を並列処理する // 並列処理をするにはyeildにArrayもしくはObjectを指定する var response = yield [ thunkifiedFunction('co two', 800), promiseFunction('co one', 600), ]; console.log("response: " + JSON.stringify(response)); // 2つの関数を直列処理する yield thunkifiedFunction('co three', 200); yield promiseFunction('co four', 400); // co.wrapで定義した関数(後述)はco generator内で利用できる yield wrappedFunction(); console.log('--- co end ---'); // Generatorでreturnするとco.then()に指定した関数が実行される return "Generator finished."; // いずれかのPromiseでreject関数が呼ばれると // co.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); }); // co.wrapを使うことでco generatorを利用した関数を定義できる // この関数もPromiseを返却するのでyeildableとなる var wrappedFunction = co.wrap(function* () { console.log('--- co.wrap start ---'); var response = yield [ thunkifiedFunction('co.wrap two', 800), thunkifiedFunction('co.wrap one', 600), ]; console.log("co.wrap response: " + JSON.stringify(response)); yield thunkifiedFunction('co.wrap three', 200); yield thunkifiedFunction('co.wrap four', 400); console.log('--- co.wrap end ---'); return yield Promise.resolve(null); });
実行結果
$ node co_generator.js --- co start --- co one co two response: ["co two","co one"] co three co four --- co.wrap start --- co.wrap one co.wrap two co.wrap response: ["co.wrap two","co.wrap one"] co.wrap three co.wrap four --- co.wrap end --- --- co end --- --- then start --- Generator finished.