2020年6月9日火曜日

Maven + Java14 + JavaFX14 + jpackage で Hello, World をパッケージ化する

前提

プロジェクト作成から実行まで

プロジェクトテンプレート作成

> cd ${WORK_DIR}
> mvn archetype:generate
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] No archetype defined. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)
Choose archetype:
1: remote -> am.ik.archetype:elm-spring-boot-blank-archetype (Blank multi project for Spring Boot + Elm)
2: remote -> am.ik.archetype:graalvm-blank-archetype (Blank project for GraalVM)
...(snip)
2332: remote -> org.openjfx:javafx-archetype-fxml (-)
2333: remote -> org.openjfx:javafx-archetype-simple (-)
...(snip)
2720: remote -> xyz.luan.generator:xyz-generator (-)
2721: remote -> za.co.absa.hyperdrive:component-archetype (-)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1615: 2332
Choose org.openjfx:javafx-archetype-fxml version:
1: 0.0.1
2: 0.0.2
3: 0.0.3
4: 0.0.4
5: 0.0.5
Choose a number: 5:
Define value for property 'groupId': jp.dip.oyasirazu.study.javafx.helloworld
Define value for property 'artifactId': helloworld
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' jp.dip.oyasirazu.study.javafx.helloworld: :
[INFO] Using property: javafx-maven-plugin-version = 0.0.4
[INFO] Using property: javafx-version = 13
Confirm properties configuration:
groupId: jp.dip.oyasirazu.study.javafx.helloworld
artifactId: helloworld
version: 1.0-SNAPSHOT
package: jp.dip.oyasirazu.study.javafx.helloworld
javafx-maven-plugin-version: 0.0.4
javafx-version: 13
 Y: :
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: javafx-archetype-fxml:0.0.5
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: jp.dip.oyasirazu.study.javafx.helloworld
[INFO] Parameter: artifactId, Value: helloworld
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: jp.dip.oyasirazu.study.javafx.helloworld
[INFO] Parameter: packageInPathFormat, Value: jp/dip/oyasirazu/study/javafx/helloworld
[INFO] Parameter: package, Value: jp.dip.oyasirazu.study.javafx.helloworld
[INFO] Parameter: groupId, Value: jp.dip.oyasirazu.study.javafx.helloworld
[INFO] Parameter: javafx-version, Value: 13
[INFO] Parameter: artifactId, Value: helloworld
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: javafx-maven-plugin-version, Value: 0.0.4
[INFO] Project created from Archetype in dir: C:\Users\mikoto\project\tmp\HelloWorld\helloworld
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:23 min
[INFO] Finished at: 2020-06-09T03:13:56+09:00
[INFO] ------------------------------------------------------------------------

> cd helloworld
  • 2332: remote -> org.openjfx:javafx-archetype-fxml (-) : これが FXML を使った JavaFX アプリテンプレート
  • Choose org.openjfx:javafx-archetype-fxml version: : とりあえず最新版を選択
  • Define value for property 'groupId': jp.dip.oyasirazu.study.javafx.helloworld : グループ ID。パッケージ名に使われる。
  • Define value for property 'artifactId': helloworld : アプリ名。 jar ファイルに使われる。
  • Define value for property 'version' 1.0-SNAPSHOT: : : アプリバージョン番号。 デフォルトだと jar ファイル名に追加される。

${WORK_DIR}/helloworld に Maven プロジェクトが作成される。

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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>jp.dip.oyasirazu.study.javafx.helloworld</groupId>
    <artifactId>helloworld</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>14</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>14</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <release>14</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.5</version>
                <configuration>
                    <mainClass>jp.dip.oyasirazu.study.javafx.helloworld.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • maven.compiler.source : 14 へ修正
  • maven.compiler.target : 14 へ修正
  • javafx-controls : version を 14 へ修正
  • javafx-fxml : version を 14 へ修正
  • maven-compiler-plugin : configuration/release を 14 へ修正
  • javafx-maven-plugin : version を 0.0.5 へ修正

コンパイル・ jar の作成

以下コマンドでコンパイルと jar 作成まで行われる。

mvn package

.\target\helloworld-1.0-SNAPSHOT.jar に jar が生成される。

コンパイルだけなら mvn compile。

とりあえず実行

java -p ".\target\helloworld-1.0-SNAPSHOT.jar;$Env:JAVAFX_HOME\lib" -m "jp.dip.oyasirazu.study.javafx.helloworld/jp.dip.oyasirazu.study.javafx.helloworld.App"
図 1: テンプレートで生成されるアプリ

ボタンを押すたびに View が切り替わるアプリ。

最小構成 JRE 生成

依存モジュールを確認

jdeps で依存モジュールを確認。

> $DEPS = jdeps --print-module-deps --ignore-missing-deps --module-path "$Env:JAVAFX_HOME\lib" .\target\helloworld-1.0-SNAPSHOT.jar
> echo $DEPS
java.base,javafx.fxml,javafx.graphics

最小構成 JRE を作成

jlink で最小構成 JRE を生成する。

> jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules $DEPS,jdk.charsets,jdk.localedata,jp.dip.oyasirazu.study.javafx.helloworld --include-locales=ja --module-path ".\target\helloworld-1.0-SNAPSHOT.jar;$Env:JAVAFX_HOME\jmods" --output "./release/app" --launcher helloworld="jp.dip.oyasirazu.study.javafx.helloworld/jp.dip.oyasirazu.study.javafx.helloworld.App"

.\release\app に最小構成 JRE が生成され、.\release\app\bin\helloworld.bat にランチャーが生成される。

最小構成 JRE で実行してみる

.\release\app\bin\helloworld.bat

OK, うごいた。

パッケージング

jpackage でパッケージ化

jpackage -n helloworld --app-image ./release/app --dest ./release/package --vendor "mikoto2000" --win-dir-chooser
  • -n: アプリケーション名
  • --app-image: アプリイメージ。 jlink で作ったディレクトリを指定する
  • --dest: 出力先ディレクトリ。このディレクトリに [アプリケーション名].exe が生成される
  • --vendor: Windows だと入れないとエラーになるようだ
  • --win-dir-chooser: ユーザーにインストール場所を選択させるためのフラグ

.\release\package\helloworld-1.0.exe にインストーラーが生成される。

インストール手順はインストール - jpackage を使って HelloWorld をパッケージ化する - mikoto2000 の日記を参照。

以上。

参考資料

2020年5月24日日曜日

jpackage を使って HelloWorld をパッケージ化する

前提

  • OS: Windows 10 Pro
  • Java: openjdk version "14.0.1" 2020-04-14
  • Gradle: Gradle 6.4.1

Java, Gradle にパスを通しておくこと。

プロジェクトの準備

プロジェクトのひな形作成

gradle init で Java プロジェクトを作る。

> gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4] 4

Project name (default: first_step):
Source package (default: first_step): jp.dip.oyasirazu.study.java14.first_step

> Task :init
Get more help with your project: https://docs.gradle.org/6.4.1/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL in 1m 5s
2 actionable tasks: 2 executed

試しに実行

> .\gradlew run
Downloading https://services.gradle.org/distributions/gradle-6.4.1-bin.zip
.........10%..........20%..........30%..........40%.........50%..........60%..........70%..........80%.........90%..........100%

> Task :run
Hello world.

BUILD SUCCESSFUL in 34s
2 actionable tasks: 2 executed

> .\gradlew test

BUILD SUCCESSFUL in 15s
3 actionable tasks: 2 executed, 1 up-to-date

module-info.java 作成

./src/main/java/module-info.java に以下ファイルを作成。

module main {
}

ビルド。

.\gradlew.bat build

Java アプリケーションのパッケージング

WIX Toolset のインストール

WiX Toolset をインストールする。

今回は Chocolatey Software | WiX Toolset 3.11.2 でインストール。

choco install wixtoolset

最小ランタイム作成

ビルドしてランチャー付き最小ランタイムを作成。

jlink --compress 2 --strip-debug --no-header-files --no-man-pages --module-path ./build/libs/first_step.jar --add-modules main --output ./release/app --launcher first_step=main/jp.dip.oyasirazu.study.java14.first_step.App

./release/app に生成される。

インストーラー作成

jpackage -n first_step --app-image ./release/app --dest ./release/package --vendor "mikoto2000" --win-dir-chooser
  • -n: アプリケーション名
  • --app-image: アプリイメージ。 jlink で作ったディレクトリを指定する
  • --dest: 出力先ディレクトリ。このディレクトリに [アプリケーション名].exe が生成される
  • --vendor: Windows だと入れないとエラーになるようだ
  • --win-dir-chooser: ユーザーにインストール場所を選択させるためのフラグ

./release/package/first_step-1.0.exe が生成される。

インストール

./release/package/first_step-1.0.exe をダブルクリックするとインストーラーが起動するのでインストールする。

  1. インストールウィザードが開くので Next ボタン押下
  2. インストールディレクトリを選択して Next ボタン押下
  3. Install ボタン押下
  4. Finish ボタン押下

実行

[インストールディレクトリ]/bin にパスを通して実行する。

> $Env:Path='C:\Program Files\first_step\bin\;'+$Env:Path
> first_step.bat
Hello world.

以上。

参考資料

2020年5月11日月曜日

自己証明書と nip.io を使って Eclipse Che を HTTPS 化する

ワンショットのデモをやることになったので、環境構築手順をメモ。

各種資材は 2019 年 10 月ごろのものなので最新化しなきゃ…

前提

Azure へログイン

PowerShell で mikoto2000/aks-tools イメージを起動。

mikoto2000/aks-tools コンテナ内でで Azure へログインする。

URL と code が表示される。Web ブラウザで表示された URL にアクセスし、 表示されたページのコード入力欄に code を入力。

Kubernetes クラスタ作成

mikoto2000/aks-tools コンテナ内ででクラスタを作成する。

Ingress デプロイ

ingress-nginx の LoadBalancer に EXTERNAL-IP が割り当てられるまで待つ。

Ingress の公開 IP アドレスをメモ。

証明書作成

下準備

mikoto2000/openssl を使用して証明書を作成。

