#chiroito ’s blog

Java を中心とした趣味の技術について

IntelliJ IDEA と WebLogic Server で Java EE 開発

IntelliJ IDEA と Oracle WebLogic Server を使用して Java EE の Web アプリケーションを開発するまでの手順です。最後に開発時間を短縮する Tips もあります。

前提条件

Oracle WebLogic Server 12.2.1.2.0 (以降 WebLogic Server)のインストールと構成ウィザード(config.cmd)を使用してドメインの作成が完了している必要があります。 インストールと構成ウィザードの手順はこちらにまとまってます。
Oracle WebLogic Server 12c管理のための5つのポイント

必要な情報

WebLogic Serverのインストール時と構成ウィザード実行時に入力した下記の情報が必要です。

  • インストール時に指定した Oracle ホーム (今回の例ではC:\Oracle\Middleware\fm12212)
  • 構成ウィザードで指定したドメインの場所 (今回の例ではC:\Oracle\Middleware\fm12212\user_projects\domains\intellij_domain)
  • 構成ウィザードで指定した名前 (今回の例ではweblogic)
  • 構成ウィザードで指定したパスワード (今回の例では具体的な値は出てきません。)

手順

必要な手順は以下の 3 つだけです。

  1. 実行環境の登録
  2. アプリケーションの作成
  3. Run/Debug の設定

1. 実行環境の登録

はじめに、IntelliJ IDEA に実行環境として WebLogic Server を登録します。

[File]-[Settings]を選択して[Settings]ダイアログを表示します。左側のメニューで[Build, Execution, Development]-[Application Servers] と選択すると下図の画面が表示されます。

f:id:chiroito:20170201182913p:plain

上の[]ボタンを選択すると様々なアプリケーションサーバがリスト形式で表示されます。その中から[WebLogic Server] を選択すると、WebLogic Server のダイアログが表示されます。
※ リストに WebLogic Server が無い場合には WebLogic Integration プラグインをインストールして下さい。

f:id:chiroito:20170201183029p:plain

WebLogic Home はインストール時に指定した[Oracle ホーム]を指定します。これを指定するとWebLogic Version は自動で設定されるので、[OK]ボタンを押します。先ほどの画面に設定が反映され、バージョンにあわせた名前が設定されます。

f:id:chiroito:20170201183145p:plain

実行環境の登録はこれで終わりなので[OK]ボタンを押します。

2. アプリケーションの作成

[File]-[New]-[Project…]を選択して[New Project]ダイアログを表示します。

f:id:chiroito:20170201200038p:plain

[Java Enterprise]を選択すると、Project SDK (JDK) 、Java EE のバージョン、アプリケーションサーバが選択できます。JDKは Java SE 8、Java EE は 7 を指定し、アプリケーションサーバは先ほど登録したものを選択します。 今回は Webアプリケーションを作成するので アプリケーションライブラリとフレームワークは [Web Application]を選択します。 [Next]を押すとプロジェクトの名前や保存先を指定します。プロジェクトの名前は SampleWebAppとして保存先は任意の場所を指定します。

3. Run/Debug の設定

最後に、作成したアプリケーションを動かしましょう。アプリケーションサーバを起動する設定のために[Run]-[Edit Configurations…]を選択して[Run/Debug Configurations]ダイアログを表示します。

f:id:chiroito:20170201182501p:plain

アプリケーションを作成するときに WebLogic Server を指定したので、左側のメニューに登録した名前と同一の WebLogic Server が作られ、いくつか設定されていますのでこれを選択します。

f:id:chiroito:20170201201229p:plain

ここでは Userに構成ウィザードで指定した名前、Passwordに構成ウィザードで指定したパスワードを入力します。Domain Pathに構成ウィザードで指定したドメインの場所を選択します。

[Deployment] タブでアプリケーションがデプロイされる設定になっていることを念のため確認しましょう。 f:id:chiroito:20170201200822p:plain

[OK]を押して反映した後は他のアプリケーション同様に起動やデバッグをすると WebLogic Server が起動します。

Tips

アプリケーション開発中はソースファイルを変更しては反映する作業が多くあります。WebLogic Server はホットデプロイに対応しているので、再起動無しに最新のクラスファイルをリロードできます。

ソースコードを修正後に[Build]-[Build Project]などでビルドするとと変更されたクラスファイルを直ぐにリロードするかをダイアログに問われます。[Yes] を選択することでリロードされます。

f:id:chiroito:20170201201739p:plain

反映が成功すると下の方に緑色の表示があります。

f:id:chiroito:20170201201904p:plain

アプリケーションを再起動しないと反映できないものがいくつかあります。この様な場合には、緑色ではなく赤色の表示で反映に失敗した旨表示されます。その場合には Ctrl+F10で再デプロイすると WebLogic Server 自体は再起動せず、アプリケーションだけ更新できます。

f:id:chiroito:20170201202011p:plain

Oracle 公式の Docker レジストリからイメージを pull

Oracle 公式の Docker レジストリには、Oracle WebLogic Server、Oracle JDK、Oracle Database、MySQL などの Oracle 製品がインストールされたイメージがあります。これらの公式イメージは Oracle 社のシングルサインオンアカウントを登録するだけで使用できます。

