Mavenをちゃんと学習する

Apache Mavenを学習

Apache MavenはPOMファイルを使用して、依存関係を簡単に追加できます。

まずはインストール

必要なものとしては、JDK(Javaを動かす&開発するため)とMaven本体です。

JDKインストール

このリンクからOpenJDK17のインストーラーがダウンロードできます。ダブルクリックでインストールできます。

Mavenのインストール

参照したサイトは本家のサイトです。
同様にMavenのリンクです。「apache-maven-3.9.6-bin.zip」がダウンロードできます。

環境変数を設定する

JDKに関しては、インストーラーを使用したので、全てインストーラーがやってくれますが。。。
Mavenに関しては手動でインストールするので次の操作が必要になります。

  1. 環境変数の設定
  2. コマンドの実行確認

1. 環境変数の設定

ダウンロードしたファイル(apache-maven-3.9.3)を、とりあえずドキュメント直下、つまりユーザーの直下に配置します。
具体的には、Takunojiユーザーの場合はC:\Users\Takunojiの下に配置します。下のようなパスになります。

C:\Users\Takunoji\apache-maven-3.9.3

そして、エクスプローラでそこからbinフォルダを開きますと下のような画面が見れます。MVNコマンドが入っています。

「bin」と書いてある部分をクリックすると「パス」が表示されるのでこれをコピーしておきます。

次に、Windowsボタンを押下

「環境変数」と入力して下のようなものを表示し、クリックします。

下のような画面が見れますので、「Path」の部分を選択して下の「編集」ボタンをクリックします。

すると、パスを入力できる場所がありますのでそこにMavenのパス+「bin」を記述します。

C:\Users\Takunoji\apache-maven-3.9.3\bin

これでOKしてからコマンドを開き

mvn -version

とコマンドを入力します。下のように表示できればOK!
※下の例はDドライブにインストールしたものなのでパスがD:¥XXXXとなっています。

単純にPOMファイルへ記述する

下のような感じでXMLを記述してMavenをリロードすればJARファイルがダウンロードできてすぐに使えます。

        <!-- Additional dependencies required to use CUDA and cuDNN -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>opencv-platform-gpu</artifactId>
            <version>4.7.0-1.5.9</version>
        </dependency>

注意点として、dependencyタグはdependenciesタグに書く必要があります。

以前、Eclipseを使用してLWJGLというライブラリをインストールしました。Mavenプロジェクトをビルドする。Maven installを実行する。複数の方法でライブラリを追加できます。

Mavenのインストール

Apacheのサイトからダウンロードした圧縮ファイルを解凍します。解凍したら環境変数PATHに追加します。

解凍したフォルダ/bin

例えば、展開したフォルダの名前が「C¥maven」の場合は次のように追加します。

WindowsでPATH追加

コマンドプロンプトを起動して次のように入力

set PATH=%PATH%;C¥maven/bin;

LinuxでPATH追加

ターミナルで次のように入力

export PATH=$PATH:解凍したフォルダまでのパス/bin;

そして、

Mavenの基本

Apache Mavenのサイトを参考にします。
このページには「5分でわかる」とか書いているけど、とりあえず動くレベルだと思う。ここから学習を始めます。

  1. コマンドプロンプトを開き、適当なフォルダに移動します。
  2. そこで次のコマンドを実行します。
    mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
  3. これでMavenプロジェクトが作成されます。

Windowsでmvnコマンドを実行する

ラズパイでmvnコマンドを実行する

こんな感じで、mvnコマンドで、プロジェクト作成などが簡単にできます。

Mavenスタートガイド

上のリンク先にはApacheのMavenプロジェクトサイトにある内容を学習します。

Mavenの主な機能

下に列挙したものが、その機能です。

  • ビルド
  • ドキュメンテーション
  • 報告
  • 依存関係
  • SCM
  • リリース
  • 分布

これらの機能を定義するのがPOMファイルです。これはProjectObjectModelの頭文字を取った感じです。

POMファイル概要

POMファイルはXMLファイルです。要素としては次のようなものがあります。

  • project: これは、すべての Maven pom.xml ファイルの最上位要素です。

