2018年1月13日土曜日

Java : EclipseでGradleを使ってWebアプリ

先日、Mavenを使ってHelloWorldを出力するWebアプリの作成を行った。それまでMavenプロジェクトを一から自分で作ったことがからやってみたかったのだけれど、Mavenと同じようにGradleプロジェクトも一から自分で設定したことがない。Gradleも初期の設定は他の人がやっていて、私自身が携わる機会がなかったのだ。

以下の手順はEclipse 4.7 Oxygenでやった場合。

最初にGradleプロジェクトの作成。ファイル -> 新規 -> その他

「Gradle プロジェクト」を選択して、次へ

プロジェクト名に任意の名前を入力して、次へ

次へ

完了

作成されたプロジェクトの構成はこのようになっている

これだけだとWebアプリとしては動作しないので、いくつか作業が必要となってくる。まずはbuild.gradleの設定から見ていく。

プロジェクトをWTPに変換するために、build.gradleファイルの先頭に以下のソースを書き加える。
apply plugin: 'war'
apply plugin: 'eclipse-wtp'

Servelt-APIを入手するためにdependenciesに以下を書き加える。
compile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'

書き換えたbuild.gradle


ここまでやったら、Gradleプロジェクトのリフレッシュを行う。

次はweb.xmlの追加を行う。下記のような構成でweb.xmlを追加する。

web.xmlの内容


最後にプロパティの変更。プロジェクトを右クリック -> プロパティ―。デプロイメント・アセンブリーを選択して追加をクリック

フォルダーを選択して、次へ

src/main/webappを選択して、完了

/src/main/webappが追加されているのを確認したら、適用して閉じる

ここまでやったらWebアプリを作成する準備が整ったので、コードの実装を行う。

コントローラ(HelloWorldController.java)


JSP(helloworld.jsp)


最終的にプロジェクトは以下のような構成となる。

Tomcatを実行して、http://localhost:8080/GradleSample/HelloWorldにアクセスするとHelloWorldが表示される。

2018年1月11日木曜日

Java : EclipseでMavenを使ってHelloWorld出力まで

Mavenは他の人が設定したのを使ったことはあるのだけれど、自分でいちから設定したことはなかったので、HelloWorld出力までをやってみることにした。

以下の手順はEclipse 4.7 Oxygenでやった場合。

まずはMavenプロジェクトの作成。ファイル -> 新規 -> その他

「Mavenプロジェクト」を選択し、次へ

次へ

アーティファクトID「maven-archetype-webapp」を選択し、次へ

グループIdとアーティファクトIDに任意の値を設定し、完了

これだけでOKかと思いきや、コンパイルエラーが発生してしまう。これって、プロジェクトのテンプレートとしてどうなんだろう?

エラーの内容は「スーパークラス "javax.servlet.http.HttpServlet" が Java ビルド・パスで見つかりませんでした」というもの。このエラーを解消するために、pom.xmlに以下を追加する。

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.0</version>
</dependency>

versionタグの値はMavenのリポジトリを参照して、最新のものを選択しておけば取りあえず問題ないだろう。

pom.xmlに追加が終わったら、プロジェクトを右クリック -> 実行 -> Maven install

最後にプロジェクトをビルドしてプロジェクトを実行するとHelloWorldが表示されるようになる。

2018年1月10日水曜日

Java : try-with-resource文のJava9における拡張

Java9ではtry-with-resource文の拡張が行われている。

try-with-resource文とは何なのかというと、これを使うことで明示的にリソースの開放を行わなくても、AutoCloseableインタフェースが実装されているクラスであれば自動的に開放を行ってくれるようになるというものだ。

try-with-resource文を使わないとfinally句でリソース開放を行う必要があるが、リソースの開放はやらなくてもコンパイルエラーとはならないため、リソースの開放をうっかり忘れてしまう危険性があるというところが問題だ。

try-with-resource文を使わないコード例


