2017年3月26日日曜日

schoo カスタマイズから学ぶPHP実践

Schooさんの授業を拝見してました。
「カスタマイズから学ぶPHP実践」


メモ

Plugins
  • BuddyPress
  • All in One SEO Pack
  • WooCommerce

laravel Auth
web.php Auth::routes();
--
Ruote::resource(...)
editなどのCRUDのメソッドを生成する

dd()
laravelのヘルパー関数

except()
laravel のセッションのうち、指定したパラメータ以外を取り出す
公式ドキュ

2017年3月11日土曜日

JAWS DAYS 2017 セッション1 「AWSでアプリ開発するなら知っておくべきこと」

初めてのJAWS DAYS参加です。
1発目のセッションは事前申し込みした「管理者に送る処方箋」ではなく、
「AWSでアプリ開発するなら知っておくべきこと」に出ました。


スケーラビリティ
水平・垂直

アーキテクチャのベストプラクティス
Design for failure
Build Security in Every Layer
Leverage Many Storage Options
Implement Elasticity
Think Parallel
Loose Coupling
Don't Fear Constraints

Everything fails, all the time.
by Wanner Vegl???

Design for failure
WebサーバとDBを分ける。
EC2とRDS

次にフェールオーバーや冗長性を考える
冗長構成にするなど。

Build Security in Every Layer
全てのレイヤーでセキュリティを確保

Leverage Many Storage Options
4種類のストレージを使い分けろ
  • S3
  • Glacier
  • EFS
  • EBS
4種類のDBを使い分けろ
  • RDS
  • Redshift
  • DynamoDB
  • ElastiCache

Implement Elasticity
動的な構成を前提とすること

Think Parallel
並列アーキテクチャを試すこと

Loose Coupling
疎結合
コンポーネントの中身を参照しないようにする

コンポーネントを結合した処理の場合、
キューにすることで一から再処理する必要はなくなる。

Asynchronous Integration
本当に即座にレスポンスが必要かを考える。
非同期処理のメリット
・アプリケーションがブロックされない(ユーザ体感の向上) ・よりスケーラブルになる

Don't Fear Constraints
スケールアップの他に、負荷分散やキャッシュも検討できる

The Twelve-Factor App
Herokuのエンジニアが公開したWebアプリ開発の方法論

Codebase
アプリトコードベースは1:1にしろ

Dependencies
特定の環境に依存しないようにする。
アプリと必要なモジュールを同梱してリリースする。

Config
環境によって異なる設定はOSレベルの環境変数によって注入されるべき

Backing Services
?

Build, Release, Run
上記3つのステージを厳密に区分すべき
各リリースに一意のIDを振るべき

Process
プロセス間共有をなくすべき
永続化するデータは外部領域にだす(DBなど)
ファイルやメモリはあくまでキャッシュとして扱い、永続化には用いないこと

Port binding
???

Dev/prod parity
本番環境と開発環境は一致させるべき
CI/CDは環境が同じであることが前提

ステートレスにするためのセッション情報の扱い
セッション情報はec2インスタンスで持たずに、
DynamoDBに外だしなどをする

DevOps
背景は、不確実性とスピード性が加速していること
Culture + Practice + Tool

Build → Test → Release Feadback ← ???

AWSのDocker管理サービス
ECS

自動ロールバック
失敗時の最も早いリカバリ

2017年2月28日火曜日

サムライズさんのJetBrains製品のハンズオンセミナー

サムライズさんのJetBrains製品のハンズオンセミナー


メモ

postfix completion

.var + tab → 変数に入れる

a + b.return + tab

.sout + tab

number &t; 18.if + tab

Emmet
dive.class + tab
script:src + tab

空気読む
山本さんのネーミングがセンスある
Alt + Enter

一つ前のペインに戻る
Control + tab
ファイルだけでなく、ツールウィンドゥを含む

閲覧履歴を開く
Cmd + e

パラメータ一覧を出す
Cmd + p

Shift + Cmd + Enter
Complete Current Statement
今の行の最後を終わらす。
");など

定義箇所にジャンプ
Cmd + b

Shift + f6
rename

リファクタリング
control + t

プロジェクトペインを開く
Cmd + 1

cmd + ↑ 探したい改装で ↓
そこでcmd + nでファイル作成もできる

cmd + n 画面で検索できる。
さらにその次の階層でも検索できる

Option + ↑↓
選択範囲の拡大・縮小

Opt + Cmd + L
コードフォーマット
選択して、範囲を絞ることができる。

PHP / Pythonには標準的なフォーマットがある
らしい。
あとは、Editor.configをプロジェクトルートに置く方法がある

SQLだとわかんない場所
Opt + Enter
Inject Language ...


RenameでAlterが書けてしまうので、
Read-Onlyをつけて置く。

SSHトンネルも掘れるよ。

Cmk + k
コミット
鍵マークを外すことで、diffの場所での変更が有効になる

Edit Json fragment
いい感じにエスケープしてくれる。

RegExpのテスト
1パターンだけはリアルタイムで判定する

2017年2月25日土曜日

Yaml入門 / Dotinstallで学ぶ

Yamlファイルに最近触れるけど、よくわかっていないのでDotinstallさんの動画を閲覧しました。
メモを残しておく。


メモ

Yamlとは
データ書式

公式サイト
YAML Ain't Markup Language

データ型
  • Scalar
  • Sequence
  • Mapping Hash

コメント
#ハッシュ記号です

Null値
~ チルダ

日付
yyyy-mm-dd

真偽値
true / false

Sequence
- (ハイフンとスペース)に続けて書く(=ブロックスタイル)
or
[]にカンマ区切りで書く(=フロースタイル)

ブロックスタイルの字下げ
ハイフンの前にスペースをつける
インデント前の要素は空白にする
- gee@nifty.com
- 
  - hoge
  - fuga
- yooo

Mapping Hash
key: value方式で: (コロンとスペース)で区切り。
こちらもブロックスタイルとフロースタイルが使える

SequenceとMapping Hashは交互に入れ子にできる

区切り文字にタブは使えない
注意

改行の取り扱い
|改行
最終行の改行を保持する。

|+
最後行以降の改行を保持する

|-
最後以降の改行を保持しない。

|を>に変えると、途中行の改行はスペースとなる

&でアンカー
*で呼び出せる(エイリアス)。変数みたいなもの。
- &hoge hogehoge
- *hoge

==
hogehoge
hogehoge
Mapping Hashは<<: *hoge
で呼び出す

--- と ...
データの区切りを示す
開始が---
終わりが...
1つのデータで、...がなくても問題はない。

Spring Batch / 区切り文字の変更

https://spring.io/guides/gs/batch-processing/ Spring Batchの公式サンプル