project: これは、すべての Maven pom.xml ファイルの最上位要素です。

  • modelVersion: この要素は、この POM が使用しているオブジェクト モデルのバージョンを示します。モデル自体のバージョンが変更されることはほとんどありませんが、Maven 開発者がモデルを変更する必要があると判断した場合、使用の安定性を確保するために必須です。

  • groupId: この要素は、プロジェクトを作成した組織またはグループの一意の識別子を示します。groupId はプロジェクトの主要な識別子の 1 つであり、通常は組織の完全修飾ドメイン名に基づいています。たとえば、org.apache.maven.pluginsすべての Maven プラグインに指定された groupId です。

  • artifactId: この要素は、このプロジェクトによって生成されるプライマリ アーティファクトの一意のベース名を示します。プロジェクトの主な成果物は通常、JAR ファイルです。ソース バンドルなどのセカンダリ アーティファクトも、最終的な名前の一部として artifactId を使用します。Maven によって生成される一般的なアーティファクトの形式は、<artifactId>-<version>.<extension> (たとえば、myapp-1.0.jar) になります。

  • version: この要素は、プロジェクトによって生成されたアーティファクトのバージョンを示します。Maven はバージョン管理に大いに役立ち、SNAPSHOTプロジェクトが開発状態にあることを示す指定子がバージョンに表示されることがよくあります。このガイドでは、スナップショットの使用法とその仕組みについてさらに詳しく説明します。

  • name: この要素は、プロジェクトに使用される表示名を示します。これは、Maven が生成するドキュメントでよく使用されます。

  • url: この要素は、プロジェクトのサイトがどこにあるかを示します。これは、Maven が生成するドキュメントでよく使用されます。

  • properties: この要素には、POM 内のどこからでもアクセスできる値のプレースホルダーが含まれています。

  • dependency: この要素の子リストはdependency です。POM の基礎。

  • build: この要素は、プロジェクトのディレクトリ構造の宣言やプラグインの管理などを処理します。

<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>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>my-app</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

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

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
       ... lots of helpful plugins
    </pluginManagement>
  </build>
</project>

アプリケーションのコンパイル

下のコマンドをたたきます。

mvn compile

Maven はコマンドを実行するために必要なすべてのプラグインと関連依存関係をダウンロードする必要があります。Maven をクリーン インストールした場合、これにはかなりの時間がかかる場合があります。

参考サイトには上記のような記述があります。つまるところは、「mvn install」を実行すると必要なプラグインなどをインストールするので時間がかかりますが、一度ダウンロードしてしまえば、ダウンロードの時間が無くなるので素早く処理ができます。ということです。

自動テスト

テストの事項を行うのには、下のコマンドで実行します。

mvn test

テストソースのコンパイルのみを行うときは

mvn test compile

依存関係のインストールなど

mvn install

Mavenリポジトリへ作ったモノを登録

mvn deploy

プラグインの使い方

POMファイルに下のような記述をします。「のような」という記述は、使用するプラグインによ記述内容が違うためです。

...
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.3</version>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>
...

ライフサイクルについて

「ライフサイクル」という単語は、「何かしらの処理が始まって終わるまでの流れ」を示します。Mavenであれば次のようなライフサイクルがあります。

ライフサイクルのフェーズ

  • validate- プロジェクトが正しく、必要な情報がすべて利用可能であることを検証します。
  • compile- プロジェクトのソースコードをコンパイルします
  • test- 適切な単体テスト フレームワークを使用して、コンパイルされたソース コードをテストします。これらのテストでは、コードをパッケージ化またはデプロイする必要はありません。
  • package- コンパイルされたコードを取得し、JAR などの配布可能な形式にパッケージ化します。
  • verify- 統合テストの結果に関するチェックを実行して、品質基準が満たされていることを確認します
  • install- ローカルの他のプロジェクトの依存関係として使用するために、パッケージをローカル リポジトリにインストールします。
  • deploy- ビルド環境で実行され、他の開発者やプロジェクトと共有するために最終パッケージをリモート リポジトリにコピーします。
実行してみた

デプロイについて

下のように設定を記述、リポジトリの用意が必要になりそうです。「なりそう」というのは「Gitリポジトリが使用できるかどうか?はまだわからないのではっきりしない言い方をしました。

  <distributionManagement>
    <repository>
      <id>mycompany-repository</id>
      <name>MyCompany Repository</name>
      <url>scp://repository.mycompany.com/repository/maven2</url>
    </repository>
  </distributionManagement>

ビルドフェーズは、プラグインの「GOAL」で構成

プラグインは、Maven に目標を提供するアーティファクトです。

参考サイトにこうありました。つまりは、Compiler プラグインには compileとtestCompile という 2 つの目標があります。
たとえば、Modello プラグインは、デフォルトでそのゴールをフェーズ「modello : java」にバインドします generate-sources(注 : 「modello : java」ゴールは Java ソース コードを生成します)。そのため、Modello プラグインを使用してモデルからソースを生成し、それをビルドに組み込むには、次のコードを のセクションのPOM に追加します

 <plugin>
   <groupId>org.codehaus.modello</groupId>
   <artifactId>modello-maven-plugin</artifactId>
   <version>1.8.1</version>
   <executions>
     <execution>
       <configuration>
         <models>
           <model>src/main/mdo/maven.mdo</model>
         </models>
         <version>4.0.0</version>
       </configuration>
       <goals>
         <goal>java</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

