8 Mavenを使用した実際のアプリケーションのビルド

多くの実際のアプリケーションには、様々なランタイム環境にデプロイすることを目的としたモジュールが含まれています。たとえば、Coherenceキャッシュに格納されているデータを使用するWebアプリケーションがあります。

この章では、そのようなWebアプリケーションのビルド方法について説明します。

Mavenアプリケーション例の紹介

この章でビルドするアプリケーション例では、Webページ上にユーザーのリストが名前と年齢とともに表示されます。新規個人を追加することもできます。人々の詳細はCoherenceキャッシュに格納されます。

このアプリケーションには、次の要素があります。

  • ポータブル・オブジェクトに組み込む必要があるPerson POJO (Plain Old Java Object)、キャッシュにアクセスするためのユーティリティ・クラス、およびCoherenceキャッシュ定義が含まれるCoherence GARプロジェクト。

  • サーブレットとデプロイメント・ディスクリプタが含まれた、WARに組み込む必要があるJakarta EE Webアプリケーション

  • GARおよびWARをEARにアセンブルし、そのEARをWebLogic Serverにデプロイするプロジェクト

この例では、モジュール間に依存性がある複数モジュールのMavenプロジェクトをビルドする方法、アプリケーション全体が含まれたデプロイ可能EARファイルにアプリケーション・コンポーネントをアセンブルする方法を確認できます。

この章の目的は、Mavenを使用してアプリケーション全体をビルドする方法を示すことであり、WebアプリケーションまたはCoherenceアプリケーションの記述方法をデモンストレーションすることではないため、例自体の内容は、サーブレットおよびcoherenceコードの観点から見れば非常に基本的なものです。詳しいステップについては、「Mavenを使用したWebLogic ServerのJakarta EEプロジェクトのビルド」および「Mavenを使用したOracle Coherenceプロジェクトのビルド」を参照してください。

複数モジュールのMavenプロジェクトについて

Mavenを使用すると、複数のモジュールを持つプロジェクトを作成できます。各モジュールは、別のMavenプロジェクトで有効です。最上位レベルには、モジュールに関する情報をMavenに示し、アプリケーション全体を1つのMavenコマンドでビルドできるPOMファイルがあります。

各モジュールは、最上位プロジェクトのルートのサブディレクトリに配置されます。この例では、最上位プロジェクトはmy-real-appと呼ばれ、3つのモジュールはmy-real-app-garmy-real-app-war,およびmy-real-app-earです。表8-1に、プロジェクトのMaven座標を示します。

表8-1 サンプル・アプリケーションのMaven座標およびパッケージ・タイプ

GroupId ArtifactId バージョン パッケージ化

org.mycompany

my-real-app

1.0-SNAPSHOT

pom

org.mycompany

my-real-app-gar

1.0-SNAPSHOT

gar

org.mycompany

my-real-app-war

1.0-SNAPSHOT

war

org.mycompany

my-real-app-ear

1.0-SNAPSHOT

ear

アプリケーションを構成しているファイルは、次のとおりです。



最上位レベルでは、最上位POMファイルは3つのモジュールを指しています。

  • my-real-app-garディレクトリには、Coherence GARプロジェクトが含まれています。独自のPOM、Coherence構成ファイル、POJO/POFクラス定義(Person.java)、キャッシュへのアクセスに必要なユーティリティ・クラス(CacheWrapper.java)が含まれています。

  • my-real-app-warディレクトリには、Webアプリケーションが含まれています。独自のPOM、サーブレットおよびデプロイメント・ディスクリプタが含まれています。このプロジェクトは、my-real-app-garプロジェクトに依存します。

  • my-real-app-earディレクトリには、EARファイルのデプロイメント・ディスクリプタ、およびEARをビルドおよびデプロイするためのPOMファイルが含まれています。

Mavenプロジェクトのビルド

サンプル・プロジェクトをビルドするには、ディレクトリを作成し、GAR、WARおよびEARプロジェクトを作成します。

最上位POMファイルから始める方が自然ですが、そうすると、アーキタイプを使用してプロジェクトを作成することを選択した場合に問題が発生します。そのため、個々のプロジェクトPOMファイルがそれに依存していても、最上位POMは最後に作成されます。

この項には次のトピックが含まれます:

プロジェクトのディレクトリの作成

次のコマンドを使用して、プロジェクトを保持するためのディレクトリを作成します。

mkdir my-real-app
cd my-real-app

注意:

この章の残りの部分では、このディレクトリに対する相対パスが示されます。

GARプロジェクトの作成

この項には次のトピックが含まれます:

初期GARプロジェクトの作成