try句とfinally句で同じ変数を使う必要があるので、変数をtry句の必ず外側で宣言しないといけない。finally句でcloseメソッドを呼ぶときにIOExceptionの可能性があるため、try-catchをネストしなければならないことが少し気に入らない。

こうした問題はtry-with-resource文を使うと解消される。

try-with-resource文を使うコード例


このように書くことで、closeを明示的に行わなくてもよくなる。

try-with-resource文がJava9でどのように拡張されたかというと、Java8までだとtry節の中で変数を宣言することが必須だったのが、不要となったところだ。

try-with-resource文(try節の外で変数を宣言)


書き方の選択肢が増えて、より柔軟になっている。

2018年1月8日月曜日

Java : Jigsaw transitiveキーワード

前回、Jigsawを少し触ってみたが、Jigsawを使おうとすると少し面倒なところがある。

module-info.java


org.Hello.hello.java


java.sqlをimportしようとするとエラーとなってしまうのだ。これはmodule-info.javaに利用するモジュールを指定していないからだ。逆に言えばmodule-info.javaにモジュールを指定しておかないとJavaの標準ライブラリだろうがなんだろうが利用できないということになる。上記のコードは以下のように書き換えることで、エラーが発生しなくなる。

module-info.java


org.Hello.hello.java


これで使えるようになるのだけれど、標準ライブラリまでいちいち全部指定していくのは面倒だ。モジュール内部で別のモジュールを利用していれば、それもmodule-info.javaに追加しないといけないので、モジュールの関連をすべて調べていく必要が出てきてしまう。

それを回避するのがtransitiveキーワード。

transitiveをつけてrequiresを宣言することで、指定したモジュール内で必要とされているモジュールも一緒に宣言したのと同じ意味となる。

module-info.java


Javaの標準ライブラリをすべて指定したい場合は下記のようにmodule-info.javaを変更すればよい。

module-info.java


JDKのモジュールとパッケージの関係はこちらのリンクの中のModule Graphを見ると分かる。

2018年1月3日水曜日

Java : Jigsawを試してみる

紆余曲折はあったみたいだけれど、Java9ではモジュールシステムが導入されることになった。Project Jigsawと呼ばれているものだ。

概念はさほど難しいものではない。これまではpublicなクラスのpublicメソッドはあらゆる場所から参照することが可能だった。APIなどを開発する開発者にとっては、ちょっと使いづらいところなんじゃないかと思う。何故なら、モジュール内部でのみの参照を想定したクラス、メソッドを作成することが出来なかったからだ。

それが、パッケージ単位で公開、非公開を設定できるというのがJigsawということになる。

やり方も難しくはなく、 module-info.java というファイルに公開するものを記述するだけで実現できる。module-info.java はsrcフォルダ直下に置く。もし、Eclipseを使っているならデフォルト・パッケージに配置すればいい。これ以外の場所に配置してもコンパイルエラーとなることはないが、正常に動作してくれないので注意。



src ---- org.hello --- Hello.java
     |
     |-- org.internal --- World.java
     |
     |-- module-info.java

このようなプロジェクトを作成する。それぞれのコードは以下のようになる。

module-info.java


"exports org.hello;"の部分で外部に公開するパッケージを指定している。

org.hello.Hello.java


org.internal.World.java



これを利用する別プロジェクトを作成。



src ---- greeting.main --- Main.java
     |
     |-- module-info.java

こちらのプロジェクトにもmodule-info.javaが必要。コードは以下のように書いた。

module-info.java


"requires org.hello;"の部分で利用するパッケージを指定。このように、利用したいパッケージをすべて指定していく必要がある。

greeting.main.Main.java



これを実行すると、"Hello"と出力される

greetingプロジェクトの module-info.java を書き換えてみる。"requires org.internal;"を追加。

module-info.java


greeting.main.Main.java


org.internal パッケージ配下のクラスやメソッドを使おうとしてもコンパイルエラーとなってしまって使うことができない。モジュール外部からは参照できないようになっていることが分かる。