POMファイル

pomファイルの基本的な記述内容です。つまりタグの意味を紹介します。

最小限のPOM定義

POM の最小要件は次のとおりです。

  • project: ルート
  • modelVersion: 最新の4.0.0に設定する必要があります
  • groupId: プロジェクトのグループの ID。
  • artifactId: アーティファクト (プロジェクト) の ID
  • version: 指定されたグループ内のアーティファクトのバージョン
<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

POMの継承

下のように書いて継承することができます。project要素の子要素です。

  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>

POMファイルの変数

次のような形で変数を使用できます。

For example, ${project.groupId}, ${project.version}, ${project.build.sourceDirectory}

それを定義するのは「properties」タグです。

<project>
  ...
  <properties>
    <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
  </properties>
  ...
</project>

特別な値もあるようです。※よくわかってないですが使えるようです。

  • project.basedir: 現在のプロジェクトが存在するディレクトリ。
  • project.baseUri: 現在のプロジェクトが存在するディレクトリ。URI として表されます。Maven 2.1.0以降
  • maven.build.timestamp: ビルドの開始を示すタイムスタンプ (UTC)。Maven 2.1.0-M1 以降

標準ディレクトリ構成

下のようになっています。

ディレクトリ名 対象
src/main/java アプリケーション/ライブラリのソース
src/main/resources アプリケーション/ライブラリのリソース
src/main/filters リソースフィルターファイル
src/main/webapp Web アプリケーションのソース
src/test/java テストソース
src/test/resources テストリソース
src/test/filters テストリソースフィルターファイル
src/it 統合テスト (主にプラグイン用)
src/assembly アセンブリ記述子
src/site サイト
LICENSE.txt プロジェクトのライセンス
NOTICE.txt プロジェクトが依存するライブラリに必要な通知と帰属
README.txt プロジェクトの Readme

最上位には、プロジェクトを説明するファイル、つまりpom.xmlファイルが表示されます。さらに、ユーザーがソースを受け取るとすぐに読めるように意図されたテキスト文書もあります: README.txt、LICENSE.txtなど。

依存関係の範囲(スコープ)

  • compile
    何も指定されていない場合に使用されます。コンパイルの依存関係は、プロジェクトのすべてのクラスパスで使用できます。さらに、それらの依存関係は依存プロジェクトに伝播されます。

  • provided
    これは によく似ていますcompileが、JDK またはコンテナが実行時に依存関係を提供することを期待していることを示します。たとえば、Java Enterprise Edition 用の Web アプリケーションを構築する場合、providedWeb コンテナがこれらのクラスを提供するため、サーブレット API および関連する Java EE API への依存関係をスコープに設定します。このスコープの依存関係は、コンパイルとテストに使用されるクラスパスに追加されますが、実行時クラスパスには追加されません。推移的ではありません。

  • runtime
    このスコープは、依存関係がコンパイルには必要ではなく、実行には必要であることを示します。Maven には、ランタイム クラスパスとテスト クラスパスにこのスコープの依存関係が含まれますが、コンパイル クラスパスには含まれません。

  • test
    このスコープは、アプリケーションの通常の使用には依存関係が必要なく、テストのコンパイルおよび実行フェーズでのみ使用できることを示します。このスコープは推移的ではありません。通常、このスコープは JUnit や Mockito などのテスト ライブラリに使用されます。また、Apache Commons IO などの非テスト ライブラリが単体テスト (src/test/java) で使用され、モデル コード (src/main/java) では使用されない場合には、これらのライブラリにも使用されます。

  • system
    このスコープは、それを含む JAR を明示的に提供する必要がある点を除けば、
    と似ています。providedアーティファクトは常に利用可能であり、リポジトリ内で検索されません。

  • import
    セクション内のタイプの依存関係でのみサポートされます。これは、依存関係が、指定された POM のセクション内の依存関係の有効なリストに置き換えられることを示します。これらは置き換えられるため、スコープが の依存関係は、依存関係の推移性の制限には実際には関与しません。

Maven エラー JavaFXのライブラリが読み込めない

Installコマンドでエラー

下のようにコマンドを入力してえらーになるケースです。

mvn install

ソースオプション

[ERROR] Source option 1.5 is no longer supported. Use 1.6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.

上のようなメッセージが出力さおうれます。
これは、pomファイルに以下のコードを追加します。「propertiesタグ」の中に追加します。

    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>

しかし、このままだと下のようなエラーメッセージが出力されます。

diamond operator is not supported in -source 6

これは、上記の値部分を「1.8」以上に設定すれば解消されます。

    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>

