狛ログ

2018年6月13日水曜日

SpringBoot 1.3 から 1.5 へのバージョンアップでハマったこと

6月 13, 2018

オフィス狛 技術部 CTOの Taka-yamです。

あるJavaのプロジェクトでSpring Frameworkの脆弱性問題により
SpringBoot1.31から1.51へアップデートする必要がありました。

その際に、やはり思った通りにはいかず、いくつかハマった点がありましたので、
ここで情報共有します。

まず最初のエラーです。
ServletContext resource [/hoge] defined by 'spring.datasource.schema' does not exist

このエラーは「datasource.schemaが存在しない」と出ています。
どうやら Spring Boot1.5 から、デフォルトでDBの初期化処理を行おうとし、schema.sqlやdata.sqlというファイルをクラスパスのルートから探しに行くようです。
今ままではこのような処理を行っていなかったため、当然ファイルは存在せずエラーとなっていました。

対策としては、下記のプロパティをapplication.ymlに追加します。
spring:datasource:initialize: false

次は下記のエラーが出ました。
java.lang.ClassNotFoundException: org.springframework.session.hazelcast.HazelcastFlushMode

これはspring-sessionのバージョンを間違えており、2系のバージョンを指定していたため、
SpringBoot1.51では依存関係が解決できないことが原因でした。
バージョンを変更し、無事に解決できました。

最後に下記のエラーが出ました。
No Spring Session store is configured: set the 'spring.session.store-type'

これもSpringBoot1.5からの特徴でspring.session.store-typeを指定しないとエラーになるように変わりました。
今回は何も使用していないため、何も指定しないように設定します。
spring:session:store-type: none

以上でエラーが解決され、無事に動作も確認ができました。
計画的ではなく、突発的なアップデートの際には色々と調査が必要ですね。

2018年6月10日日曜日

knexライブラリで動的パラメータを使ったlike検索をする方法

6月 10, 2018

オフィス狛 技術部 CTOの Taka-yamです。
Node.js のアプリケーションを開発していて、
SQLを構築するためにknexというライブラリを活用しています。
http://knexjs.org

素のSQLに近い形でfluentにSQLを構築できるので大変便利なのですが、
動的パラメータでlike検索を行うとした際に値の設定方法ではまったので共有します。

下記のようなユーザテーブルがあるとします。
User
id: String
name: String

textという変数に入力された値が格納されているとして
ユーザテーブルのnameカラムにあいまい検索を行うとします。

まず最初に思いついたのが、
knex(‘user’).whereRaw(“name like ‘%?%’”, text);

これはエラーとなります。
type \"like\" does not exist"

次に思いついたのが、
knex(‘user’).where('name', 'like', knex.raw('%?%', text));

これもエラーになります。
syntax error at or near \"%\""