Maven原型からのCoherenceプロジェクトの作成で説明しているように原型を使用するか、またはディレクトリおよびファイルを手動で作成して、GARプロジェクトを作成できます。

  • 原型を使用するには、次のコマンドを実行します。

    mvn archetype:generate
        -DarchetypeGroupId=com.oracle.coherence.archetype
        -DarchetypeArtifactId=gar-maven-archetype
        -DarchetypeVersion=14.1.2-0-0
        -DgroupId=org.mycompany
        -DartifactId=my-real-app-gar
        -Dversion=1.0-SNAPSHOT
    
  • プロジェクトを手動で作成するには、次のコマンドを使用して、必要なディレクトリを作成します。

    mkdir -p my-real-app-gar/src/main/resources/META-INF
    mkdir -p my-real-app-gar/src/main/java/org/mycompany
POMファイルの作成または変更

原型を使用する場合、POMファイルはすでに存在します。次の例に一致するようにファイルを変更します。プロジェクトを手動で作成する場合は、次の内容のPOMファイル(my-real-app-gar/pom.xml)を作成します。

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>my-real-app-gar</artifactId>
  <packaging>gar</packaging>

  <parent>
    <groupId>org.mycompany</groupId>
    <artifactId>my-real-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

  <dependencies>
    <dependency>
      <groupId>com.oracle.coherence</groupId>
      <artifactId>coherence</artifactId>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>com.oracle.coherence</groupId>
        <artifactId>gar-maven-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <generatePof>true</generatePof>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <forceCreation>true</forceCreation>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

POMファイルを調べて、ファイルの各部分について理解します。

  • Maven座標groupIdおよびversionは最上位POMから継承され、POMではartifactIdおよびパッケージ・タイプのみを指定する必要があります。Coherence GAR Mavenプラグインを使用してこのプロジェクトをCoherence GARファイルにビルドするため、パッケージ化がgarであることに注意してください。

    <artifactId>my-real-app-gar</artifactId>
    <packaging>gar</packaging>
  • 親プロジェクトの座標が設定されます。これらの座標は、最上位POMを指し示し、構成の継承を可能にします。

    <parent>
      <groupId>org.mycompany</groupId>
      <artifactId>my-real-app</artifactId>
      <version>1.0-SNAPSHOT</version>
      <relativePath>../pom.xml</relativePath>
    </parent>
  • dependenciesセクションは、このプロジェクトが持っている依存性を示しています。この場合、Coherenceライブラリ、つまりcom.oracle.coherence:coherence:14.1.2-0-0にのみ依存します。最上位POMファイルのdependencyManagementセクションから継承されたバージョンなので、依存関係宣言にバージョンを含める必要はありません。スコープprovidedは、このライブラリが単にコンパイル用であり、ランタイム環境ですでに提供されているため、ビルドするアーティファクト(GARファイル)でパッケージ化する必要がないことを意味します。

      <dependencies>
        <dependency>
          <groupId>com.oracle.coherence</groupId>
          <artifactId>coherence</artifactId>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    
  • pluginsセクションには、ビルド中に実行したいプラグインで、自動的に含まれないものや、maven-jar-pluginのように追加の設定を指定する必要があるプラグインが含まれます。この場合、generatePof trueに設定して、プラグインでPOF注釈付きPOJOが検索され、必要なアーティファクトが生成されるようにする必要があります。常にGARファイルを再生成するようにmaven-jar-pluginに指示する必要もあります。プラグインのバージョンは、最上位POMファイルのpluginManagementセクションから継承されるため、提供されないことに注意してください。

    <plugins>
      <plugin>
        <groupId>com.oracle.coherence</groupId>
        <artifactId>gar-maven-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <generatePof>true</generatePof>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <forceCreation>true</forceCreation>
        </configuration>
      </plugin>
    </plugins>
Coherenceの構成ファイルの作成または変更

GARプロジェクトに必要なCoherence構成ファイルは3つあります。原型を使用する場合、ファイルはすでに存在しますが、次の例に一致するように変更する必要があります。プロジェクトを手動で作成する場合は、次に示す場所にこれらのファイルを作成します。

