投稿

9月, 2017の投稿を表示しています

[Java] IPアドレスが `169.254.xx.yy`になってしまう

Javaプログラムが動いているPCで、そのPCのIPアドレスを取得したい。 InetAddress.getLocalHost() で取得した InetAddress の getHostAddress() メソッドから返ってくるIPアドレスが 169.254.xx.yy (プライベートIPアドレス) になってしまう。 おそらく環境によっては結果は違う (もしかするとWindowsなら意図する動作するかも) と思う。 InetAddress.getLocalHost() は複数NICのことは考えてないのかもしれない。いまどきは仮想NICみたいなのがあるのが普通の気がするので、これでは困る。 ということで、とりあえず以下のようなテストプログラムを作成してみた。 package test; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Enumeration; public class TestGetAddress { public static void main (String[] args) { TestGetAddress test = new TestGetAddress(); test.getLocalAddress(); test.getInterfaces(); } public void getInterfaces () { try { Enumeration<NetworkInterface> list = NetworkInterface.getNetworkInterfaces(); if (list == null ) { return ; } while (list.hasMoreElemen

[Jersey] CORS対応

Jersey2でREST APIを提供し、フロントエンドはNode.js (Koa) という構成のシステムを開発している。 APIはTomcat, フロントエンドはNode.jsなのでブラウザからは別ドメインと判定されてしまうので、クロスドメイン対応 (以降CORS対応) が必要。 今までは Apache を噛ませてヘッダーに Access-Control-Allow-ほにゃらら を無理やりくっつけていたんだけど、Apacheなしでも動作確認できるようにJerseyのFilterを作成した。 定型パターンだと思うので、コードを残しておく。 package jp.tmt_mc.smu_plus.api.filter; import java.io.IOException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.core.MultivaluedMap; /** * CORS対応フィルター * * @author kimurakazunori * */ public class CorsFilter implements ContainerResponseFilter { @Override public void filter (ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { MultivaluedMap<String, Object> headers = responseContext.getHeaders(); // すべてのクライアントからの要求を許可する headers.add( "Access-Cont

Classpath entry org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER is marked for publish/export but is not exported on the project classpath

Jerseyのプロジェクトで、別プロジェクトにModelクラスなどを配置している。 デプロイメント・アセンブリーでModelプロジェクトを参照するように設定しているんだけど、 以下のような警告が表示されていた。 Classpath entry org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER is marked for publish/export but is not exported on the project classpath. Classpath visibility within Eclipse and at runtime will differ. とりあえずデバッグ実行しても問題なく動いているんだけど、キモチワルイので除去するために調査。 結論からいうと、下記「参考」リンクの 1 や 2 の対応でOKだった。 該当プロジェクトのプロパティを表示 「Java のビルド・パス」 -> 「順序およびエクスポート」 「Maven 依存関係」にチェック 「OK」をクリック つまり、Mavenでインストールしたモジュールが他プロジェクトから見えねーよ!って警告だったんですね。 参考 Why the “MAVEN2_CLASSPATH_CONTAINER will not be exported or published” | Geert Schuring java ee - Eclipse build path warning - Stack Overflow JavaEE 7をやってみよう。 Webデプロイメントアセンブリー - ひこぽんのーと “クラスパス・エントリーはエクスポートまたは公開されません”警告を解消する - R42日記

[eclipse] "Java コンパイラー・レベルが、インストールされている Java プロジェクト・ファセットのバージョンと一致しません" という警告を解消する

JerseyのプロジェクトでModelクラス群を別プロジェクトに切り出して開発してる。 で、「デプロイメント・アセンブリー」でModelクラス群のあるプロジェクトを参照するように設定してるんだけど、そうすると以下のような警告が表示された。 Java コンパイラー・レベルが、インストールされている Java プロジェクト・ファセットのバージョンと一致しません Javaプロジェクト・ファセットなんて設定した覚えないんですけど?って感じだが、警告はキモチワルイので除去しよう。 で、Modelプロジェクトのプロパティに「プロジェクト・ファセット」という項目がある。 確かに「Java」の項目のバージョンが 1.6 になっていたので 1.8 に変更。 それだけで警告が除去できた。 参考 エンジニアの暇潰し : EclipseでJava プロジェクト・ファセットのエラーが出る http://blog.livedoor.jp/crimson373/archives/2924766.html

[node.js] CP932のテキストを読み込む

Windowsで作成したテキストファイル (文字コードが CP932) をNode.jsで読み込むときに、どのモジュールを使うか毎回検索するのでメモ。 node-iconv より iconv-lite の方が早いらしい。 ついでに promisify と async / await のサンプルとしてテストコードを作成してみた。 const fs = require ( "fs" ); const util = require ( "util" ); const iconv = require ( "iconv-lite" ); // 対象ファイル const filePath = `./test.txt`; // readFileをpromiseを返すように変換 const readFileAsync = util.promisify(fs.readFile); async function main () { try { // テキストファイルを読み込む const buf = await readFileAsync(filePath); // CP932->UTF8に変換 const text = iconv.decode(buf, "CP932" ); console.log(text); } catch (err) { console.log( "ERROR:" , err); } } main(); 参考 iconv-lite node.jsのfsでShift-jisのテキストを文字化けせず読み込む(iconv-lite) | TPB util.promisify()でcallbackスタイルの関数をpromise化 - Qiita Node.js 8: util.promisify()

[Java] SingletonなクラスでExceptionInInitializerError

Databaseから正常に応答が返ってくるかを定期的にチェックし、結果をRedisの特定キーに保持するプログラムを書いたんだが、Databaseが停止しているとConnectionを取得する際に ExceptionInInitializerError が出てしまう。 catch (Exception e) としていても捕まえられなかったので、ちょっと調べた。 そもそも ExceptionInInitializerError って? ExceptionInInitializerErrorとは : JavaA2Z static初期化子内で例外が投げられた場合に投げられる。Errorクラスのサブクラスのため厳密には例外ではない。 なるほど。 今回、Connection取得処理をSingletonなクラスに集約したんだけど、そのSingletonクラスの初期化時に当該エラーが出ている模様。 Exceptionでcatchできなかったのは Errorクラスのサブクラス だからか。 今回の対応 以下のようにすると catch できた。 private void hoge () { try { // Singletonなクラスの使用 MySingleton.getInstance().execute(); } catch (Exception | ExceptionInInitializerError e) { logger.error( "エラーだよ" , e); } } 参考: SingletonとExceptionについて考えてたら、なんだか良く分からなくなってしまいました。 - テツ日記

[Jedis] ZRANGE WITHSCORES

RedisのZSETに受信データを蓄積していくプログラムを書いた。 ZSETのScoreに受信日時(1970/01/01からのミリ秒)をセットしていて、日付を指定して受信データを抜き出せる設計にした。 で、テストするときに「最も過去のデータがいつ受信したのか知りたいなー」と思って調査。 Redisだと以下の方法で memberとscore を取得できる。 > ZRANGE key 0 0 WITHSCORES 日本語ドキュメントだと 値だけではなくて要素のスコアを返せるように WITHSCORES オプションを与えることもできます。Redisはデータをvalue1,score1,value2,score2,…,valueN,scoreNというリストの形で返します。しかしクライアントライブラリはデータをより適切な形で返すことも可能です。(このコマンドで一番良い形なのは2要素のタプルの配列だと思います) ってあって、「Javaにタプルねーしなー、どうすっべかなー」と思ってたら redis.clients.jedis.Tuple ってクラスがあった。 Jedisだと以下のように実装できる。 Set<Tuple> result = jedis.zrangeWithScores(key, 0 , 0 ); for (Tuple item : result) { return item.getScore(); } ふむ。簡単。 別に汎用的に使えるタプルのクラス、って訳ではなく、あくまでRedisのscoreとmemberを一緒に返す時に使うクラスってだけなので、 Tuple って名称は微妙だな。 参考 ソート済みセット型 — redis 2.0.3 documentation Java Code Example redis.clients.jedis.Tuple

[Jedis] Subscribe時にClassCastException

JavaのRedisクライアントであるJedisを使って、Redis Pub/SubのSubscribeするクライアントを作ってたんだけど動作確認してみると ClassCastException - [B cannot be cast to java.util.List という例外が発生する。 原因 作成したプログラムではdaemonとして稼働するんだけど、中では2つのスレッドが動いていて きちんとdaemonが正常稼働していることをRedisの特定キーに書き込むスレッド チャンネルをSubscribeしてRedisからデータを受け取るスレッド 各スレッドはJedisが提供するJedisPoolを使ってRedisのコネクションを取得していたんだけど、Subscribeするコネクションが1.で使用される (あるいは逆の) 状況が発生していたんじゃないかと推測。 解決方法 Subscribeするスレッドは JedisPool からではなく、普通に new Jedis(hostname); するように修正したところ、再現しなくなった。

[Redis] パターンに一致するキーを一括削除

パターンを指定して一括削除をしたい場合 redis-cli は引数にRedisコマンドを受ける事ができるので、それを活用する。 > redis- cli KEYS "prefix*" | xargs redis- cli DEL ShellScriptでRedisの操作を行いたい場合にも使えそう。 参考 Redisのパターンに一致するキーを削除 - Qiita

dockerコンテナの再開・停止

以前作成した PostgreSQL のコンテナを再開しようとした際に、コマンドが分からなかったので確認。 作成済みのコンテナ一覧を表示する場合は ps -a > docker ps -a 停止中のコンテナを再開するのは start run 時に指定していたオプション等は保持しているようで、ポートフォワードの設定なんかも復元された。 > docker start postgres また停止するときは stop > docker stop postgres 参考 docker コマンド チートシート - Qiita PostgreSQLのDockerイメージの使い方 - SIerだけど技術やりたいブログ

2017-09-15 日報

コーディング作業が一段落したのでドキュメント作成を進める。 先日下書きしてたので半日で書きあがった。 あとはテストだが、データ準備とか環境整備とか面倒くさい… 今日調べたこと [Webデザイン] iPhoneXの画面について iPhone X の Safari における Web コンテンツの表示 – ONO TAKEHIKO – Medium iPhoneXのディスプレイ上部に出っぱった部分があったり、上部・下部はシステム領域的な扱いになっているのにも関わらず、Safari (というかViewport) の設定でシステム領域的な箇所にまで表示領域を広げる事が可能になっている。 システム領域的な箇所のタッチイベントは iOS がキャッチしてしまいブラウザ側には届かないので、操作できない箇所が生じてしまう、という問題。 CSSでシステム領域的な箇所のサイズが取得できるから padding なり margin なりを設定しろ、という事みたいだけど、そのプロパティをSafari以外が解釈できなかったら意味なくね?という話。 iPhoneXでのAutoLayoutをきれいに書くための試行錯誤 - Qiita iPhoneXが出てきたらディスプレイ解像度のパターンも増えるのでAutoLayoutきちんと実装しなきゃね、という内容。 [PWA] pwa_study アウトラインメモ | Web Scratch PWA難しいなー Android/iOSでアプリの配布や前述のディスプレイ解像度なんかの問題があるから、Webアプリの方が展開・運用・保守が楽だと思う。 Webアプリ化の問題点はオフライン状態で使用できない事だけど、PWAにすればその課題も解消できるはず。 …なんだけど、僕の知識不足で記事が理解しきれない。なんとか時間を作ってHelloWorld的なものを作ってみたいなー。

2017-09-14 日報

Twitterの埋め込みテストも兼ねて… GTDの簡易版をチームで回す、って感じ。これWebサービス化すればいいんじゃない? / “プロジェクトの残業を50%削減したタスク管理手法を惜しみなく公開する - Qiita” https://t.co/Vwzf7bmUlY — きむら (@KazunoriJs) 2017年9月14日 今日調べたこと [Jersey] 単純なHashMapを返すAPI わざわざ Pojo を作るまでもない、単純なデータ形式を返したかった。 以下を参考に実装。 java - HashMap to JSON response in Jersey 2 - Stack Overflow

2017-09-13 日報

昨日投稿できなかったので2日分をまとめて投稿。 今日調べたこと [Java] Map -> List 変換 Map<Object, T>#values() を取得して List<T> にしたかった。 ArrayList のコンストラクタにあるのね。一発でした。 List<T> list = new ArrayList<T>(map.values()); 【Java実践】Map→List、List→Map変換方法まとめ | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト [Java] Java で LeftPad / RightPad Commons Lang の StringUtils にあるけど、わざわざ Commons Lang を導入するほどでもないので自作。 実際には RightPad しか必要なかったんだけど、どうせなので LeftPad も実装しておいた。 public class StringUtility { /** * 方向 */ public enum Direction { Left, Right } /** * 文字列が空か判定します * * @param str * @return */ public static boolean isEmpty (String str) { if (str == null ) { return true ; } if ( "" .equals(str)) { return true ; } return false ; } /** * 対象文字列が指定された桁数になるまで左側に文字列を追加します * * @param source 対象文字列 * @param length

2017-09-12 日報

現行システムのRedis対応を進めていて、他人が書いた画面のLogicクラスなんかを見てるんだけど、コレ何がやりたいの?とか、明らかに別Logicクラスからコピペしてきたメソッドをちょろっと修正してるんだけど、コメントはそのままなので処理内容とコメントが合っていないとか、1つのメソッドにダラダラと200〜300行くらい処理を書いていて、やってる内容はあるPojoクラスから別のPojoクラスにデータの中身をコピーしてる (つまり entity1.setProp(entity2.getProp()) がメソッド内の半分くらいある) とかを見ていて、ちょっとコメント書けばわかりやすくなるのに、priveteメソッドに分割すればスッキリするのに、とかいうのがいっぱいでストレス溜まる。 リファクタリングする際にペアプログラミングすればスキルアップになりそうだけど、別に僕の同僚でもなんでもないのでコッチで直してしまう。 今日調べたこと Jersey と Apache Tomcat を使って RESTful な Web サービスを作成する POST (create) した時のResponseに採番したIDをセットしたいなぁ、みたいな。 model#create(Object entity) すると採番した id が返ってくるとして… int id = model.create(entity); URI uri = uriInfo.getAbsolutePathBuilder().path(id).build(); return Response.created(uri).build(); みたいな感じ。定型パターンだな。 IBM Knowledge Center - UriInfo オブジェクトを使用した URI に関する情報の取得

2017-09-08 日報

デブサミ関西に行くつもりだったけどプロジェクトの進捗が芳しくないので作業。 他人に振ったタスクが思ったより重たかったので、一部巻取り。 今日調べたこと [Jersey] 単純なGETのAPIでエラーコードを返す 他人が作ったAPIを見てて、Exceptionを捨てて空のEntityを返している箇所が多数あったので、適切にエラー処理をするよう修正。 WebApplicationException をthrowして、メッセージに Exception の内容をセットした。 JSON・XMLを返すけどエラー時はステータスコードやメッセージを選びたい - edgegram [Redis] Pub/Subの説明 Redisを知らない人向けにPub/Subとはなんぞや、という説明が必要になった。 チャットアプリの例が直感的かな。 3分でRedisのpub/subを使ってみる【redis】 - DRYな備忘録 [Eclipse] プロジェクトごとにインデント設定を変える 同じシステムの異なるプロジェクトにおいて、インデントの文字がタブだったりスペースだったり。 案件の初期に統一しなかった僕が悪いので、プロジェクトごとにエディタ設定を変えるようにした。 Eclipseではプロジェクトのプロパティから Java コード・スタイル -> フォーマッター を プロジェクト固有の設定を可能にする とすれば設定可能。 Eclipse のエディタでタブ幅を指定する / タブ文字ではなく空白を利用する方法

2017-09-06 日報

電磁パルス攻撃とかされたら仕事できんなー、と思った。 ほとんどの職種で影響甚大なんだろうけど、プログラマーだと顕著だ。PCが壊れると何も出来ない。 サラリーマンだったら電磁パルスの影響中も給料出るのかな? だとしたら、フリーランスは戦争になると収入が無くなるのでサラリーマンに比べてリスクが高いと言える。 今日調べたこと スネークケースをキャメルケースに変換 テーブル定義書からコードを生成するのに、スネークケースからキャメルケースに変換したい事がある。 たいしたコードじゃないけど、毎回実装している気がするのでメモ。 function toLowerCamelCase (str) { return str.replace( /_./g , (s) => { return s.charAt( 1 ).toUpperCase(); }); } function toUpperCamelCase (str) { // 1文字目を大文字にする let val = str.substring( 0 , 1 ).toUpperCase() + str.substring( 1 ); return val.replace( /_./g , (s) => { return s.charAt( 1 ).toUpperCase(); }); } javascriptでキャメルケースとスネークケースの相互変換 - Qiita

2017-09-05 日報

めっちゃコード書いてた。 今日調べたこと [Redis] pipelining と transaction の違い stack overflowに超分かりやすい回答があった。 パイプライン処理は、主にネットワークの最適化です。これは基本的に、クライアントが一連のコマンドをバッファリングし、それらを一度にサーバーに送ることを意味します。これらのコマンドは、トランザクション内で実行される保証はありません。ここでの利点は、すべてのコマンドのネットワークラウンドトリップ時間を節約することです。 Redisはシングルスレッドなので、個々のコマンドは常にアトミックですが、異なるクライアントからの2つのコマンドは、例えば、それらの間で交互に実行できます。 しかし、Multi / execは、他のクライアントがmulti / execシーケンスのコマンド間でコマンドを実行していないことを保証します。 pipelining vs transaction in redis - Stack Overflow [Redis] Jedisでの Pipelineの使い方 AdvancedUsage · xetorthio/jedis Wiki 場合によっては、さまざまなコマンドを送信する必要があります。素朴なやり方よりも優れたパフォーマンスを発揮する、非常にクールな方法は、パイプライニングを使用することです。こうすることで、応答を待たずにコマンドを送信することができ、実際には最後に応答を読むことができます。 Pipeline p = jedis.pipelined(); p.set( "fool" , "bar" ); p.zadd( "foo" , 1 , "barowitch" ); p.zadd( "foo" , 0 , "barinsky" ); p.zadd( "foo" , 0 , "barikoviev" ); Response<String> pipeString = p.get( "fool" );

2017-09-04 日報

文章を推敲していると余計な時間を食ってしまうので、思いついたことを書き連ねることにした。 ITエンジニアの評価などについて。 食べログみたいにお客さんに「この人と仕事してよかった!」みたいな評価をしてもらい、それを職務経歴書と一緒に公開することでエンジニア能力を客観的に表すことはできないだろうか。 ランサーズとかクラウドワークスではそういう仕組みがあるのかな? 今日調べたこと [Java] 未実装であることを表現する方法 非推奨メソッドとする場合は @Deprecated を付ける。 その操作をサポート (実装) していないというときは UnsupportedOperationException をスローする。 Javaクラス使用メモ(Hishidama’s Java Class use Memo) Java例外の投げ方メモ(Hishidama’s Java throw Memo) [Redis] ZSETでスコアを指定して要素を削除 ZREMRANGEBYSCORE で min と max に同じ値をセットする。 ソート済みセット型 — redis 2.0.3 documentation ZREMRANGEBYSCORE Redis [Redis] LISTのpush/pop 単純なキューを実装するときに右を最新とするのか、左を最新とするのか、どちらが直感的かを考えだしたら分けわかんなくなってきた。 今回は rpush, lpop (右に追加して左から取り出す) にした。 んー、反対な気がするなw 僕は左利きなので、こういう時に他人と反対になっちゃう。 リスト型 — redis 2.0.3 documentation [Redis] Pub/Subしたときに受信したかどうか RedisのPub/Subにおいて、Publishする方で、クライアントがデータを受信できたかどうかを判定する方法。 悩むまでもなく、PUBLISHコマンドの戻り値が受信したクライアントの件数だった。 万が一、Subscribeしてるプロセスが死んでいた場合にデータが時空の狭間に消えていくと困る気がするので、PUBLISHの戻り値が 0 なら LIST に保持することにした。

2017-09-01 日報

他者の作業がボトルネックになって自分の作業が進められない。 影響がなさそうなプログラムから先に実装を進めていくことに。 やっぱりチャットツールがある方が仕事やりやすいなぁ。 事前の登録なんかが容易で チャンネルとかの参加とか退出が手軽で メンションが容易に飛ばせて Botなんかが楽に導入できる って感じのチャットツールないかしら。 今日調べたこと Jersey Clientの使い方 » Jersey Client API : Java でWeb API Client を作成する方法 TECHSCORE BLOG Web API の死活監視がしたいだけだったので、レスポンスをStringで受けることにした。 HTTP Status Codeをチェックしていないので微妙だけど、とりあえず要件は満たしているのでOK。 Propertiesで取得した値の走査 java.util.Properties は Mapインターフェースを実装してるから拡張for文で全要素を走査できるのね。 public class Config { public void function () { Properties prop = new Properties(); InputStream stream = Config.class.getClassLoader().getResourceAsStream( "config.properties" ); try { prop.load(stream); stream.close(); for (Entry<Object, Object> entry : prop.entrySet()) { // なんかの処理 } } catch (IOException e) { e.printStackTrace(); } } } Java Propertiesで習得したプロパティファイルの内容をMapに詰め込み表示する - Code Log Properties (Java Platform SE 8 )