次に思いついたのが、
knex(‘user’).whereRaw(‘name like %' + text + '%');

これもエラーになります。
syntax error at or near \"%\""

次に思いついたのが、
knex(‘user’).whereRaw("name like '%" + text + "%'");

これはうまくいきました。

ですが、このような文字列連結をすると弊社で使用している Lint に怒られてgit commitさえ出来ません。(lint-stagedでcommit制限掛けているので)

なので、最終的に、
knex(‘user’).where(‘name’, 'like', `%${text}%`);

となりました。

結論を見ればすごい単純なことなのですが、
結構はまったので、もし同じようなことで困っている人の助けになれば幸いです。

PostgreSQLで「あればUPDATE、なければINSERT」のUPSERTをやってみる

6月 10, 2018

オフィス狛 技術部のHammarです。

よくデータベースを操作する処理で、あるキーでデータがあればUPDATE、なければINSERTするーというような場面が多々あると思います。
通常はまずはそのキーで件数をSELECTして、件数が0件ならINSERT処理へ、0件以上ならUPDATE処理へ分岐させるというような感じの処理の流れが、まあよくある感じかなと思います。

じつはこれを1回のクエリで行うことができるのですが、PostgresqlやMysql等でやり方がそれぞれ違います。
今回はPostgresqlでのやり方で、自分が少しハマった部分や注意点も含めて書こうと思います。

■UPSERT

「データがあればUPDATE、なければINSERTする」という処理はUPSERTと呼ばれています。INSERT(追加)とUPDATE(更新)の両方の機能を併せ持っていることから、UPDATE + INSERTで、UPSERTということのようです。

PostgresqlはバージョンによってこのUPSERTのやり方が変わってきます。
Postgresql 9.5以上でCONFLICTというUPSERTができる機能が備わりましたが、それより前のバージョンではこの機能が使えないので、CTE(共通テーブル式)という構文を利用して下記のようなクエリでUPSERT的なことが可能です。
(ちなみにCTEとはこちらに詳しく書かれています)

■CTEを使ったUPSERT的なクエリ

  WITH upsert AS (
        UPDATE test_table
        SET
            name = val_name
        WHERE
            id = val_id
        RETURNING val_id
    )
    INSERT INTO test_table (val_id, val_name)
    SELECT val_id, val_name From test_table
    WHERE not exists (SELECT id FROM upsert);

上記のクエリでUPSERT的な動きとなり、自分もこの方法で処理を書いていたのですが、この方法で1つハマったことが起きました。
通常テーブルにレコードが何件かある状態で上記のクエリは問題ないのですが、テーブルにレコードが1件もない(初期状態)の場合、「なければINSERT」となるので本来ならレコードが登録されるはずなのですが、なぜか上記のクエリではレコードが登録されず、テーブルは空のままでした。
原因は不明なのですが、恐らくSELECT句でNULL判定できずに登録するものがないと判断されるようです。(ただ、試しにNOT NULLでやってもうまくいきませんでした)
ということで上記の方法は厳密には使えないことがわかったので、どうしようかとちょっと悩みましたが自分の開発環境がPostgresql 9.5以上であることがわかり、ならばあたらしく備わったCONFLICTという機能を使ってみようということで、下記のようなクエリを作成します。

■CONFLICT機能を利用したクエリ

    INSERT INTO test_table (id, name)
    VALUES (val_id, val_name)
    ON CONFLICT (id)
    DO UPDATE SET name = val_name;

短くていいですね!
ON CONFLICTにキーを指定して存在確認し、レコードがあればUPDATE、なければINSERTというようになっています。ただこのクエリにも1つ注意点があり、ON CONFLICTに指定する項目はUNIQUE制約がある項目でないとこのクエリはエラーとなってしまいます。なので、テーブルの指定の項目にUNIQUE制約をつけて使うようにしてください(複数項目でUNIQUEとなる場合は複合UNIQUE制約をつける)

CTEを使ったクエリでも本来ならうまくできると思うんですが、自分の環境が悪いのかそもそもの問題なのかは今のところわかっていません。ただCONFLICT機能のほうがクエリ的にもすっきりですし、かなり使えると思うのでPostgresql 9.5以上の環境があればこちらを使ったほうがいいと思います。


2018年5月31日木曜日

InVisionStudioを使ってアニメーションするモックアップを作成してみた。

5月 31, 2018

こんにちは、オフィス狛デザイン部のSatoです。
時代の波に追いつきたいと思い、一時期話題になったあのプロトタイプソフトの記事を書いてみました。(ちょっと遅いか)

先月InVision Studioのearly accessのメールが届いたのですが、SketchもXDも使った事の無い私は、通常の操作もあまりうまくできずに使うのを後回しにしていたのですが、公式の動画を見たり公式のGETTING STARTEDを見たりして、やっとアニメーションをつけたりする所までできるようになりました。


作ったモックアップ(iphoneXサイズ)
気になる部分はありますが!(なぜか色を変えたら一部のオブジェクトがプレビュー時だけ消えてしまった…?バグでしょうか?)InVision Studioで作った動いてるモックアップです!
InVision StudioだとInVisionでお馴染みのリンクでの画面の遷移の再現や固定ヘッダーの再現だけでなくぬるぬるパーツが動きます!言葉で説明するのが難しい動きもこれでエンジニアさんに伝えられますね!


一番手こずったのがアニメーション機能で作る横から出てくるメニューだったので個人的に作り方を解説します。
(UIを載せるとよろしく無いそうなので、詳しいアニメーション機能についてはこちらの公式の説明を読んでみてください!)

横から入ってくるメニューは最初アニメーションのTransitionをPresetに設定し横にずれるような動きに設定してどうにかしようと思ったのですが、なかなかメニューが横から動くようには見えてくれませんでした……。

しかし、元の画面要素をコンポーネントとして登録し、別にコンポーネント化させたメニューを見切れるように配置し、TransitionをMotionにしてあげるといい感じに動いてくれました。

応用すれば色々な表現が可能になりますね!

唯一、使っていて大きな欠点だなと思った点は日本語対応。
InVision Studio内は日本語もきちんと打ち込めますが、右上のプレビューボタンの横のアップロードボタンでInVisionにプロトタイプとしてアップロードできるという機能を使った後にプレビューで見てみると日本語部分が綺麗に消えてしまいました。
InVisionのソフトなのに日本語を使うとInVisionにうまい具合にアップできないのは痛い……。
こんなに素敵なのにクライアントさんにモックアップとして見せるのはまだ無理そうなのが勿体無い気がしますが、early accessだし海外製だから仕方ない。

他にも不具合な気がする不思議な挙動や実装されていない機能などありますが使う価値は大いにあると思います。
何よりearly access版は今の所(2018年5月現在)無料です!ぜひみなさま使ってみてください。

2018年5月13日日曜日

クラウドサービスの種類について。(新人さん向け)

5月 13, 2018

オフィス狛 技術部のHammarです。

この度、4月からオフィス狛へ参画しました。
役割的にはマネージャー兼プログラマー(何でも屋?)です。
これから、よろしくお願いします。
さて、参画後初のブログ記事ということで、4月入社の新人さんへ、IT用語の説明を記載しようと思います。
今回は『クラウド』についてです。

最近は多種多様なクラウドサービスが本当に多くなってきました。Amazon、Microsoft、Google、といったいわゆるクラウドBIG3を筆頭に中小さまざまなクラウドサービスが存在しています。
一概にクラウドサービスを利用するといっても、実はクラウドの利用形態によっていくつか分類されるのをご存知でしょうか。またその利用形態ごとのどういう機能を利用するかによってどのクラウドサービスを選ぶかの基準にもなってきます。
クラウドを利用した開発をするにあたって、そのクラウドサービスの種類についてちょっと勉強したことをまとめてみたいと思います。

そもそもクラウドとは

クラウドコンピューティング(英: cloud computing)は、インターネットなどのコンピュータネットワークを経由して、コンピュータ資源をサービスの形で提供する利用形態である。略してクラウドと呼ばれることも多い。 wikipedia

もう少しざっくり書くと、ユーザーはサーバーやストレージなどのインフラやソフトウエアなど物理的に持つ必要がなく、インターネット等を利用していつでも手軽にサービスを利用できる技術です。
上記の意味合いでは身近にあるGoogleのGmailはメールに特化したクラウドサービスです。

このクラウドサービスの種類についてですが、クラウドサービスには実は細かくわけると「SaaS」、「PaaS」、「IaaS」という種類があります(もう少し細かく「DaaS」というのもあります)

■SaaSについて

「Software as a Service」の略で「サース」と呼びます。
その名の通りソフトウェアをクラウドで利用できるサービスになります。
上記に書いたメールサービスなどがこれにあたります。
ほかにもDropbox等のクラウドストレージサービスやMicrosoft Office 365などのオフィスソフトも代表例になります。SaaSはすでにアプリケーションとしてすぐに利用できる状態で、エンドユーザーが一番身近に使うサービスが多いのではないかと思います。

■PaaSについて

「Platform as a Service」の略で、「パース」と呼ばれています。
プラットフォームのクラウドサービスということで、プラットフォーム「土台となる環境」をクラウド上で利用できるサービスになります。
開発者はシステムの開発に必要な土台となる環境(アプリケーションとOSをつなぐミドルウェアやDB管理システム、プログラミング言語、OS等がすでに利用できる状態でアプリケーションを開発できるので、いちいち開発環境を整える必要がなく、すぐに開発に取り掛かることができます。
代表例としてはGoogle App Engine やMicrosoft Azureあたりになります。AWSもサービスの内容によってはPaaSになりますね。

■IaaSについて

「Infrastructure as a Service」の略で、「イアース」や「アイアース」と呼ばれます。
インフラストラクチャ―のクラウドサービスなので、サーバーやストレージ、ネットワークをクラウド上で利用できるサービスになります。
サーバを利用する際に必要なハードウェアのスペックやOSを、ユーザーが自分で選んで利用することが可能です。PaaSとは違いインフラだけの利用なので、開発者が細かく設定を自由に設計することができます。
代表例としてはGoogle Compute EngineやAWSのEC2がこれにあたります。


これらの「SaaS」、「PaaS」、「IaaS」の種類の違いがわかると、開発時にどのクラウドサービスを使えばよいのかがわかってくると思います。

含まれている機能要素の順に
【SaaS:すぐに使える】>【PaaS:基本的な準備あり】> 【IaaS:インフラだけ】
になるでしょうか。

開発基本に考えた場合、基本的にはPaaSを利用する機会が多いと思いますが、案件内容や状況によってメリット、デメリットをクラウドサービスを考えて選択できるのではないかと思います。


2018年5月11日金曜日

Photoshopのレイヤー名検索したい時に使える機能

5月 11, 2018

こんにちは、オフィス狛 デザイン部のSatoです。

先日、Photoshopでの作業中に、とある言葉の入ったレイヤーだけ抽出したい!という場面がありました。
 イメージ的には下の画像のような状態です。


Photoshopでレイヤー検索ができるかわからなかったので、とりあえず「Command⌘(Ctrl)」+「F」を押下した所、検索画面のようなポップアップが出てきてくれました。
検索したいレイヤー名を入れると、ちゃんとレイヤー名検索ができました!やったー!

ただ、検索結果をクリックするとポップアップが消えてしまうので、キーワードが入ったレイヤー名のレイヤーを色々見比べようとすると少し不便でした。


先日はこの機能だけ使い作業をしていたのですが、調べてみると実はもっとレイヤー名だけ抽出する場合に便利な機能がありました。
「Command⌘(Ctrl)」+「shift(Alt)」+「F」を押下するとレイヤーの上に入力部分が出てきました。ここに検索したい言葉を入れるとその言葉の入ったレイヤー名のみを表示してくれました!

この機能はCS6で実装された機能らしいです。もっと早く知っておきたかった!


補足しますと最初に記載した「Command⌘」+「F」は、レイヤーの検索という面では「Command⌘」+「shift」+「F」に劣りますが、アドビ公式のチュートリアルや情報の検索、adobe stockの画像を検索しワンクリックでライブラリに選択した画像(コピーライト入り)が登録される機能などがあるので、非常に便利です。

また、1つの手でショートカットキーが押せる「Command⌘」+「F」の方が手早く検索できるので、複数件のレイヤーを確認したい場合以外は、この検索機能がおすすめです。

2018年5月10日木曜日

AWS Windowsサーバで Spring Boot の MessageResource の {0} が展開されない場合の解決方法

5月 10, 2018

オフィス狛 技術部 CTOの Taka-yamです。

先日、Spring BootのプログラムをAWSのWindowsサーバにデプロイした際に「あれ?」と思ったことがあったので記載します。

利用したEC2: Microsoft Windows Server 2012 Base - ami-1380926f

Spring Bootではエラーメッセージなどを表示するのみ properties ファイルを利用し、
下記のようにプレースフォルダーを利用しています。

ErrorsCommonInvalid =入力した内容にエラーがあります。
ErrorsCommonRequired ={0}は必ず入力してください。

AWSの無料利用枠を利用していた関係上、Windowsサーバが英語版になっているため、言語や時刻の設定を変更しました。
設定方法はたくさんの良い記事があるので参考リンクを載せて割愛します。
http://blog.serverworks.co.jp/tech/2016/06/20/windows-server-2012-r2-japanese-localization/

設定も完了し、実際に動かしてみても特に問題ないかなと思ったところ、

入力した内容にエラーがあります。// 〇
{0}は必ず入力してください。 // あれ?

という結果に。

元々はオンプレミスのWindowsサーバで動かしており、そっちの環境設定と比べてみても違う箇所が見当たらずしばらく悩むことに、、、

悩んだ結果とうとう見つけたのがこちらでした。

@Bean
ReloadableResourceBundleMessageSource messageSource() {

    Locale.setDefault(Locale.JAPAN); // ←これ!!!!!!!

    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames("classpath:messages/messages");
    messageSource.setCacheSeconds(0);
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
}

Springでメッセージリソースを読み込む際にリソースが変更されたらメッセージも変更される様にしたいので ReloadableResourceBundleMessageSource を使っていたのですが、 ここのロケールが ja_JP になっていないようです。

システムのロケールを変更しても、サーバのデフォルトのロケール設定は変わらなかったのか?
ちょっと根本的な原因はわかっていませんが、解決策としてはロケールはきちんと指定するということでした。

こういう暗黙の設定による罠、気が付かない内に潜り込んでいることがあるので怖いですね。