OpenCVライブラリが読み込めない

module-info.javaでOpenCVライブラリが読み込めないのでエラーになりました。下のようなエラー内容です。

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project pi4j-example-javafx: Compilation failure: Compilation failure: 
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[8,18] package org.opencv.core is not visible
[ERROR]   (package org.opencv.core is declared in the unnamed module, but module org.opencv.core does not read it)
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[11,26] package javafx.embed.swing does not exist
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[28,19] package javafx.fxml does not exist
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[29,18] package org.opencv.core is not visible
[ERROR]   (package org.opencv.core is declared in the unnamed module, but module org.opencv.core does not read it)
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[30,18] package org.opencv.core is not visible
[ERROR]   (package org.opencv.core is declared in the unnamed module, but module org.opencv.core does not read it)
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[45,9] cannot find symbol
[ERROR]   symbol:   class FXMLLoader
[ERROR]   location: class com.pi4j.example.HelloCV
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[45,33] cannot find symbol
[ERROR]   symbol:   class FXMLLoader
[ERROR]   location: class com.pi4j.example.HelloCV
[ERROR] /home/pi/projects/pi4j-example-javafx/src/main/java/com/pi4j/example/HelloCV.java:[51,15] cannot find symbol
[ERROR]   symbol:   class OpenCvController
[ERROR]   location: class com.pi4j.example.HelloCV
[ERROR] -> [Help 1]

Mavenで下のコマンドを実行したときに出たエラーです。

mvn package

コンパイルするときにJARファイルはインストールできているのだが、読み込めない。。。

他にも下のようなエラーが出ました。

was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]

解決

以下の原因があったようです。

  1. キャッシュが更新されていない
  2. module-infoに読み込みを書いてない
  3. javafx-fxml, javafx-swingのバージョン指定が不適切

キャッシュをクリアする

下のコマンドで再度実行

mvn -U package

これで読込は動いた

module com.pi4j.example {
    // Pi4J MODULES
    requires com.pi4j;
    requires com.pi4j.plugin.pigpio;

    // SLF4J MODULES
    requires org.slf4j;
    requires org.slf4j.simple;

    //  JavaFX
    requires transitive javafx.graphics;
    requires transitive javafx.controls;
    requires transitive javafx.fxml;
    requires transitive javafx.swing;
    requires transitive javafx.base;
    // Add Modules
    requires java.desktop;
        // 3rd-party
    requires org.bytedeco.opencv.platform;
    requires org.bytedeco.javacv.platform;

    uses com.pi4j.extension.Extension;
    uses com.pi4j.provider.Provider;

    // allow access to classes in the following namespaces for Pi4J annotation processing
    opens com.pi4j.example to com.pi4j;
    exports com.pi4j.example to javafx.graphics;
}

バージョン指定

下の部分がバージョン指定のところです。「${javafx.version}」はプロパティ要素で定義している定数です。

<version>${javafx.version}</version>

javafx-fxmlは「11」が使用できないらしい。。。

POMファイル

下記のようにPOMファイルに定義したらコンパイルできた。

        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-swing -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>17-ea+8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-base -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-base</artifactId>
            <version>${javafx.version}</version>
        </dependency>

module-info.java

/*-
 * #%L
 * **********************************************************************
 * ORGANIZATION  :  Pi4J
 * PROJECT       :  Pi4J :: EXAMPLE  :: Sample Code
 * FILENAME      :  module-info.java
 *
 * This file is part of the Pi4J project. More information about
 * this project can be found here:  https://pi4j.com/
 * **********************************************************************
 * %%
 * Copyright (C) 2012 - 2020 Pi4J
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
module com.pi4j.example {
    // Pi4J MODULES
    requires com.pi4j;
    requires com.pi4j.plugin.pigpio;

    // SLF4J MODULES
    requires org.slf4j;
    requires org.slf4j.simple;

    //  JavaFX
    requires transitive javafx.graphics;
    requires transitive javafx.controls;
    requires transitive javafx.fxml;
    requires transitive javafx.swing;
    requires transitive javafx.base;
    // Add Modules
    requires java.desktop;
        // 3rd-party
    requires org.bytedeco.opencv.platform;
    requires org.bytedeco.javacv.platform;

    uses com.pi4j.extension.Extension;
    uses com.pi4j.provider.Provider;

    // allow access to classes in the following namespaces for Pi4J annotation processing
    opens com.pi4j.example to com.pi4j;
/*    opens com.pi4j.example to javafx.graphics;
    opens com.pi4j.example to javafx.controls;
    opens com.pi4j.example to javafx.fxml;
    opens com.pi4j.example to javafx.swing;
    opens com.pi4j.example to javafx.base; */
}