注:日本国内からはまだ利用できません。US、UK、オーストラリアに在住の方は利用できます。(2017年1月31日現在)
日本からも利用できるようになりました。(2017年5月現在)

ブラウザで以下の URL から Oracle Container Registry へアクセスし、サインインします。アカウントを Docker リポジトリと紐付ける画面になりますので、紐付けましょう。紐付けが完了した後に再度アクセスすると用意されているイメージのリストが見られるようになります。
Oracle Container Registry: Login

シングルサインオンのアカウントである Oracle.comプロファイルを新規作成するには以下の URL から作成できます。
Oracle | Create Account
不明点がある場合はこちらを参考にして下さい。
Oracle.comプロファイルについて

紐付けが完了すると、次のように docker コマンドでリポジトリにログインして、イメージを pull できるようになります。

c:\>docker login container-registry.oracle.com
Username: <登録したメールアドレス>
Password: <登録したパスワード>
Login Succeeded

c:\>docker pull container-registry.oracle.com/java/serverjre:latest
latest: Pulling from java/serverjre
67d242720c3e: Pull complete
23eaae4f2427: Pull complete
Digest: sha256:2af18347c9e283e8279e58ea2c8af59268d12b8800f7b7b8c4ca356eb884503f
Status: Downloaded newer image for container-registry.oracle.com/java/serverjre:latest

c:\>docker images
REPOSITORY                                     TAG          IMAGE ID            CREATED             SIZE
container-registry.oracle.com/java/serverjre   latest       4455f4c1edff        6 days ago          382.2 MB

Oracle WebLogic Server や Oracle Database が簡単に使えるようになりますので、Java EE や Oracle Master などの学習にお役立て下さい。

IntelliJ IDEA で CDI をデバッグする時の落とし穴

IntelliJ IDEA (以下 IntelliJ) を使用して CDI 実装の1つである Weld を使用したアプリケーションを開発している人は多いかと思います。 テストフェーズでは、テストが上手くいかず、原因を特定するためにデバッグ実行をして動きをステップ毎に確認することも多いと思います。しかしながら Weld はブレークポイントの入れ方次第で動作が大きく変わる事に注意が必要です。

今回は CDI の実装として Weld の 1.1 系と 2.3 系で確認してます。

問題が分かる例として次のような RequestScoped な Bean である HelloBean とサーブレットである HelloServlet を処理するとします。HelloBean はクラスフィールドとして作成したオブジェクトの数を保持し、オブジェクトが生成されると 1 つ加算し、オブジェクトが破棄されると 1 つ減算します。
※今回は AP サーバのスレッドを 1 つにして処理するため同期処理は気にしていません。

@RequestScoped
public class HelloBean {
    private static int OBJECT_NUM = 0;

    @PostConstruct
    public void init() {
        OBJECT_NUM++
    }

    @PreDestroy
    public void destroy() {
        OBJECT_NUM ++;
    }

    public String hello() {
        return "Hello";
    }
}

HelloServlet は HelloBean をインジェクトします。doGet メソッドは HelloBean オブジェクトが null かどうか確認し、HelloBean オブジェクトの hello メソッドを実行し、その前後で作成された HelloBean の数を出力します。

@WebServlet(name = "Hello", urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {

    @Inject
    private HelloBean bean;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        res.getWriter().println("<html><body>");
        res.getWriter().println("HelloBean is " + ((this.bean == null) ? "" : "not") + " null<br/>");
        res.getWriter().println("HelloBean count is " + HelloBean.OBJECT_NUM  + "<br/>");
        res.getWriter().println(this.bean.hello() + "<br/>");
        res.getWriter().println("HelloBean count is " + HelloBean.OBJECT_NUM  + "<br/>");
        res.getWriter().println("</body></html>");
    }
}

この時、出力される結果はどうなるでしょうか?
HelloBean クラスのオブジェクトがインジェクトされているため、bean フィールドは null にはならず、OBJECT_NUM の数は 0 から 1 に増加していると考えるかと思います。
実際に出力されるコードは以下の通り、1 回目の OBJECT_NUM は 0 になります。

HelloBean is not null
HelloBean count is 0
Hello
HelloBean count is 1

この理由は、@Inject で渡されるオブジェクトが HelloBean クラスのプロキシであり、HelloBean オブジェクトではないためです。プロキシ先となる HelloBean のオブジェクトは HelloBean が持っている特定のメソッドが初めて呼ばれたタイミングでが作られます。特定のメソッドは HelloBean クラスが持つメソッドと toString() メソッドです。
IntelliJ では、デバッグをしながら実行すると、以下のようにコードの右側にオブジェクトの toString() メソッドの結果が出力されます。

f:id:chiroito:20170131010326p:plain

そのため、IntelliJ で Weld をデバッグしながら実行すると toString() メソッドが呼ばれたタイミングでオブジェクトが生成されるため、デバッグをしていない時と動きが変わってしまいます。

HelloBean is not null
HelloBean count is 1
Hello
HelloBean count is 1

今回のサンプルではブレークポイントが 1 つ下の行だった場合には動きに差はありません。ですが、実際のアプリケーションではどこに問題があるかを特定するのはすごく難しいでしょう。