やってみてつまづいた点2点
・application.propertiesにDB定義しとかないいけない
・デフォルトパッケージだと動かないので、適当なパッケージ入れる必要がある
※パッケージに入れないのはテストやサンプルぐらいだと思いますが。。。

また、読み込むファイルの区切り文字の変更は「DelimitedLineTokenizer」のコンストラクトの引数で、区切りたい文字を渡す。
\tで、タブ区切りにした例です。
    reader.setLineMapper(new DefaultLineMapper() {
        {
           this.setLineTokenizer(new DelimitedLineTokenizer("\t") {
             {
              setNames(new String[] {"firstName", "lastName"});        
             }
           });        
           setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {
             {
              setTargetType(Person.class);        
             }
           });      
        }
    });

2017年2月20日月曜日

Spring Boot / Redirect先にオブジェクトを渡す

Spring Bootをいじってました。


RedirectAttributes attributes
Spring BootのGetting StartedでRedirect先にオブジェクトが渡せなくて1時間くらいハマってました。
結論、「RedirectAttributes attributes」で回避
  @PostMapping("/")
  public String checkPersonInfo(
          @Valid
          @ModelAttribute("personForm")
          PersonForm personForm
          ,BindingResult bindingResult
          ,RedirectAttributes attributes) {

    if (bindingResult.hasErrors() ) {
      return "form";
    }
    attributes.addFlashAttribute("personForm", personForm);
    return "redirect:/results";
  }
こちらを参考にさせていただきました。
Qiita SpringMVCでリダイレクト先ページにパラメータを渡す方法

brに閉じスラッシュをどうしてもつけたくない
意外とかったるいThymeleafのtemplatemodeの制約
LegacyHTML5だと単独タグでも閉じスラッシュが必要になる。
そこでtemplatemodeをLegacyHTML5にしましたが、この時はnekoHTMLというライブラリをimportする必要があるみたいです。
Gradleなら
dependencies {
        ...
 compile('net.sourceforge.nekohtml:nekohtml')
}

spring.thymeleaf.cache=falseを指定したのに、更新されない!どういうこと!?
IntelliJ上でgradle::bootRunしていて、spring.thymeleaf.cache=falseを設定の上、
HTMLファイルを更新してもブラウザで変更が確認できず調べる羽目になった。

結果、ファイル更新した後にbuildしないと内容は変わりません。
IntelliJ依存も疑って、Terminalでgradle bootRunしてみましたが、
これもbuildし直さなきゃHTMLファイルの変更すら反映されませんでした。

javax.validation.constraints.*のvalidation message
@NotNull(message="hoge")
以上!!簡単かつ簡潔
Spring Bootいいね!!

エラーページ
デフォルトなら、templates配下にerror.htmlを作ればよし。
エラーコードによる分岐はまた今度やります。
こちらを参考にさせてもらいました:システム開発メモ Spring Boot + Thymeleafでエラー画面をカスタマイズする

2017年2月19日日曜日

Perlのシジルの覚え方

Perl入学式という勉強会に参加して、覚えやすいシジルの覚え方を教わった


$
ScalorのS

@
ArrayのA

%
/を挟んで対応している=>なんか連想配列っぽい

Android is Dead.: Javaでメモリリークする件

Android is Dead.: Javaでメモリリークする件: Java プログラムでメモリー・リークが発生するのでしょうか? その通りです。 http://www.ibm.com/developerworks/jp/java/library/j-leaks/ メモリはリークするか まとめ 相互参照は問題ない。...



Javaで相互参照でメモリリークするのかどうか、この記事が一番しっくりくる柔らかい説明でした。もう循環参照以外から参照されないその循環参照は、GCの対象になるんですね。リファレンスカウンタ方式と世代別管理。。。まだまだ知らないことばかりです。

Git / githubのusernameを変更したら


Githubのusername変えたら、リモートリポジトリの書き換えが必要だったので、その実施メモ



メモ

git remote -v
今設定しているurlを確認
origin https://github.com/user_name/repository_name


git remote set-url origin https://github.com/new_user_name/repository_name
URLの書き換え

git remote -v
書き換わったことを確認

2017年2月11日土曜日

JVM入門

Schooの授業メモ
Apache Tomcatチューニング入門


メモ

Java/Tomcatアプリのレスポンスのボトルネック
keep-aliveの見直し、DB設計、SQL見直し
インデックスの見直し、Tomcatのメモリ設定

TomcatもJavaプログラム
知らなかったです。
TomcatもJavaプログラムのため、
物理メモリ → JVM → Tomcat → Webアプリ
という関係性のイメージになる

JVMの仮想メモリ
スタック領域 + ヒープ領域

スタック領域
参照型変数のアドレス参照とプリミティブ型変数を格納する

ヒープ領域
オブジェクトのインスタンスを格納する
実行速度に特に影響が出やすいのが、このヒープ領域

さらにEden領域・Survivor領域・Tenured領域に区切られる。
Eden領域 + Survivor領域 = New領域
Tenured領域 = Old領域ともいう。

Survivor領域については、From空間とTo空間
(Survivor0 / Survivor1)にさらに別れる。

Garbage Collectionの動き
インスタンスを生成して最初に格納されるのが、ヒープ領域のうちのEden領域
Eden領域がいっぱいになると、Scavenge GC(Minor GC)が起動する。
参照されていないインスタンスは破棄し、残りは
Survivor領域のTo空間(Survivor1)に移動する

その後のScavenge GCにおいて、参照されているTo空間のインスタンスは、
From空間(Survivor0)に移動する

デフォルトでは、16回マイナーGCを実行されたインスタンスは、
Tenured領域に移動します。
new領域とOld領域が一杯になるとFull GC(Major GC)が実行され、
一時的にアプリが停止します。
以上のように、GCの対象になるかどうかは参照があるかどうかですが、
GCが実行されるタイミングは、メモリ容量によって決まります。

JVMのプロセスを表示
JVMのプロセスを表示
$ jps
3528 Jps
2554 
3403 Bootstrap
2188 

-vをつけると、実行コマンドを確認できる
$ jps -v
3529 Jps -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home 
-Xms8m
2554  -javaagent:../Eclipse/lombok.jar -Dosgi.requiredJavaVersion=1.8 -Xms40m 

JVMプロセスのメモリ使用状況
jstat -gcutil  3403
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
  0.00  68.59  90.99  38.86  96.71  92.41      9    0.121     1    0.059    0.180
FGCがFull GCが発生した回数
FGCが発生していた時間