コンテナ内で証明書作成

# 必要な情報整理

## ドメイン定義
DOMAIN_IP="20.37.126.225"
DOMAIN="$(echo ${DOMAIN_IP} | sed -e "s/\./-/g").nip.io"

## SAN 設定作成
echo "subjectAltName = @alt_names" >> ./usr_lib_ssl/v3.txt
echo "" >> ./usr_lib_ssl/v3.txt
echo "[ alt_names ]" >> ./usr_lib_ssl/v3.txt
echo "DNS.1 = "'*'".${DOMAIN}" >> ./usr_lib_ssl/v3.txt

## 各種生成物定義
CA_KEY_FILE="/ca/private/cakey.pem"
CA_CSR_FILE="/ca/ca.csr"
CA_CRT_FILE="/ca/cacert.pem"

CA_COUNTRY="JP"
CA_STATE="KEN"
CA_LOCALITY="KU"
CA_ORGANIZATION="KOJIN"
CA_ORGANIZATION_UNIT="NONE"
CA_COMMON="${DOMAIN}"
CA_EMAIL="mikoto2000@gmail.com"


# CA 初期化
cd /ca

## 各種ディレクトリ作成
mkdir cert private crl newcerts
chmod 700 private

## シリアル初期化
echo "01" | tee -a serial

## crlnumber 初期化
echo "01" | tee -a crlnumber

## インデックス初期化
touch index.txt
echo "unique_subjec = yes" > index.txt.attr


# CA 鍵と CA 証明書作成

## CA 用秘密鍵作成
openssl genrsa -out ${CA_KEY_FILE} 2048

## CA 証明書要求作成
CA_SUBJECT="/C=${CA_COUNTRY}/ST=${CA_STATE}/L=${CA_LOCALITY}/O=${CA_ORGANIZATION}/OU=${CA_ORGANIZATION_UNIT}/CN=${CA_COMMON}"
openssl req -new -key ${CA_KEY_FILE} -out ${CA_CSR_FILE} -subj "${CA_SUBJECT}"

## CA 証明書要求確認
openssl req -noout -text -in ${CA_CSR_FILE}

## CA 証明書作成
openssl x509 -req -in ${CA_CSR_FILE} -signkey ${CA_KEY_FILE} -out ${CA_CRT_FILE} -extfile /usr/lib/ssl/v3_ca.txt

## CA 証明書確認
openssl x509 -text -noout -in ${CA_CRT_FILE}

## CA 証明書を out ディレクトリへコピー
cp ${CA_CRT_FILE} /client/ca.crt


# サーバー証明書発行
SERVER_COMMON="${DOMAIN}"
SERVER_KEY_FILE="/client/${SERVER_COMMON}.key"
SERVER_CSR_FILE="/client/${SERVER_COMMON}.csr"
SERVER_CRT_FILE="/client/${SERVER_COMMON}.crt"

SERVER_COUNTRY="JP"
SERVER_STATE="KEN"
SERVER_LOCALITY="KU"
SERVER_ORGANIZATION="KOJIN"
SERVER_ORGANIZATION_UNIT="NONE"
SERVER_COMMON="${DOMAIN}"
SERVER_EMAIL="mikoto2000@gmail.com"

## サーバー秘密鍵作成
openssl genrsa -out ${SERVER_KEY_FILE} 2048

## サーバー証明書要求作成
SERVER_SUBJECT="/C=${SERVER_COUNTRY}/ST=${SERVER_STATE}/L=${SERVER_LOCALITY}/O=${SERVER_ORGANIZATION}/OU=${SERVER_ORGANIZATION_UNIT}/CN=${SERVER_COMMON}"
openssl req -new -key ${SERVER_KEY_FILE} -out ${SERVER_CSR_FILE} -subj "${SERVER_SUBJECT}"

## クライアント証明書要求確認
openssl req -noout -text -in ${SERVER_CSR_FILE}


# サーバー証明書作成
cd /client
yes | openssl ca -out ${SERVER_CRT_FILE} -extfile /usr/lib/ssl/v3.txt -infiles ${SERVER_CSR_FILE}

※ DOMAIN_IP: mikoto2000/aks-tools でメモした EXTERNAL-IP

Kubernetes に証明書を設定

mikoto2000/aks-tools コンテナ内での作業。

デプロイ

ソースコード取得

tiller のインストール

che デプロイ

devfile-registry の修正

quay.io/eclipse/che-devfile-registry:nightly -> mikoto2000/che-devfile-registry:ET2019.

plugin-registry の修正

quay.io/eclipse/che-plugin-registry:nightly -> mikoto2000/che-plugin-registry:ET2019.

デプロイ

che-plugin-registry と che-devfile-registry が 7.4.0 向けなので che-server もそれに合わせる。

動作確認

  1. 作成した ca.crt をブラウザにインポート
  2. https://che-keycloak.$DOMAIN へ接続して管理者設定・ユーザー追加
  3. https://che-che.$DOMAIN へ接続してログイン

余裕があったら別記事で手順を書く。

後片付け

mikoto2000/aks-tools で以下コマンドを実行。

以上。