my-real-app-gar/src/main/resources/META-INF/pof-config.xml
my-real-app-gar/src/main/resources/META-INF/coherence-application.xml
my-real-app-gar/src/main/resources/META-INF/cache-config.xml
  • pof-config.xmlファイルの内容を次の例に示します。

    <?xml version="1.0"?>
    <pof-config
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
            xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config coherence-pof-config.xsd">
      <user-type-list>
        <include>coherence-pof-config.xml</include>
        <user-type>
          <type-id>1001</type-id>
          <class-name>org.mycompany.Person</class-name>
        </user-type>
      </user-type-list>
    </pof-config>

    このファイルは、アーキタイプを使用して作成した場合、Personタイプを追加する必要があります。

  • coherence-application.xmlファイルの内容を次の例に示します。

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <coherence-application xmlns="http://xmlns.oracle.com/weblogic/coherence-application">
      <cache-configuration-ref>META-INF/cache-config.xml</cache-configuration-ref>
      <pof-configuration-ref>META-INF/pof-config.xml</pof-configuration-ref>
    </coherence-application>
    

    このファイルは、原型を使用して作成した場合、変更する必要がほとんどないか、またはまったくありません。

  • 原型を使用した場合、cache-config.xmlファイルを更新する必要があります。

    このファイルでは、Peopleという名前のキャッシュ、real-distributed-garという名前のキャッシュ・スキーム、およびRealDistributedCacheというサービスを作成します。これは、ローカル・バッキング・スキームを使用して自動的に開始されます。これらの用語に詳しくない場合は、Mavenを使用したOracle Coherenceプロジェクトのビルドを参照してください。ファイルの例を次に示します。

    <?xml version="1.0"?>
    <cache-config
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
        xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">
      <caching-scheme-mapping>
        <cache-mapping>
          <cache-name>People</cache-name>
          <scheme-name>real-distributed-gar</scheme-name>
        </cache-mapping>
      </caching-scheme-mapping>
    
      <caching-schemes>
        <distributed-scheme>
          <scheme-name>real-distributed-gar</scheme-name>
          <service-name>RealDistributedCache</service-name>
          <backing-map-scheme>
            <local-scheme/>
          </backing-map-scheme>
          <autostart>true</autostart>
        </distributed-scheme>
      </caching-schemes>
    </cache-config>
ポータブル・オブジェクトの作成

キャッシュに情報を格納するPersonオブジェクトを作成します。新しいJavaクラスを次の場所に作成します。

my-real-app-gar/src/main/java/org/mycompany/Person.java
クラスの内容を次に示します。
package org.mycompany;

import com.tangosol.io.pof.annotation.Portable;
import com.tangosol.io.pof.annotation.PortableProperty;

@Portable
public class Person {
  @PortableProperty(0)
  public String name;

  @PortableProperty(1)
  public int age;

  public Person() {}

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() { return this.name; }
  public int getAge() { return this.age; }
}

POJOは、このクラスで何を実行するかをCoherenceに示します。この章では、Mavenを使用したアプリケーションのビルドに焦点を当てているため、Coherenceアプリケーションの記述の詳細には触れていません。Coherenceの詳細は、Mavenを使用したOracle Coherenceプロジェクトのビルドを参照してください。

キャッシュにアクセスするためのラッパー・クラスの作成

キャッシュのアクセスに使用できる小さなラッパー・クラスを作成します。別のJavaクラスを次の場所に作成します。

my-real-app-gar/src/main/java/org/mycompany/CacheWrapper.java
クラスの内容を次に示します。
package org.mycompany;

import java.util.Map;
import java.util.Set;

import org.mycompany.Person;
import com.tangosol.net.CacheFactory;

public class CacheWrapper {
  private static CacheWrapper INSTANCE = new CacheWrapper();
  public static CacheWrapper getInstance() {
    return INSTANCE;
  }

  public Set<Map.Entry<Object, Object>> getPeople() {
    return CacheFactory.getCache("People").entrySet();
  }

  public void addPerson(int personId, String name, int age) {
    CacheFactory.getCache("People").put(personId, new Person(name, age));
  }
}

後で、このクラスをサーブレットで使用して、キャッシュからデータを取得したり、新しいデータをキャッシュに追加することができます。

WARプロジェクトの作成

この項には次のトピックが含まれます:

初期WARプロジェクトの作成

「Mavenを使用したWebLogic ServerのJakarta EEプロジェクトのビルド」で説明しているように原型を使用するか、またはディレクトリおよびファイルを手動で作成して、WARプロジェクトを作成できます。

  • 原型を使用するには、次のコマンドを実行します。

    mvn archetype:generate
      -DarchetypeGroupId=com.oracle.weblogic.archetype
      -DarchetypeArtifactId=basic-webapp
      -DarchetypeVersion=14.1.2-0-0
      -DgroupId=org.mycompany
      -DartifactId=my-real-app-war
      -Dversion=1.0-SNAPSHOT

    原型を使用する場合は、プロジェクトに含まれている不要なファイルをすべて削除する必要があります。たとえば、更新されたPOMファイルにはコンパイルに必要なすべての依存性が含まれないため、生成されたAccountBean.javaファイルを削除する必要があります。

  • プロジェクトを手動で作成するには、次のコマンドを使用して、必要なディレクトリを作成します。

    mkdir -p my-real-app-war/src/main/webapp/WEB-INF
    mkdir -p my-real-app-war/src/main/java/org/mycompany/servlets
POMファイルの作成または変更