単発は問題ない(メモリを解放するので悪いことではない)が、
頻発しているとアプリが止まっているので、問題がある
項目の詳細は公式から
  • S0 : Survivor0の使用率
  • S1 : Survivor1の使用率
  • E : Eden領域の使用率
  • O : Old領域の使用率
  • P : Permanent領域(Tenured領域の別名)の使用率
  • M : メタスペースの使用率
  • CCS : 圧縮したクラス領域の使用率
  • YGC : マイナーGCの回数
  • YGCT : マイナーGCの時間
マイナーGC = Young GCの理解ですが、時間があったら確認したい。

Stop The world
Full GCにより一時的にアプリが停止すること(スレッドの停止)

OutOfMemmoryError
Full GCでもメモリ不足が解消できない状態

指定メモリが大きすぎるのも問題
メモリ・CPU・アプリケーションの性能により、
単純にメモリを大きくすれば良いという話ではないらしい。
  • マイナーGCに時間がかかる:New領域が大きすぎる
  • フルGCに時間がかかる:Old領域が大きすぎる

JVMの起動時の設定
  • -Xms:ヒープ領域の起動時のサイズ
  • -Xmx:ヒープ領域の最大サイズ
  • -XX:NewSize:New領域のサイズ
  • -XX:MaxSize:New領域の最大サイズ
  • -XX:SurvivorRatio:From/To領域の使用比率
  • -XX:MaxTenuringThreshold:New領域からOld領域に移動する閾値
  • -XX:TargetSurvivorRatio:Survivor領域の閾値

起動オブションの設定
・引数で渡す
・設定ファイルに書いておく(setenv.sh/setenv.bat)

intelliJ IDEAの操作

Schooの授業とJetBrains公式
ショートカットはここも参照
Keyboard Shortcuts You Cannot Miss
Default Key Map
MAKING DEVELOPMENT AN ENJOYABLE EXPERIENCE あとは、公式販売代理店のサムライズさんの記事

開発効率あげるぞー


メモ

プロジェクト > モジュール
intelliJの階層構造は、「プロジェクト > モジュール」
Eclipseは「ワークスペース > プロジェクト」

クイックフィックス
Win:Alt + Enter Mac:opt + Enter

クラス作成の基本
psvm > public static void main(String[] args) { } sout > System.out.println;

補完
Win:(Ctrl + Space) or (Shift + Ctrl + Space)
Mac:Ctrl + Space
もう一度押すと、詳しくサーチしてくれるらしいです。

アドバイバーの表示
Win:alt + Enter
Mac:alt + Enter

インスタンスの生成(new Class())を書いて補完
introduce local variableが出てくるので、それを押下すると、
クラス名をキャメルケースにした変数を宣言してくれる。

Generate
Win:Ctrl + Enter
Mac:Ctrl + Enter

静的コード解析ツール
format string > +で文字列と変数をつなげているものprint(ln)している場合、
printfを提案してくれる。(alt + Enter)

その他、ラムダへの書き換えやStream APIなども対応

Postfix
list_variable.for まで書いてtabを押すと、拡張for文
list_variable.fori まで書いてtabを押すと、for文
instance.nn で書いてtabを押すと、!= nullのif文
instance.null で書いてtabを押すと、== nullのif文

たっけーけど、Ultimate版を購入してみた
新規IntelliJのみ1年ライセンスで16,000ぐらい

Rename
Refactorの基本 Win:Shift + F6
Mac:Shift + F6

Search everywhere
Win:Double Shift
Mac:Double Shift

Redo / Undo Win:Ctrl + z / Ctrl + Shift + z
Mac:Ctrl + z / Ctrl + Shift + z

たまにUndoをCtrl + yと間違えて、バッファー消しちゃうときがあります。

現在の行を削除
*更新* Win:Ctrl + y
Mac:Cmd + Del

WinとMacで違うみたいです。

現在の行を下にコピー
Win:Ctrl + d
Mac:Ctrl + d

カーソルも移動。公式はカーソルではなくcaretって言っている。

ファイルの場所の表示
Win:Alt + F1 → 「Project View」を選択
Mac:Alt + F1 + fn → 「Project View」を選択

実装や呼び出し元へジャンプ
Win:Ctrl押しながらクリック
Mac:Cmd押しながらクリック

これ慣れると便利です。

選択しているクラスなどの定義をポップアップ表示
Win:Ctrl + Shift + I
Mac:Cmd+Y

Editor以外のウィンドウからEditorに戻る
Win:Esc
Mac:Esc

アクティブなEditorのタブを閉じる
Win:Ctrl + F4
Mac:Ctrl + w
違うね。

アクティブなペイン(pane)を閉じる
Win:Shift + esc
Mac:Shift + esc

規定の番号に対応したpaneを開く(Project:1/Version Control:9)
Win:Alt + Num
Mac:Cmd + Num

ターミナルを開く
前項目のpaneに登録されていないようでして、 Win:未確認
Mac:opt + f12

ファイルの構成をポップアップ
Win:Ctrl + F12
Mac:Cmd + F12

OSのディレクトリアプリで表示
Win:未確認
Mac:Opt + Cmd + F12

Win:
Mac:

Win:
Mac:

Win:
Mac:

Win:
Mac:

Win:
Mac:

2017年2月8日水曜日

Spring Boot / Form周り

Spring BootのForm周りでつまずいたところのメモ
時々intelliJショートカットやGradleのメモ


メモ

Gradle / 拡張プロパティ
ext {
  springBootVersion = '4.0.0.BUILD-SNAPSHOT'
}

Gradle / buildscript
拡張プロパティやレポジトリ、ビルドツールの依存を記述
ライブラリの依存は別の場所
buildscript { 
 ext { // extended property
  springBootVersion = '2.0.0.BUILD-SNAPSHOT'
 }
 repositories {
  mavenCentral()
  maven { url "https://repo.spring.io/snapshot" }
  maven { url "https://repo.spring.io/milestone" }
 }
 dependencies {
  classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
 }
}

Gradle / タスク名は前方一致で特定できれば省略できる
公式参照

Gradle / -x
依存しているタスクを省略
$ gradle --daemon jar 
:compileJava
:processResources
:classes
:jar

BUILD SUCCESSFUL

Total time: 2.217 secs
--
$ gradle --daemon jar -x compileJava
:processResources UP-TO-DATE
:classes
:jar UP-TO-DATE

BUILD SUCCESSFUL

Total time: 0.844 secs


Spring / URLをパラメータとして受け取る
@RequestMapping("/{param}")
public String calc(@PathVariable int param) {

ちなみに、型が違うと下記のように怒られます
Tue Feb 07 22:24:50 JST 2017
There was an unexpected error (type=Bad Request, status=400).
Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "hoge"

少数は問題なかったです。

intelliJ + lombok
Qiita IntelliJ IDEA+GradleでLombokを使う
Enable annotation processing にチェックが覚えられない
Welcome画面で設定すればデフォルト設定できます。
現在Gradleの設定は、 compileOnly "org.projectlombok:lombok:1.16.12" でした

また、ディレクトリのインポート時にbuild.gradleにlombokをdependenciesに記載していなかった場合、
build.gradleに追記後、それをsynchronizedする必要があるみたいでした。
少なくても自分の環境では、synchronizedしないとimport lombok.*;は認識しませんでした。
  • @Data:getter/setter/toString/equals/hashCode
  • @AllArgsConstructor
  • @NoArgsConstructor
うむ、楽だ。

Spring / org.springframework:springloaded
htmlファイルの更新時に、再読み込みをするライブラリ
参照: Qiita Spring Boot + Thymeleaf + Tomcat + Gradleで業務系アプリ 躓いた所6点
buildscript {
 ext {
  springBootVersion = '1.5.1.RELEASE'
 }
 repositories {
  mavenCentral()
 }
 dependencies {
  classpath
                  ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  classpath "org.springframework:springloaded"
 }
}
開発効率上げるために入れたほうがいい。

Thymeleaf自体はgradleで
compile "org.springframework.boot:spring-boot-starter-thymeleaf"

またまた、thymeleafのキャッシュは開発時には切っておきます。
[application.properties]
spring.thymeleaf.cache=false

Spring / @Controllerと@RestController
かなり恥ずかしい話ですが、違いがよくわかっていなかった。
@Controllerが付いているクラスのメソッドの戻り値は、HTMLテンプレートのファイル名
@RestControllerがついているクラスのメソッドの戻り値はHTTPレスポンスボディ

参考:Qiita Spring MVCのコントローラでの戻り値いろいろ

Git / **/で再帰的にignore
参考:MindTo01s git-ignoreの設定

Spring / 2.0.0-SNAPSHOTで超絶シンプル@Controllerサンプルを試してみるも。。。
ルーティング(@RequestMapping)がうまくいかず、ファイルがあるのに404が出た
hotload=ONやhtmlcache=OFFの設定があったので、とりあえずミートしてみましたが、変わらず。
1.5.1.RELEASEで同じコードを試したら、問題なくルーティングできた。
無駄に時間食ったわ。。。

Spring / ModelとModelAndView
Modelはセッションの属性値を持つだけ。
ビューのファイル名は別途メッソドの文字列返り値として渡す。

一方、ModelAndViewはセッションの属性値に加え、viewNameとしてビューのファイル名をもつ。
// Model
@RequestMapping("/{num}")
public String index(@PathVariable int num, Model model) {
  model.addAttribute("msg", "arg: " +num);
return "index"; // index.htmlを開く

// ModelAndView
public ModelAndView index(@PathVariable int num, ModelAndView modelAndView) {
  modelAndView.addObject("msg", "total: " + res);
  modelAndView.setViewName("index");
return modelAndView; // index.htmlを開く

IntelliJ w/Mac 1行消す
Command + delete
Qiita 忙しい人のためのIntelliJ IDEAショートカット集(´-`)

Command + dかと思ったんですが、逆に1行増えました。。。。Duplicateっすね。

Spring / フォームの値受け取り
@RequestParam("form_name") Type var_name
public ModelAndView submit(@RequestParam("name") String name , ModelAndView modelAndView) {

forwardとredirect
forwardはURLは元のまま、
redirectはURLも遷移後のものとなります。
Modelの場合
return "forward:/";

ModelAndViewの場合
return modelAndView;

2017年2月7日火曜日

Spring Boot / JPAとか

Spring BootのJPA周りとかでつまずいたところのメモ


メモ

JPA /JPQLのつまずきポイント
@QueryのFrom句は、ドメインクラスの@Table(name=xxx)の指定とは関係がなく、
ドメインクラス名を指定する

****
具体的には、
ドメインクラスでこう指定し、
@Table(name = "customers")

リポジトリのJPAインターフェースを下記のように設定
public interface CustomerRepository
 extends JpaRepository {
    @Query("SELECT x FROM Customer x ORDER BY x.firstName, x.lastName")
    List findAllOrderByName();

}
customersだとmappingできないと怒られる。
ドキュメントをちゃんと読もう

RequestMappingの設定確認
@RestControllerをつけたクラスに、
対応した@RequestMappingが付与する

起動時の確認としては、ログにMapped "xxx" onto ....と出力されるかを確認する
Looking for @ControllerAdvice: 
 org.springframework.boot.context.embedded.
 AnnotationConfigEmbeddedWebApplicationContext@243c4f91
Mapped "{[/api/customers],methods=[GET]}" 
 onto java.util.List 
 com.example.api.CustomerRestController.getCustomers()
...

SQL / Primary key制約の解除
> ALTER TABLE table_name DROP CONSTRAINT primary_key_name ;

JPA / Pagingとsort
Mapping(Controller)
    @GetMapping
    Page<Customer&t; getCustomers(@PageableDefault Pageable pageable) {
        Page customers = customerService.findAll(pageable);
        return customers;
    }
Service
    public Page<Customer> findAll(Pageable pageable) {
        return customerRepository.findAll(pageable);
    }
Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer&t; {
    @Query("SELECT x FROM Customer x ORDER BY x.firstName, x.lastName")
    Page<Customer&t; findAllOrderByName(Pageable pagealbe);
}
URLパラメータで表示数を変化できる
http://localhost:8080/project?page=1&size=3
これ面白い。ちょうど検索数が多い場合の画面を実装どうしようと考えていたとこ。
Pageの内容だとこんな感じのJSON
{"content":[{"id":1,"firstName":"Hanamichi","lastName":"Sakuragi"},
{"id":2,"firstName":"Kaede","lastName":"Rukawa"},
{"id":3,"firstName":"Sho","lastName":"Sato"}],
"last":false,
"totalElements":5,
"totalPages":2,
"size":3,
"number":0,
"numberOfElements":3,
"first":true,"
sort":null}


Spring / 開発時にHTMLのキャッシュを無効化する
デフォルトはパフォーマンス向上のため、HTMLはキャッシュされる設定です。
そのため、HTMLキャッシュを開発時に無効化すると効率的にHTMLファイルの変更を確認できます。

方法は2通り
  1. application.propertiesで設定する
  2. Spring Dev Toolsを使用する
Spring Dev Tools はgradleならbuild.gradleのdependencyに加えておくだけ。

2017年2月5日日曜日

Eclipse

Eclipseのschoo授業を見てみた


ショートカット

Undo / Redo
  • Win:Ctrl + z / Ctrl + y
  • Mac:Ctrl + z / Ctrl + Shift + z

カーソルがある行を削除
  • Win:Ctrl + d
  • Mac:Ctrl + d

先頭末尾移動
  • Win:Ctrl + ↑→↓←
  • Mac:Cmd + ↑→↓←

カーソルがある行の移動
  • Win:alt + ↑↓
  • Mac:opt + ↑↓

カーソルがある行を前後行にコピー
  • Win:Alt + Ctrl + ↑↓
  • Mac:opt + Cmd + ↑↓

改行せずに行挿入
  • Win:Shift + Enter
  • Mac:Shift + Enter

不要なimport文の削除
  • Win:Ctrl + Shift + o
  • Mac:Shift + Cmd + o

対応する中かっこへ移動
  • Win:Ctrl + Shift + p
  • Mac:Cmd + Shift + p

フォーマット
  • Win:Ctrl + Shift + f
  • Mac:Ctrl + Shift + f

mainメソッドの実行
  • Win:Ctrl + alt + xj
  • Mac:Cmd + opt + xj

入力補完の呼び出し
  • Win:Ctrl + space
  • Mac:Ctrl + space

Rename
  • Win:Ctrl + Alt + r
  • Mac:Cmd + opt + r

プロジェクトサーチ
  • Win:Ctrl + h
  • Mac:Ctrl + h

2017年2月4日土曜日

あまり進展しないPostgre SQLメモ -case式

達人に学ぶ SQL徹底指南書を読んで、Postgre SQL DBで試してみました。


メモ

とりあえずpostgresql serverの起動
$ postgres -D /usr/local/var/postgres

いるはずのユーザのログインで、DBがないって怒られる
(usr) $ psql -U usr -W
Password for user usr: 
FATAL:  database "usr" does not exist
psql: FATAL:  database "usr" does not exist
$ 
なにやら、psql実行時ユーザと同じロール名でアクセスする際は、
-UをつけていてもDB名として認識されるみたいでした。
DB名を記載すれば、期待通り、-Uはロール名として認識してくれました。
$ psql -U usr -W testdb

\l
DBの一覧表示

# create database professional_sql ;
databaseの作成

# \c proffesional_sql
DBへの接続

新規テーブルの作成
create table Greatests (
  key char(1) primary key
  , x integer not null
  , y integer not null
  , z integer not null
);

\dt
テーブルの一覧表示

\i file
SQLファイルからクエリの実行

UNION / UNION ALL
UNIONは重複を削除
UNION ALLは削除しない

\w ファイル名
バッファに残っている内容をファイルに保存

PostgresqlでGreatest/Least関数使えるんですね
Release 8.1で追加されたみたいでした。
Add GREATEST() and LEAST() variadic functions (Pavel Stehule)
8.1 release note

都道府県テーブルを作る
東京都の人口が1,300万なので、
2バイトのsmallintでは足りず、4バイトのintegerがちょうど良さげ

最初に該当したwhen句を返す
対象値は重複させないようにする
ELSE句を省略すると
ELSE NULLとなる

条件法
「PならばQ」の論理式
「P→Q」と書ける

論理積(logical product)
「PかつQ」の論理式 「P^Q」と書ける

\r
クエリのキャンセル

テーブルのリネーム
alter table cousemaster rename to coursemaster;

# \! pwd
psqlプロンプトでlinuxコマンドを実行

# \d TABLE_NAME
テーブル定義を確認する
参考:PostgreSQLのpsqlでテーブル定義を確認する方法

テーブルに付く制約とカラムに付く制約
表現が正しいか自信がないが、あるカラムに対する制約はカラムに適用され、
複数カラムにまたがる制約はテーブルに適用されているみたいでした。
alter文やテーブル定義を確認しただけの推測です。公式ドキュメント読まな。。。
# alter table studentclub add primary key (std_id, club_id);
# alter table studentclub alter column main_club_flg set not null;

アルファにしてオメガ
最初にして最後
コトバンクより

$createdb hoge / $dropdb hoge
localのpostgresに対してcreate database hoge(drop database hoge)を実行する

データベース名
先頭はアルファベット
63文字以内
ユーザ名と同じデータベース名を推奨

DBに接続するPostgreSQLユーザ
指定がなければ、OSのアカウントと同じ名前を使用
Postgresを起動するOSユーザは、PostgreSQLユーザとしても存在する

mydb=> / mydb=#
mydb=> 一般ユーザ
mydb=# スーパーユーザ

SELECT version();
バージョン情報を取得

識別子を二重引用符で囲むと大文字小文字を区別する
公式ドキュメントを読んでてびっくりした。
SQLはキーワードと識別子に対して大文字小文字を区別しません。 
ただし、(上では行っていませんが)識別子が二重引用符で括られていた場合は大文字小文字を区別します。
version 8.4.4だけど、多分、最新でもそうでしょう。

COPYコマンド
クライアントとサーバが別で(localhostでなくて)、サーバにファイルを置かない場合、\copyコマンド
サーバにファイルを置く場合(COPYコマンド)
参照:CSVファイルをデータベースにインポートする
# copy coursemaster from '/Users/usr/test.csv' USING DELIMITERS ',';
from句でファイルをフルパスで書く必要性がありました。

ビュー
他のビューに対して、ビューをつくってもOK
CREATE VIEW tempview AS
    SELECT city, location
        FROM weather, cities
        WHERE city = name;

ウィンドウ関数
チュートリアルで説明されるほど、メジャーな関数なのですが、
自分がOracle DB Bronze SQLを勉強したときは、試験範囲ではなかったと思います。
利点は、集約しなくても、平均や順位を出すことができるということです。
avg(salary) OVER (PARTITION BY depname)
rank() OVER (PARTITION BY depname ORDER BY salary DESC)
OVER句をつけることにより、avg集約関数ではなく、ウィンドウ関数として扱われます。

また、partition by COLUMN_NAMEは省略可能で、この場合は全ての行を含む仮想テーブルを対象とします。
SELECT score, sum(score) over () from score_table;
また、ORDER BY句のみの場合は、
ウィンドウ範囲が広がっていくような動きになります。
SELECT score, sum(score) over (ORDER BY score) from score_table;
公式にもありますが、重複するscoreがsumに含まれないことに注意が必要です。 ウィンドウ関数は、SELECT句とORDER BY句でしか使えません


テーブルの継承
初めて知った。テーブルを拡張する場合に、選択可能な手段です。
デメリットはUNIQUE制約または外部キーと合わせて使えないこと。これは痛い
CREATE TABLE users (
  name text,
  create_dt date
);

CREATE TABLE super_users (
  approver text
) INHERITS (users);

文字列定数内に'シングルクォートを入れる
''と続けて2つシングルクォートを入力する

改行で文字定数を区切った場合
SELECT 'foo'
'bar';
 ?column? 
----------
 foobar

SELECT 'foo''bar';
 ?column? 
----------
 foo'bar

# SELECT 'foo'      'bar';
ERROR:  syntax error at or near "'bar'" at character 19
STATEMENT:  SELECT 'foo'      'bar';
ERROR:  syntax error at or near "'bar'"
LINE 1: SELECT 'foo'      'bar';
                          ^

エスケープ文字列定数
E'hoge'というように、シングルクォートの前にEをつける
エスケープ文字列定数内だとシングルクォートを入力するのに、''以外に\'も使える

引用符を指定する
$$や$hoge$と文字列定数の区切り文字を指定することができる

Oracle DBでは別名にasをつけない
トリビア

dropテーブルの権限は付与できない
テーブルの所有者しか、テーブルの削除はできない。権限をGRANTできない。
レコードの削除(DELETE)権限は付与することができる

PostgreSQLはレコードをDELETEしても、物理削除しない
知らなかったよー。

以下引用:OSS DB/Silverの例題解説「運用管理 - 基本的な運用管理作業(自動バキュームの概念と動作)」
PostgreSQLは追記型のデータ構造を採っており、
データをDELETEしても、データに削除済フラグがつくだけで、
物理的にはデータが削除されません。

UPDATEも内部的にはDELETEとINSERTを実行するため、
古いデータが残り、そのまま放置すると物理的なデータ量が増えていきます。
この削除済みデータの領域を回収するのがバキューム(VACUUM)機能であり、
それを自動的に実行するのが自動バキュームです。

PITR
Point In Time Recovery
特定時点への復旧のこと

createuserの方式変更
PostgreSQL 9.1:対話式
PostgreSQL 9.2:デフォルトで権限を付与しない

付与していないユーザ権限の剥奪
エラーにもならず、コマンドは実行される

RoleとUserに違いがない
PostgreSQLだとそうらしい

2017年1月29日日曜日

Gradle / 事始め2

書き足りなかった部分をプラス
途中からSpringも混ざりますが、ご容赦願います。


メモ

$ gradlew xxx -Pargs="hoge"
-Pargs:引数の設定

jarだけ消す
$ gradle cleanJar
[root]/build/libsディレクトリ配下にあるjarを消去できます。
生成済みのclassファイルは残ったままです。

サーバポートを変更してwebアプリjarを実行する
$ java -jar demo-0.0.1-SNAPSHOT.jar --server.port=8888
でいけるはずですが、、、
no main manifest attribute, in demo-0.0.1-SNAPSHOT.jar
となりました。デフォルトポートで実行するぶんにはマニフェストファイル不要なんですがね。。。
mavenで作った際は指定できましたが、gradleだと何か足りていないみたいでした。

spring boot devtoolsを使用する
compile('org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-devtools')

結果、立ち上げ時のmainプロセスが、restartedMainプロセスに変わります。
これでホットデプロイできるらしいですが、これは完全サポートが保証されているわけではないみたいです。

build.gradle
sourceCompatibility:受け付けるソースコードのバージョン
targetCompatibility:クラスファイルのバージョン

SpringBootTest
package com.example;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.boot.test.web.client.TestRestTemplate;
import static org.hamcrest.CoreMatchers.is;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoApplicationTests {

 @Autowired
 TestRestTemplate template;


 @Test
 public void contextLoads() {
  ResponseEntity res = template.getForEntity("/", String.class);
  assertThat(res.getStatusCode(), is(HttpStatus.OK));
  assertThat(res.getBody(), is("Hello world"));
 }

}

Assertはstaticでないといけないっていうのが気をつけどこ

Java / try with resources句
tryに()カッコをつけて、その中で閉じる必要があるインスタンスを生成する
finally句がなくてOK

IntelliJでlombokを入れる
Preferencies → Install JetBrains plugin...
→ lombokで検索 → Install
libraryに追加した後にビルドパスに追加するのをお忘れなく。。。
Eclipseでもそうですが、libraryにjarをコピーしただけでは使えません。

また、Annotation Processorsを有効にしないと@AllArgsConstructorなどが認識されない
参考:Lombokプラグインをインストールする
Preferencies → Build, Execution, Deployment
→ Compiler → Annotation Processors
Defaultを選んで、右のペインで「Enable annotation processing」にチェックを入れる

IntelliJにCoverageというプラグインが入っている
Run with Coverageで実行するとどれだけテストがカバーできているかが表示される

Spring / @SpringBootApplication
下記3つのアノテーションを1つにまとめた効果
  • @EnableAutoCOnfiguration
  • @Configulation
  • @ComponentScan

Spring / CommandLineRunnerインターフェース
DIが可能になる(プロパティに@Autowiredをつけて、インスタンスを自動生成できる)
また、mainメソッドに
SpringApplication.run(xxx.class, args);
とすることでアプリを立ち上げられる。
もちろん、自クラスにrunメソッドを記載すること。

Java可変長引数([type]... hoges)
そんなに使わないから、ググりました。
ひしだま's 技術メモページ
  • 配列としてメソッド内で使える
  • 引数のうち一つだけ
  • 最後の引数の時だけ使用可能
  • 可変長引数と同じ型でオーバーロードして、どちらにも適用されるような呼び出しは、可変長で「ない」メソッドに引数を渡す

Spring / @ComponentScanの対象になるアノテーション
  • @Component
  • @Controller
  • @Service
  • @Repository

lombok/ @AllArgsConstructor
プロパティ全てを引数に取るコンストラクタを自動生成するCC

Java / ConcurrentMapインターフェース
スレッドセーフなマップ
実装はConcurrentHashMapクラスか、ConcurrentSkipListMapクラス。

Postgre SQL / ユーザの一覧
$ select rolname from pg_roles;
or
=> \du
Describe Userかな。。。

psql / \c (database name)
pslqでのDB接続は\c (database name)

Spring / JDBCでの接続
必要なもの
  • DBコネクタライブラリ
  • spring-boot-starter-jdbc
実行の流れ
  • NamedParameterJdbcTemplateインスタンス
  • SQL文字列
  • MapSqlParameterSourceインスタンス(SqlParameterSourceインターフェース)
  • NamedParameterJdbcTemplateのqueryForObjectメソッド実行

H2DBでインメモリな設定
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.sql-script-encoding=UTF-8

H2DBで永続化する
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./target/db/testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.sql-script-encoding=UTF-8

SQL / テーブルがなかったら、、、
CREATE table if not EXISTS salse_table ( id int, date timestamp );

2017年1月28日土曜日

Gradle / 事始め

今更感がありますが、Gradleを初めてちゃんと触れたので、メモメモ


メモ

Mac OSXでのJAVA_HOME設定
$ export JAVA_HOME=`/usr/libexec/java_home`
バッククォートです。
注意点は、JDK変えた時に改めてexportしないといけないことですか。
$ /usr/libexec/java_home --help
Usage: java_home [options...]
Returns the path to a Java home directory from the current user's settings.
ログインユーザの環境でのjava_homeを返します。

gvmもといSDKMAN
Groovy/Grails関連のパッケージ管理ソフト
$ curl -s "https://get.sdkman.io" | bash
でインスト

$ gvm install gradle
gradleのインストール
Installing: gradle 3.3
Done installing!


Setting gradle 3.3 as default.
で終わり。

バージョンを指定したインスト
$ gvm list gradle
DL可能なバージョンを表示
$ gvm install gradle 3.2.1
など。

デフォルトバージョンの設定
$ gvm default gradle [version]

$ gradle --version
とりあえず、パス通っているかを確認

Groovy / 文字列
'シングルクォート:文字列(charじゃない)
"ダブルクォート:GString($で変数を入れることができる...「なんだと」)

Groovy / メソッド呼び出し時のカッコ
引数がないとき、メソッドの引数としてメソッドを使うとき、式の右辺でメソッドを使うときは、()が必須 その他のケースで、引数があるときはなくてもOK
1つのメソッド呼び出しする行の時だけですね。

Groovy / defによる変数の宣言
def age = 99
型を省略して変数を宣言できます。
Javaにおける、Object型の変数と同じ扱いになるそうです。

ダックタイピング
実際の値が、処理に適したものかどうかでメソッドやプロパティを捉える。

クロージャ
{}で定義する
def closure = { param -> println "$param" }
引数に対して->処理を行う
$itをつかって、引数を省略することも可能
呼び出しは、
closure.call()または、closure()
カッコの省略はメソッドと同様。

<<によってタスクに定義することも可能
task printParam << { println "$it" }

分けて書く場合、
def closure = { param-> println "$param" }
task printParam {}
printParam.leftShift(closure)

built-in task
あらかじめ利用できるgradleのタスク
$ gradle tasksで一覧表示が可能
$ gradle tasks
The Task.leftShift(Closure) method has been deprecated and is 
 ..scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
        (/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment
 - Displays all buildscript dependencies declared in root project 'gradle_git'.
components
 - Displays the components produced by root project 'gradle_git'. [incubating]
dependencies
 - Displays all dependencies declared in root project 'gradle_git'.
dependencyInsight
 - Displays the insight into a specific dependency in root project 'gradle_git'.
dependentComponents
 - Displays the dependent components of components in root project 'gradle_git'. [incubating]
help
 - Displays a help message.
model
 - Displays the configuration model of root project 'gradle_git'. [incubating]
projects
 - Displays the sub-projects of root project 'gradle_git'.
properties
 - Displays the properties of root project 'gradle_git'.
tasks
 - Displays the tasks runnable from root project 'gradle_git'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task 

BUILD SUCCESSFUL

Total time: 0.957 secs


Build Setup tasks / Help tasksのグループが確認できる

とりあえずのテスト
$ vim build.gradle
task hello << {
  println 'Hello Gradle world!'
$ gradle hello
Starting a Gradle Daemon (subsequent builds will be faster)
The Task.leftShift(Closure) method has been deprecated and is scheduled to 
 ..be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
        at build_441sas0jfgrsmxsyzaz0sazay.run
 ..(/Users/Shogo/gitdir/gradle_git/build.gradle:1)
:hello <-----タスク名
Hello Gradle world! <-----タスクの出力

BUILD SUCCESSFUL

Total time: 4.332 secs

$ gradle properties
ビルドスクリプトで定義されているプロパティの一覧を表示

gradleのデバッグ

-q:エラーログのみ出力する
-i:INFOレベル
-s:例外のスタックトレースを表示
-S:例外のフルスタックトレースを表示
-d:通常のスタックトレースを含むデバッグログを表示

$ gradle help --task
タスクを指定してヘルプを確認できる

ビルドスクリプトファイル名をデフォルト(build.gradle)以外のファイル名にする場合
$ gradle -b build_new.gradle hello
-bオプションでビルドファイルを指定する

initタスク
手順
  1. プロジェクトルートとなるディレクトリを作成する
  2. そのディレクトリに移動する
  3. $ gradle init --type java-library

タスクのライフサイクル
  • Internal:内部的にしか参照できない機能。ユーザが直接使うことはできない。
  • Incubating:実験的な公開
  • Public(default):公開中  どのライフサイクルステータスもつけられていないときはパブリック
  • Deprecated:廃止予定のタスク

JCenter
Mavenレポジトリ

dependency
gradle init --type java-libraryで作ったbuild.gradle
dependencies {
    // The production code uses Guava
    compile 'com.google.guava:guava:20.0'

    // Use JUnit test framework
    testCompile 'junit:junit:4.12'
}
compile:プロダクションコードのコンパイルと実行に必要なライブラリを記載 test:テストコードのコンパイルと実行に必要なライブラリを記載

Google Guava
Javaのコアライブラリ

タスクの一覧をGUIで確認する
$ gradle --gui

ビルドする
$ gradle build
Starting a Gradle Daemon (subsequent builds will be faster)
:compileJava
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava-parent/20.0/guava-parent-20.0.pom
Download https://jcenter.bintray.com/com/google/guava/guava/20.0/guava-20.0.jar
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test <-- テストの実行
:check
:build

BUILD SUCCESSFUL

Total time: 17.849 secs
実行すると、プロジェクトルート配下にbuildディレクトリができます。
再度、$ gradle build 実行しても、変更がないタスクはスキップされます。

$ gradle clean
buildディレクトリが削除されます

テストの実行結果
build/reports/tests/test/index.html
にテスト結果が記載されます。

テストコードの実行
$ gradle test

$ gradle tomcatRunWar

Gradleでは型の宣言が必要
最低でもdefが必要(Object型)

システムプロパティの使用
System.properties['xxx']
$ gradle -Dxxx=hoge [task]

もしくは、gradle.propertiesに記述する
systemProp.message=hoge
この場合、自動でプロパティファイルを参照するので、
引数は不要
$ gradle [task]

taskの定義
タスクの設定
<<あり:実行処理
<<なし:設定処理

2017年1月24日火曜日

Java/ org.w3c.dom

Java SE 1.4からある古いパッケージですが、今日初めて知ったので、少しメモ


メモ

Documentインターフェース
スーパーインスタンス:Node
HTML/XMLファイル全体をさすインターフェース。
ドキュメントツリーのルートを格納する。

Elementインターフェース
HTML/XMLファイルの要素のインターフェース

2017年1月22日日曜日

Groovy / Differences with Java

Groovyの公式ドキュメントを読んでみます。
参考:Differences with Java

実行環境:Groovy Version: 2.4.8 JVM: 1.8.0_111 IDE:IntelliJ IDEA 2016.3.3


Default imports

次のパッケージはデフォルトでインポートされていますので、
下記のパッケージのクラスは明示的にimportしなくても使えます。

  • java.io.*
  • java.lang.*
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.net.*
  • java.util.*
  • groovy.lang.*
  • groovy.util.*
printlnで標準出力できます〜。(System.outがいらない)


Intellij IDE CEでJunitしてみる

プロジェクトを右クリックする
Open Module Settings
Libraries
+ button
Junitで検索
とりあえず現在の最新のjunit:junit:4.12を検索
OK

あとは実行クラスでassertするだけ

import org.junit.Assert;
Assert.assert();


Intellij IDE CEでgroovyしてみる

Groovyプロジェクトは最初から選べましたが、
実行してみるとSDKがないと怒られました。

実行環境がMax OSXなので、brew install groovysdkです。
先にgroovyだけでインストールしていると競合します。
(エラーメッセージにある通り、brew unlink groovy競合を回避できます)

...

が、しかし、
brewでのインストール先が、「/usr/local/Cellar/groovysdk/2.4.7」で
Intellijで選べないとこにあるわけです。
しょうがないので、公式からzipをダウンロードし、解凍したディレクトリを選択します。
これでコンパイルできます。


Multi-method(Runtime Dispatch)

オーバーロードされたメソッドについての話。
Javaだとコンパイル時にどのメソッドを呼ぶかが決まります。
一方、実行時の引数の型により、呼び出すメソッドが決まります。

公式のサンプルをIntelliJで実行できる形式にしたものが下記です。
※JUnitをライブラリに登録してあるものとします。

import org.junit.Assert;

int test(String arg) {
    return 1;
}
int test(Object arg) {
    return 2;
}
Object o = "Object";
int returnInt = test(o);

//println result;
Assert.assertEquals((long)1, (long)returnInt);


IntelliJの実行ショートカット

Ctl + Shift + r
MacでIntelliJを使うのに慣れていないものでして。。。

Array initializers

配列の初期化は[]でよろしくどうぞ。
{}はクロージャ(無名メソッド)で予約されているので、配列の初期化には使えないそうです。

unexpected token: 1 @ line 4, column 17.
   int[] array = { 1, 2, 3};
                   ^
こんな感じで怒られます。

クラスのフィールドのアクセス修飾子を省力するとprivateとなりgetter/setterが作られます

class Student {
    String name
}

Student person = new Student()
person.setName("hoge")

println(person.getName())
Javaだとデフォルトのアクセスレベルはパッケージプライベートです。

また、groovyで@PackageScopeアノテーションをつけることで、
パブリックではなく、パッケージプライベートにすることができるようです。
自分の環境だと下記のエラーでアノテーションとして認識してくれなかったのですが。。。

6: unable to resolve class PackageScope ,  unable to find class for annotation
 @ line 6, column 1.
   @PackageScope class Student {
コマンドラインで実行してもダメ、コンパイルの設定も問題なさそうでしたが。。。
stackoverflowでも同じ事例はなさそうで、
「Eclipseでクリーン実行したらエラーが消えた」という事例はありましたがIntelliJでクリーン実行なさげ。


EclipseでGroovyしてみる

上記のunable to resolve class PackageScope問題で、原因切り分けとして、
Eclipseで同じコードを実行してみます。
参考:Qiita Gradle + Spock + Eclipse環境
まずプラグインが入っていなかったので、入れます。
使用バージョンは、STS 3.8.3.RELEASE(Eclipse Neon.2(4.6.2))です。
Help → Install New Software... →
http://dist.springsource.org/snapshot/GRECLIPSE/e4.6/ に対して、groovyで検索してプラグインを入れます。
これで新規作成ウィザードでGroovy関連を使用できます。
結果、変わらず「PackageScope is not an annotation」でエラーでした。とりあえず次。


GroovyはTry with Resourceをサポートしていません

公式でARM(Automatic Resource Management)という言葉が出てきましたが、StackOverflowを見た限り、
Try with ResourceのことをARMとも呼ぶみたいです。
GroovyはTry with Resourceはサポートしていませんが、クロージャで代用することが可能みたいです。
該当するeachLineメソッドがドキュメントに載っていないので、定かではないのですが。。。
IOGroovyMethodsのpublic static <T> T eachLine(InputStream stream, Closure<T> closure)
が一番近しいですが、、、どうだか。


Static inner classes

若干Javaと異なるらしい

Static inner classes

これは全然変わらない。

Anonymous Inner Classes

インナークラスのインスタンス生成は、
outer.new.Inner()はサポートされず、new Outer(inner)で書く


Lambdas

Java8のラムダそのままの書き方ができないが、クロージャで代用できる。


GStrings

ダブルクォートで囲った文字列は、GStringとして解釈される。
ダラーマークを含む文字列が,JavaとGroovyで若干異なる出力になる可能性がある。
ただ、Java APIに沿ってGStringとStringをオートキャストしてくれる。
しかし、Objectクラスの場合は、実際の値がチェックされる。


String and Character literals

Groovyだとシングルクォートは文字列として扱われる。
char型の変数にシングルクォートの値が割り振られた時は、自動でcharにキャストする。
値を直接参照する時は、キャストされないので、明示的にキャストする必要がある。

キャスト方法

  1. (char)'a'
  2. 'a' as char
(char)'a'
String str = 'x'
char x = (char) str
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x
'a' as char
String str = 'x'
char x = str as char
println((Object)x.getClass().getCanonicalName())
println(x)
-----------
java.lang.Character
x


Primitives and wrappers

Groovyは変数を全てオブジェクトとして扱う、とさらっと書かれています。
そのため、プリミティブ型変数をラッパークラスに自動変換します。
Javaはボクシング(ラッパークラスからプリミティブ型変数への変換)より変数拡張を優先します。
Groovyでは、プリミティブ型変数の引数をラッパークラスとしてまずは扱うので、
JavaとGroovyとでオーバーライドしたメソッドの呼び出し先が異なる場合があります。


Behaviour of ==

==:値のチェック
a.is(b):参照のチェック
nullは==でいいみたいです。


Extra keywords

Javaのキーワードに加えて、Groovyはas, def, in, traitもキーワードです。


Conversions

時間があるときに、確認します。


参照サイト

公式以外はこれかな、、、
http://www.tutorialspoint.com/groovy/