原型を使用する場合は、POMファイルがすでに存在します。次の例に一致するようにファイルを変更します。プロジェクトを手動で作成した場合は、次の内容のPOMファイル(my-real-app-war/pom.xml)を作成します。

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>my-real-app-war</artifactId>
  <packaging>war</packaging>

  <parent>
    <groupId>org.mycompany</groupId>
    <artifactId>my-real-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>my-real-app-gar</artifactId>
      <version>${project.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

POMファイルを調べて、ファイルの各部分について理解します。

  • GARプロジェクトで確認したように、groupIdおよびversionは最上位POMファイルから継承されるため、このプロジェクトのartifactIdおよびパッケージ・タイプの座標のみを設定する必要があります。このプロジェクトのパッケージ化はwarであることに注意してください。

    <artifactId>my-real-app-war</artifactId>
    <packaging>war</packaging>
  • GARプロジェクトの場合と同様に親を定義します。

    <parent>
      <groupId>org.mycompany</groupId>
      <artifactId>my-real-app</artifactId>
      <version>1.0-SNAPSHOT</version>
      <relativePath>../pom.xml</relativePath>
    </parent>
  • このプロジェクトの依存性をリストします。この場合、2つの依存性があります(POJOおよびそこで定義されたユーティリティ・クラスにアクセスするためのGARプロジェクト、およびサーブレットAPI)。GARプロジェクトはこのサンプル・アプリケーションの一部として構築されるため、${project.groupId}および${project.version}組込みプロパティ参照を使用して、この依存関係のgroupIdおよびversionを指定します。

    <dependencies>
      <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>my-real-app-gar</artifactId>
        <version>${project.version}</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <scope>provided</scope>
      </dependency>
    </dependencies>
デプロイメント・ディスクリプタの作成

Webアプリケーションには、Webアプリケーションのdisplay-nameを設定する単純なJakarta EEデプロイメント・ディスクリプタがあります。これは、次の場所にあります。

my-real-app-war/src/main/webapp/WEB-INF/web.xml

このファイルの内容を次に示します。

<web-app version="3.1"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
  <display-name>my-real-app-war</display-name>
</web-app>
サーブレットの作成

サーブレットを作成するには、次のようにMyServlet.javaファイルを検索します。

my-real-app-war/src/main/java/org/mycompany/servlets/MyServlet.java

サーブレットでは、現在キャッシュ内に存在する個人のリストが表示され、新規個人をキャッシュに追加できます。この項の目的は、Mavenを使用してこれらのタイプのアプリケーションをビルドする方法を学習することであり、Jakarta EE Webアプリケーションの記述方法を学習することではないため、単純なサーブレットを使用しています。

サーブレット・クラスの内容を次に示します。
package org.mycompany.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;

import org.mycompany.Person;
import org.mycompany.CacheWrapper;

@WebServlet(name = "MyServlet", urlPatterns = "MyServlet")
public class MyServlet extends HttpServlet {
  protected void doPost(HttpServletRequest request,
                        HttpServletResponse response)
    throws ServletException, IOException {
    String id = request.getParameter("id");
    String name = request.getParameter("name");
    String age = request.getParameter("age");
    if (name == null || name.isEmpty() ||
        age == null || age.isEmpty() ||
        id == null || id.isEmpty()) {
      // no need to add a new entry
    } else {
      // we have a new entry - so add it
      CacheWrapper.getInstance().addPerson(Integer.parseInt(id),
        name, Integer.parseInt(age));
    }
    renderPage(request, response);
  }

  protected void doGet(HttpServletRequest request,
                       HttpServletResponse response)
    throws ServletException, IOException {
    renderPage(request, response);
  }

  private void renderPage(HttpServletRequest request,
                          HttpServletResponse response)
    throws ServletException, IOException {
    // get the data
    Set<Map.Entry<Object, Object>> people =
      CacheWrapper.getInstance().getPeople();

    PrintWriter out = response.getWriter();
    out.write("<html><head><title>MyServlet" +
              "</title></head><body>");
    out.write("<h2>Add a new person</h2>");
    out.write("<form name=\"myform\" method=\"POST\">");
    out.write("ID:<input type=\"text\" name=\"id\"/><br/>");
    out.write("Name:<input type=\"text\" name=\"name\"/><br/>");
    out.write("Age:<input type=\"text\" name=\"age\"/><br/>");
    out.write("<input type=\"submit\" name=\"submit\" " +
              "value=\"add\"/>");
    out.write("</form>");
    out.write("<h2>People in the cache now</h2>");
    out.write("<table><tr><th>ID</th><th>Name" +
              "</th><th>Age</th></tr>");
    // for each person in data
    if (people != null) {
      for (Map.Entry<Object, Object> entry : people) {
        out.write("<tr><td>" +
          entry.getKey() +
          "</td><td>" +
          ((Person) entry.getValue()).getName() +
          "</td><td>" +
          ((Person) entry.getValue()).getAge() +
          "</td></tr>");
      }
    }
    out.write("</table></body></html>");
  }
}

ユーザーがフォームにデータを入力したかどうかをチェックします。その場合は、そのデータを使用して新規個人をキャッシュに追加します。このアプリケーションでは、最小限のエラー処理しか行われないことに注意してください。新規個人をキャッシュに追加するには、GARプロジェクトで作成したCacheWrapperクラスでaddPerson()メソッドを使用します。

キャッシュの内容を表に出力します。この例では、キャッシュに含まれているエントリが十分に少ないと想定しCacheWrapperクラスのgetPeople()メソッドを使用してすべてを読み取ります。

EARプロジェクトの作成

EARプロジェクトは、EARへのWARおよびGARのアセンブルを管理します。

この項には次のトピックが含まれます:

初期EARプロジェクトの作成

次のコマンドを使用して、EARプロジェクトを手動で作成します。

mkdir -p my-real-app-ear/src/main/application/META-INF

このプロジェクトには、次の2つのファイル(POMファイルとデプロイメント・ディスクリプタ)があります。

my-real-app-ear/pom.xml
my-real-app-ear/src/main/application/META-INF/weblogic-application.xml
アプリケーション例のPOMファイルについて
POMファイルの内容を次に示します。
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>my-real-app-ear</artifactId>
  <packaging>ear</packaging>

  <parent>
    <groupId>org.mycompany</groupId>
    <artifactId>my-real-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

  <dependencies>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>my-real-app-gar</artifactId>
      <version>${project.version}</version>
      <type>gar</type>
    </dependency>
    <dependency>
      <groupId>${project.groupId}</groupId>
      <artifactId>my-real-app-war</artifactId>
      <version>${project.version}</version>
      <type>war</type>
    </dependency>
  </dependencies>

  <build>
    <finalName>my-real-app-ear</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-gar-locally</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>copy</goal>
            </goals>
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>${project.groupId}</groupId>
                  <artifactId>my-real-app-gar</artifactId>
                  <version>${project.version}</version>
                  <type>gar</type>
                </artifactItem>
              </artifactItems>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
        <configuration>
          <outputFileNameMapping>@{artifactId}@-@{version}@.@{extension}@</outputFileNameMapping>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
          </archive>
          <artifactTypeMappings>
            <artifactTypeMapping type="gar" mapping="jar"/>
          </artifactTypeMappings>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <profiles>
    <profile>
      <id>integration-test</id>
      <activation>
        <property>
          <name>skipITs</name>
          <value>false</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>com.oracle.weblogic</groupId>
            <artifactId>weblogic-maven-plugin</artifactId>
            <executions>
              <!--Deploy the application to the server-->
              <execution>
                <id>deploy for integration testing</id>
                <phase>pre-integration-test</phase>
                <goals>
                  <goal>deploy</goal>
                </goals>
                <configuration>
                  <adminurl>${wls.admin.url}</adminurl>
                  <user>${wls.admin.user}</user>
                  <password>${wls.admin.pass}</password>
                  <!--The location of the file or directory to be deployed-->
                  <source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
                  <!--The target servers where the application is deployed-->
                  <targets>${wls.ear.targets}</targets>
                  <verbose>true</verbose>
                  <name>${project.build.finalName}</name>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

POMファイルを調べて、ファイルの各部分について理解します。

  • 前のプロジェクトと同様に、artifactId、パッケージ・タイプおよび親のみを指定する必要があります。

    <artifactId>my-real-app-ear</artifactId>
    <packaging>ear</packaging>
    
    <parent>
      <groupId>org.mycompany</groupId>
      <artifactId>my-real-app</artifactId>
      <version>1.0-SNAPSHOT</version>
      <relativePath>../pom.xml</relativePath>
    </parent>
  • WARプロジェクトとGARプロジェクトの依存性が示されます。

    <dependencies>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>my-real-app-gar</artifactId>
            <version>${project.version}</version>
            <type>gar</type>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>my-real-app-war</artifactId>
            <version>${project.version}</version>
            <type>war</type>
        </dependency>
    </dependencies>
  • 2番目のプラグイン構成はmaven-dependency-pluginが対象です。GARファイルをmy-real-app-garプロジェクトの出力(ターゲット)ディレクトリからEARプロジェクトにコピーするようにこれを構成します。

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
        <execution>
          <id>copy-gar-locally</id>
          <phase>prepare-package</phase>
          <goals>
            <goal>copy</goal>
          </goals>
          <configuration>
            <artifactItems>
              <artifactItem>
                <groupId>${project.groupId}</groupId>
                <artifactId>my-real-app-gar</artifactId>
                <version>${project.version}</version>
                <type>gar</type>
              </artifactItem>
            </artifactItems>
          </configuration>
        </execution>
      </executions>
    </plugin>
  • 2番目のプラグイン構成はmaven-ear-pluginが対象です。次の例のようにartifactTypeMappingを追加して、GARファイルをJARファイルのように処理するよう指定する必要があります。

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-ear-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <addClasspath>true</addClasspath>
          </manifest>
        </archive>
        <artifactTypeMappings>
          <artifactTypeMapping type="gar" mapping="jar"/>
        </artifactTypeMappings>
      </configuration>
    </plugin>
  • profileセクションは、weblogic-maven-pluginの3番目のプラグイン構成を追加し、結果のEARファイルのデプロイ方法を示します。adminurluserpasswordおよびtargetsパラメータの値が、最上位POMファイルで定義されるプロパティに設定されていることを確認します。

    このプロファイルは、Mavenコマンド行に-DskipITs=falseを追加することでアクティブ化されます。こうすると、すべてのビルドにEARファイルをデプロイしなくても、EARファイルの構築が簡単になります。

    <profile>
      <id>integration-test</id>
      <activation>
        <property>
          <name>skipITs</name>
          <value>false</value>
        </property>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>com.oracle.weblogic</groupId>
            <artifactId>weblogic-maven-plugin</artifactId>
            <executions>
              <!--Deploy the application to the server-->
              <execution>
                <id>deploy for integration testing</id>
                <phase>pre-integration-test</phase>
                <goals>
                  <goal>deploy</goal>
                </goals>
                <configuration>
                  <adminurl>${wls.admin.url}</adminurl>
                  <user>${wls.admin.user}</user>
                  <password>${wls.admin.pass}</password>
                  <!--The location of the file or directory to be deployed-->
                  <source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
                  <!--The target servers where the application is deployed-->
                  <targets>${wls.ear.targets}</targets>
                  <verbose>true</verbose>
                  <name>${project.build.finalName}</name>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

POMプロジェクトが完了したら、デプロイメント・ディスクリプタを追加します。

アプリケーション例のデプロイメント・ディスクリプタについて

EARファイルのWebLogicデプロイメント・ディスクリプタは、次のファイルにあります。

my-real-app-ear/src/main/application/META-INF/weblogic-application.xml

内容を次に示します。

<weblogic-application>
       <module>
             <name>GAR</name>
             <type>GAR</type>
             <path>my-real-app-gar-1.0-SNAPSHOT.gar</path>
       </module>
</weblogic-application>

このデプロイメント・ディスクリプタでは、EARファイル内でGARファイルが配置されている場所、およびその呼び名に関する詳細が示されます。

最上位POMの作成

最上位POMを作成します。これは、アプリケーションのルート・ディレクトリ内のpom.xmlファイルにあり、その内容は次のとおりです。

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.mycompany</groupId>
  <artifactId>my-real-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>

    <fmw.version>14.1.2-0-0</fmw.version>
    <coherence.version>${fmw.version}</coherence.version>
    <weblogic.version>${fmw.version}</weblogic.version>

    <wls.admin.url>t3://localhost:7001</wls.admin.url>
    <wls.admin.user>weblogic</wls.admin.user>
    <wls.admin.pass>password</wls.admin.pass>
    <wls.ear.targets>AdminServer</wls.ear.targets>
  </properties>

  <modules>
    <module>my-real-app-gar</module>
    <module>my-real-app-war</module>
    <module>my-real-app-ear</module>
  </modules>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.oracle.coherence</groupId>
        <artifactId>coherence</artifactId>
        <version>${coherence.version}</version>
      </dependency>
      <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
        <version>4.0.4</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>com.oracle.coherence</groupId>
          <artifactId>gar-maven-plugin</artifactId>
          <version>${coherence.version}</version>
        </plugin>
        <plugin>
          <groupId>com.oracle.weblogic</groupId>
          <artifactId>weblogic-maven-plugin</artifactId>
          <version>${weblogic.version}</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>3.8.1</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-ear-plugin</artifactId>
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-enforcer-plugin</artifactId>
          <version>3.5.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <executions>
          <execution>
            <id>enforce-java-version</id>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <requireJavaVersion>
                  <version>[17,18),[21,22)</version>
                  <message>You must use JDK 17 or JDK 21 to build the project</message>
                </requireJavaVersion>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

プロジェクトの座標を設定します。これらは3つの各プロジェクトで指定した親座標に一致します。パッケージ化がpomであることに注意してください。これは、このプロジェクト自体がアーティファクトを作成しないことをMavenに通知します。この例では、modulesセクションで指定されているように、一連のモジュールのビルドを単純に編成します。3つのサブプロジェクトそれぞれに1つのモジュール・エントリがあります。

このPOMは他の3つの親であり、POMはそれらの親から継承されるため、共通のプロパティをこのPOMに追加でき、それらのプロパティは3つのサブプロジェクトすべてで利用できるようになります。この場合は、次の3つのセクションを追加します。
  • propertiesセクション: 現在のPOMファイルおよび任意のモジュールPOMファイルのほとんどの場所で使用できる変数を定義できます。最初の3つは、maven-compiler-pluginの構成に使用される変数です。maven-compiler-pluginを通常のプラグインとして宣言し、同じことを実現するために構成を追加することもできますが、これらのプロパティを使用すると、構成が少なくなります。Mavenのベスト・プラクティスです。

    次に、使用するOracle Fusion Middlewareのバージョンを保持するfmw.versionプロパティを定義しました。便宜上、coherence.versionおよびweblogic.versionプロパティも定義し、その値をfmw.versionプロパティの値に設定します。

    最後に、WebLogic Server URL、資格証明およびテスト対象のアプリケーションのターゲットとなる場所を指定するプロパティを定義しました。

  • dependencyManagementセクション: このセクションでは、プロジェクトおよびそのすべてのモジュールで使用される依存関係のバージョンを集中管理できます。この場合、プロジェクトにはコンパイルに必要な2つの外部依存性のみがありますが、実行時にすでに提供されています。コアCoherence依存関係およびJakarta Servlet APIです。
  • pluginManagementセクション: このセクションでは、プロジェクトおよびそのすべてのモジュールで使用されるプラグインのバージョンを集中管理できます。この例では、次のプラグインが含まれます。
    • gar-maven-plugin: Coherence GARファイルをアセンブルします
    • weblogic-maven-plugin: 統合テストのためにEARファイルをWebLogic Serverにデプロイします
    • maven-dependency-plugin: Coherence GARファイルをEARファイルに含めることができるようにコピーします
    • maven-enforcer-plugin: ビルドで互換性のあるJavaバージョンが使用されていることを確認します
    • maven-ear-plugin: Jakarta EE EARファイルをアセンブルします
    • maven-jar-plugin: Coherence GARファイルのアセンブルに参加します
    • maven-war-plugin: Jakarta EE WARファイルをアセンブルします
  • pluginセクション: このセクションでは、Maven Enforcerプラグインを構成して、ビルドがJDK 17またはJDK 21で実行されていることを確認します。

Mavenを使用したアプリケーションのビルド

これで、アプリケーションをビルドおよびデプロイする準備が整いました。Mavenを実行してアプリケーションをビルドおよびデプロイする前に、知っておかなければならないことがいくつかあります。ここでは、次の項目について説明します。

Coherenceネットワーキングについての考慮事項
デフォルトでは、Coherenceは使用する適切なネットワーク・インタフェースを選択し、IPマルチキャストを使用してクラスタを形成しようとします。一部のマシンでは、Coherenceで間違ったインタフェースが選択されているか、または選択したインタフェースがIPマルチキャストをサポートしていないとCoherenceで判断される場合があります。これにより、WebLogic Mavenプラグインのデプロイ・コマンドがタイムアウトするまでハングする可能性があります。デプロイ後、サーバーは次のようなメッセージを出力する場合もあります。
2024-11-06 18:48:27.677/52.215 Oracle Coherence GE 14.1.2.0.0 <Warning>
      (thread=Cluster, member=n/a): Delaying formation of a new cluster; multicast networking
      appears to be inoperable on interface 192.168.1.179 as this process isn't receiving even its
      own transmissions; consider forcing IPv4 via -Djava.net.preferIPv4Stack=true
このような問題が発生した場合は、この単純な例で、WebLogic Serverの起動時にJavaシステム・プロパティcoherence.wka127.0.0.1に設定する最も簡単な解決策です。これにより、Coherenceはマルチキャストのかわりにユニキャストを使用し、127.0.0.1に関連付けられたネットワーク・インタフェースを使用します。このシステム・プロパティをWebLogic Serverに渡すには、startWebLogicスクリプトを実行する前に、JAVA_OPTIONS環境変数を設定します。macOSまたはLinuxの場合、次のようにします。
export JAVA_OPTIONS="-Dcoherence.wka=127.0.0.1"
Microsoft Windowsの場合、次のようにします。
set "JAVA_OPTIONS=-Dcoherence.wka=127.0.0.1"
Maven依存性解決についての考慮事項
Mavenプロジェクトを構築する場合、Mavenが依存関係を解決する際に使用する2つの方法があります。
  • Mavenリポジトリからの依存性のフェッチ
  • マルチモジュール・ビルド内のモジュール間の依存関係の受渡し

Mavenリポジトリから依存関係をフェッチするには、依存関係がリモート・リポジトリ(Maven Centralなど)またはローカルのMavenリポジトリに存在する必要があります。ローカルのMavenリポジトリで使用できない依存関係はすべて、リモート・リポジトリからフェッチされ、ローカルのMavenリポジトリに追加されます。ビルド・アーティファクトをローカルのMavenリポジトリに配置するには、mvn installを実行するのが普通です。ローカル・リポジトリ内のすべてのアーティファクトは、制限なくMavenビルドによってフェッチできます。

この例では、3つのモジュールがあり、そのうちのいくつかはビルドの他のモジュールに依存関係があります。my-real-app-warモジュールはmy-real-app-garモジュールに依存し、my-real-app-earモジュールはmy-real-app-garmy-real-app-warの両方に依存します。my-real-app-garモジュール・アーティファクトをローカルMavenリポジトリにビルドおよびインストールする前にmy-real-app-warモジュール自体をビルドしようとすると、次のようなエラーが表示されます。
[ERROR] Failed to execute goal on project my-real-app-war: Could not resolve
      dependencies for project org.mycompany:my-real-app-war:war:1.0-SNAPSHOT: The following
      artifacts could not be resolved: org.mycompany:my-real-app-gar:jar:1.0-SNAPSHOT (absent):
      Could not find artifact org.mycompany:my-real-app-gar:jar:1.0-SNAPSHOT -> [Help
      1]
この問題を解決するには、次の2つの方法があります:
  • my-real-app-garモジュール・ディレクトリでmvn installを実行します
  • 最上位のmy-real-appディレクトリから、任意のターゲット(mvn packageなど)を使用してビルドを実行します

Mavenは、マルチモジュール・ビルドを理解し、ビルドに関する情報を様々なモジュールに渡すために使用する、Maven Reactorと呼ばれるインメモリー構造を作成します。一部は、ローカルのMavenリポジトリに存在しない可能性があるクロスモジュール依存関係を解決する方法に関する情報です。これにより、MavenはローカルMavenリポジトリにないmy-real-app-garモジュールに関するリアクタ情報を使用してmy-real-app-warモジュールをビルドできます。

Mavenの実行によるアプリケーションのビルドとデプロイ
これで、次のコマンドを(最上位ディレクトリmy-real-appで)1つ以上使用して、Mavenによるアプリケーションのビルドを実行できるようになります。
mvn compile
mvn package
mvn verify
mvn install
mvn install -DskipITs=false

Mavenでは、指定したフェーズまでのすべてのフェーズが実行されます。表8-2に、各コマンドの効果を示します。

表8-2 Mavenコマンドの効果

コマンド 詳細

mvn compile

Javaソースをターゲット・クラス・ファイルにコンパイルします。

mvn package

  1. Javaソースをターゲット・クラス・ファイルにコンパイルします。

  2. 記述した可能性のあるユニット・テストを実行します。

  3. コンパイルされたファイルおよびリソース(デプロイメント・ディスクリプタ、構成ファイルなど)を含むアーカイブ(WAR、GARなど)を作成します。

mvn verify

  1. Javaソースをターゲット・クラス・ファイルにコンパイルします。

  2. 記述した可能性のあるユニット・テストを実行します。

  3. コンパイルされたファイルおよびリソース(デプロイメント・ディスクリプタ、構成ファイルなど)を含むアーカイブ(WAR、GARなど)を作成します。

  4. WebLogic Server環境にEARファイルをデプロイします。脚注1

  5. 記述した可能性のある統合テストを実行します。

  6. 統合テスト結果があれば検証します。

mvn install

  1. Javaソースをターゲット・クラス・ファイルにコンパイルします。

  2. 記述した可能性のあるユニット・テストを実行します。

  3. コンパイルされたファイルおよびリソース(デプロイメント・ディスクリプタ、構成ファイルなど)を含むアーカイブ(WAR、GARなど)を作成します。

  4. WebLogic Server環境にEARファイルをデプロイします。脚注2

  5. 記述した可能性のある統合テストを実行します。

  6. 統合テスト結果があれば検証します。

  7. ある場合にはアーティファクトと、POMファイルをローカルのMavenリポジトリにコピーします。

脚注1 デプロイメントは、-DskipITs=false引数がMavenに渡される場合にのみ行われます。

脚注2 デプロイメントは、-DskipITs=false引数がMavenに渡される場合にのみ行われます。

通常のMavenビルドでは、-DskipITs=falseを追加しないかぎり、アプリケーションのデプロイはスキップされることに注意してください。そのため、毎回デプロイしなくてもアプリケーションを簡単に構築できます。アプリケーションが構築されて正常にデプロイされたら、アプリケーションをテストして適切に動作していることを確認します。

アプリケーションへのアクセス

アプリケーションが正常にデプロイされたら、/my-real-app-war/MyServlet URLコンテキスト・パスを使用してアプリケーションを表示します(たとえば、http://127.0.0.1:7001/my-real-app-war/MyServlet)。