タイガー!タイガー!じれったいぞー!(SE編)

AS400, Java, JavaEE, JSF等の開発、習慣など。日々の気づきをまとめたブログ(備忘録)

【シェルスクリプト】Javaクラスの実行結果を取得する方法

Linuxのシェルスプリプトでは、Javaの実行結果(System.exit)の値を取得できることが今回、わかりました。

以前に作成した「Test.jarファイル」を使用して、クラスの実行結果を取得するシェルスプリプトを書いてみました。

tigertaizo.hatenablog.com

サンプル・コード

/home/tigertaizo/Test.sh

vim /home/tigertaizo/Test.sh

#!/bin/bash

PGM_NAME=Test01
java tigertaizo.$PGM_NAME
RETURN_CODE=$?
echo $RETURN_CODE
if [ $RETURN_CODE = 0 ]; then
   echo "${PGM_NAME}-正常終了"
else
   echo "${PGM_NAME}-異常終了"
fi

作成しましたら、実行権限を付加します。

$ chmod +x Test.sh

実行結果

(1) PGM_NAME=Test01

$ ./Test.sh
run Test01#main.
Test01は、正常終了しました。
0
Test01-正常終了

(2) PGM_NAME=Test02

$ ./Test.sh
run Test02#main.
Test02は、異常終了しました。
1
Test02-異常終了

(3) PGM_NAME=Test03

guavaがクラスパスに通っている場合
$ ./Test.sh
run Test03#main.
文字列sは、null または 空白です。
0
Test03-正常終了
guavaがクラスパスに通っていない場合
$ ./Test.sh
run Test03#main.
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Strings
        at tigertaizo.Test03.main(Test03.java:9)
Caused by: java.lang.ClassNotFoundException: com.google.common.base.Strings
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 1 more
1
Test03-異常終了

(4) PGM_NAME=Test04

$ ./Test.sh
run Test04#main.
Exception in thread "main" java.lang.NullPointerException
        at tigertaizo.Test04.main(Test04.java:6)
1
Test04-異常終了

基本的なことなんでしょうが、シェルからJavaの実行結果を取得できることで、実現できることの幅が広がるように感じました。

【Eclipse】JARファイルのエクスポート/実行確認(Gradleプロジェクト編)

またまたJARファイルの実験ということで。

これまでの実験結果はこちら。

今度は、Elipseで、Gradleプロジェクトを作成してみました。

プロジェクト作成

f:id:no14141:20150530172057j:plain

f:id:no14141:20150530172102j:plain

クラスについては、前回同様です。

プロジェクト構成は、下記の通りです。

f:id:no14141:20150530172108j:plain

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'

sourceCompatibility = 1.8
targetCompatibility = 1.8
jar.baseName = 'test'
version = '1.0'

repositories {
  mavenCentral()
}
    
dependencies {
  compile 'com.google.guava:guava:18.0'
  testCompile group: 'junit', name: 'junit', version: '4.+'
}

test {
  systemProperties 'property': 'value'
}

jar {
  manifest {
    attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    attributes "Main-Class" : "tigertaizo.Test03"
  }
  from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}

JARファイルの作成

gradleに関する知識が乏しいので、間違っているかもしれませんが、「clean」タスク実行後、「build」タスクを実行してみました。

f:id:no14141:20150530172116j:plain

build時のログ

[sts] -----------------------------------------------------
[sts] Starting Gradle build for the following tasks: 
[sts]      :build
[sts] -----------------------------------------------------
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 6.146 secs
[sts] -----------------------------------------------------
[sts] Build finished succesfully!
[sts] Time taken: 0 min, 6 sec
[sts] -----------------------------------------------------

成功しました!

すると、「PROJECT_HOME/build/libs」の中に、「test-1.0.jar」ができているではありませんか!!

f:id:no14141:20150530172124j:plain

JARファイル実行テスト

さあ、出来立てのJARファイルをLinuxへ! JARを配備し、パスを通して、クラス1~4を実行!! すべてオッケー!!!
Gradle最高すぎ!!!!

$ vim ~/.bash_profile
CLASSPATH=/home/tigertaizo/lib/test-1.0.jar:.
export CLASSPATH=$CLASSPATH

$ source ~/.bash_profile

$ echo $CLASSPATH
/home/tigertaizo/lib/test-1.0.jar:.

$ java tigertaizo.Test01
run Test01#main.
Test01は、正常終了しました。

$ java tigertaizo.Test02
run Test02#main.
Test02は、異常終了しました。

$ java tigertaizo.Test03
run Test03#main.
文字列sは、null または 空白です。

$ java tigertaizo.Test04
run Test04#main.
Exception in thread "main" java.lang.NullPointerException
        at tigertaizo.Test04.main(Test04.java:6)

最後に、gradleのビルド処理でできたJARを展開してみました。

test-1.0.jar
│  
├─com
│  └─google
│     (※中身は省略)
│     
│                  
├─META-INF
│  │  MANIFEST.MF
│  │  
│  └─maven
│      └─com.google.guava
│          └─guava
│                  pom.properties
│                  pom.xml
│                  
└─tigertaizo
        Test01.class
        Test02.class
        Test03.class
        Test04.class
MANIFEST.MF
Manifest-Version: 1.0
Implementation-Title: Gradle Quickstart
Implementation-Version: 1.0
Main-Class: tigertaizo.Test03

下記の設定では、Extract required libraries into generated JAR(生成されるJARに必須ライブラリーを抽出)になるようです。

from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }

今回は、JARの取り出しや配備は、手作業でやりましたが、実際にはuploadArchivesタスクなどで自動化できそうです。そちらについては、また別の機会にトライしたいと思います。

【Eclipse】実行可能なJARファイルのエクスポート/実行確認(Javaプロジェクト編)

前回の続きです。

前回の実験では、外部クラスへの参照があるクラスを実行した場合に、NoClassDefFoundErrorになってしまったわけですが、外部クラスを使わずにコーディングするのは無謀でしょう。「車輪の再発明」したくないですし。。。

というわけで、今度は実行可能なJARファイルを使ってテストしてみました。

使用したJavaプロジェクトは、前回とまったく同じものです。

JARファイルの作成

エクスポートを選択し、今度は「Runnable JAR File」をチョイス!

f:id:no14141:20150530163751j:plain

Launch configurationに指定したクラスが、jarオプションで実行した際に実行されるクラスになるようです。

f:id:no14141:20150530163758j:plain

これで、デスクトップに「Test_runnable.jar」が生成されました。

JARファイル実行テスト

(1)JARファイルの配備

先のJARを次の場所に設置(ちなみに前回のJARやクラスパス設定はすべて消去しました)

/home/tigertaizo/lib/Test_runnable.jar

(2)クラスパスの登録

自分のユーザー環境のプロファイルにクラスパスを登録します。

$ vim ~/.bash_profile

CLASSPATH=/home/tigertaizo/lib/Test_runnable.jar:.
export CLASSPATH=$CLASSPATH

即、設定を反映し、環境変数を確認します。

$ source .bash_profile
$ echo $CLASSPATH
/home/tigertaizo/lib/Test_runnable.jar:.

パスが通りました。

(3)実行

Javaコマンドで4つのクラスを実行してみました。

$ java tigertaizo.Test01
run Test01#main.
Test01は、正常終了しました。

$ java tigertaizo.Test02
run Test02#main.
Test02は、異常終了しました。

$ java tigertaizo.Test03
run Test03#main.
文字列sは、null または 空白です。

$ java tigertaizo.Test04
run Test04#main.
Exception in thread "main" java.lang.NullPointerException
        at tigertaizo.Test04.main(Test04.java:6)

今度は、すべて想定通りに動かせましたね。

JARエクスポートの設定で、Launch configurationをTest03に設定したものを-jarオプションで実行しても、問題ないことが確認できました!

$ java -jar ~/lib/Test_runnable.jar
run Test03#main.
文字列sは、null または 空白です。

これで、JARファイルについて、だいぶ理解が深まりました。

最後に、エクスポート設定で、「Library handling」というのが気になったので、こちらも確認しておきます。

こちらについては、下記のサイトにて、詳しく書かれておりました! 

daybreaksnow.hatenablog.jp

とりあえず、私も3つの設定ごとに実行可能JARをエクスポートしてみました。

Extract required libraries into generated JAR(生成されるJARに必須ライブラリーを抽出)

Test_runnable.jar
│  
├─com
│  └─google(※ファイルは省略)
│       +---common
│       |   +---annotations
│       |   +---base
│       |   |   \---internal
│       |   +---cache
│       |   +---collect
│       |   +---escape
│       |   +---eventbus
│       |   +---hash
│       |   +---html
│       |   +---io
│       |   +---math
│       |   +---net
│       |   +---primitives
│       |   +---reflect
│       |   +---util
│       |   |   \---concurrent
│       |   \---xml
│       \---thirdparty
│           \---publicsuffix
│                  
├─META-INF
│  │  MANIFEST.MF
│  │  
│  └─maven
│      └─com.google.guava
│          └─guava
│                  pom.properties
│                  pom.xml
│                  
└─tigertaizo
        Test01.class
        Test02.class
        Test03.class
        Test04.class
MANIFEST.MF
Manifest-Version: 1.0
Class-Path: .
Main-Class: tigertaizo.Test01

Package required libraries into generated JAR(生成されるJARに必須ライブラリーをパッケージ)

Test_runnable.jar
│  guava-18.0.jar
│  
├─META-INF
│      MANIFEST.MF
│      
├─org
│  └─eclipse
│      └─jdt
│          └─internal
│              └─jarinjarloader
│                      JarRsrcLoader$ManifestInfo.class
│                      JarRsrcLoader.class
│                      JIJConstants.class
│                      RsrcURLConnection.class
│                      RsrcURLStreamHandler.class
│                      RsrcURLStreamHandlerFactory.class
│                      
└─tigertaizo
        Test01.class
        Test02.class
        Test03.class
        Test04.class
        
MANIFEST.MF
Manifest-Version: 1.0
Rsrc-Class-Path: ./ guava-18.0.jar
Class-Path: .
Rsrc-Main-Class: tigertaizo.Test01
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader

Copy required libraries into a sub-folder next to the generated JAR(生成されるJARの隣のサブフォルダーに必須ライブラリーをコピー)

Test_runnable.jar
│  
├─META-INF
│      MANIFEST.MF
│      
└─tigertaizo
        Test01.class
        Test02.class
        Test03.class
        Test04.class

Test_runnable_lib
    guava-18.0.jar
MANIFEST.MF
Manifest-Version: 1.0
Class-Path: . Test_runnable_lib/guava-18.0.jar
Main-Class: tigertaizo.Test01

個人的には、2番目の「生成されるJARに必須ライブラリーをパッケージ」が好みでしょうか。

【Eclipse】JARファイルのエクスポート/実行確認(Javaプロジェクト編)

JavaEEの開発に携わって、だいぶ時間が経ちましたが、Javaそのものの原理・原則を正しく理解できていない今日この頃です。

というわけで、Eclipseを使って(この時点でアウトでしょうか。コマンドでやりなさい!というのは無しでお願いします)、簡単なサンプルを使って、jar化し、それを実行する段階までテストしたいと思います。
今回は、一般的なJavaプロジェクトになります。

動作環境

  • Window 7 64bit
  • JDK
>java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

>javac -version
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
javac 1.8.0_45
Eclipse Java EE IDE for Web Developers.
Version: Luna Service Release 1 (4.4.1)

プロジェクト作成

下記のような設定で、プロジェクトを作成。

f:id:no14141:20150530145936j:plain

「guava-18.0.jar」を「/lib」を配置し、guavaを右クリックで「Build Path -> Add to Build Path」を選択。 テスト用クラスは、4つ作成しました。

Test01 - 1つのクラスで正常終了するもの。

package tigertaizo;

public class Test01 {
    public static void main(String[] args) {
        System.out.println("run Test01#main.");
        System.out.println("Test01は、正常終了しました。");
        System.exit(0);
    }
}

Test02 - 1つのクラスで異常終了するもの。

package tigertaizo;

public class Test02 {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("run Test02#main.");
        Thread.sleep(1000);
        System.err.println("Test02は、異常終了しました。");
        System.exit(1);
    }
}

Test03 - 他のライブラリー(guava)を必要とするもの。

package tigertaizo;

import com.google.common.base.Strings;

public class Test03 {
    public static void main(String[] args) {
        System.out.println("run Test03#main.");
        String s = "";
        if(Strings.isNullOrEmpty(s)) {
            System.out.println("文字列sは、null または 空白です。");
        }
        //System.exit(0);
    }   
}

Test04 - 例外を吐き出すもの

package tigertaizo;

public class Test04 {
    public static void main(String[] args) {
        System.out.println("run Test04#main.");
        throw new NullPointerException();
    }   
}

完成したプロジェクトの構成は、こちら。

f:id:no14141:20150530161628j:plain

以上で、実行させたいJavaプロジェクトは完成です。

JARファイルの作成

次にJavaプロジェクトを1つのJarファイルにパッケージングします。
まずは、通常のJarファイルにまとめてみます。

f:id:no14141:20150530153034j:plain

f:id:no14141:20150530153041j:plain

f:id:no14141:20150530153047j:plain

f:id:no14141:20150530153053j:plain

Test01がMain Classとなる設定にしました。「Finish」ボタンでデスクトップにJarファイルが書き出しされました。

解凍した中身は、こんな感じになりました。

Test.jar
│  .checkstyle
│  .classpath
│  .project
│  tree.txt
│  
├─lib
│      guava-18.0.jar
│      
├─META-INF
│      MANIFEST.MF
│      
└─tigertaizo
        Test01.class
        Test02.class
        Test03.class
        Test04.class        
MANIFEST.MF

マニフェストファイルは、Jarのエクスポート設定で、任意のファイルを読み込ませることができるようですが、今回は、マニフェストファイルを指定していないので、指定したMain Classのみが反映されています。

Manifest-Version: 1.0
Main-Class: tigertaizo.Test01

JARファイル実行テスト

「Write once, run anywhere」ということで、このJARファイルは、WindowsでもLinuxでもJVMの上でなら、どこでも動きますが、テストは、Linux上で行いました。OSはCentOS7.0で。

(1)JARファイルの配備

先のJARを次の場所に設置。

/home/tigertaizo/lib/Test.jar 

(2)クラスパスの登録

自分のユーザー環境のプロファイルにクラスパスを登録します。

$ vim ~/.bash_profile

CLASSPATH=/home/tigertaizo/lib/Test.jar:.
export CLASSPATH=$CLASSPATH

即、設定を反映し、環境変数を確認します。

$ source .bash_profile
$ echo $CLASSPATH
/home/tigertaizo/lib/Test.jar:.

これで、パスが通ったことを確認できました!

(3)実行

まずは、Javaコマンドで3つのクラスを実行してみました。

$ java tigertaizo.Test01
run Test01#main.
Test01は、正常終了しました。

$ java tigertaizo.Test02
run Test02#main.
Test02は、異常終了しました。

$ java tigertaizo.Test03
run Test03#main.
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Strings
        at tigertaizo.Test03.main(Test03.java:9)
Caused by: java.lang.ClassNotFoundException: com.google.common.base.Strings
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 1 more

$ java tigertaizo.Test04
run Test04#main.
Exception in thread "main" java.lang.NullPointerException
        at tigertaizo.Test04.main(Test04.java:6)

4つ目は、故意的に例外を吐かせているので、問題ありませんが、3番目のクラスの実行では、NoClassDefFoundErrorが発生!
これは、クラスが見つからないというエラーになります。JARファイル内にguavaが存在するものの、そこへのパスが通っていないというわけですね。

「guava-18.0.jar」をLinuxに置いて、それをクラスパスに設定したうえで実行すると、正常終了しますが、これではJARの中に「guava-18.0.jar」が存在している意味が無いでしょう。

CLASSPATH=/home/tigertaizo/lib/Test.jar:/home/tigertaizo/lib/guava-18.0.jar:.
export CLASSPATH=$CLASSPATH
クラスパスにguavaを追加して、実行した結果
$ java tigertaizo.Test03
run Test03#main.
文字列sは、null または 空白です。

さらに、-jarオプションで、JARファイルを直接実行してみました。

java -jar ~/lib/Test.jar

こちらの結果は、Mainクラスで指定されているクラスが実行されますので、Test01,Test02は無事に実行できましたが、Test03ではNoClassDefFoundErrorとなりました。

このパスの問題を解決する方法として、「実行可能なJAR」というものがあるのでしょうか。

次回、検証してみます!

WebStorm購入!

5/19に、身銭を切らないとhtml5が上達しないと思い、個人購入しました。WebStormを!!!

見たことのあるデザインだと思ったら、「IntellIDEA」を出している会社さんの製品だったのですね!

f:id:no14141:20150530143707j:plain

さっそく、背景をダークにして、Yeomanで生成したAngular Applicationのソースを参照してみました。

画面右下に、Yeomanおじさんらしきアイコンが!

最高です。

【AS400】オペレーション・コンソールによる接続

久しぶりにAS400に関する投稿です。

オンプレミス系サーバーで最重要なものといえば、コンソールですよね。
AS400のコンソールについて、はるか昔は同軸ケーブルで接続のダム端で行っていましたが、今やPCベースで操作が可能です。

そういえば、最初からコンソール環境を構築したことが無いなぁ~と思い、急遽、セットアップを行うことにしました。
今使っているコンソールPCがいつ壊れてもいいように。
備えあれば憂いなしですね。

構築手順

(1) Client Accessより「オペレーション・コンソール」をインストールする

セットアップタイプ「すべて」を選択するか、「カスタム」であれば、「オペレーション・コンソール」をインストール対象にします。

f:id:no14141:20150530124553j:plain

f:id:no14141:20150530124600j:plain

(2) PCのIPアドレス設定変更

AS400本体(V7R01)のコンソール側のネットワーク体系に合わせて、IPアドレスサブネットマスクの設定を行います。 AS400側が192.168.128.1/24 の設定だったので、今回、私は、下記のような設定にしました(Windows7 PC)。

f:id:no14141:20150530125911j:plain

(3) AS400との導通テスト

まずは、基本確認ということで、コンソールケーブルを直接、PCに接続し、AS400本体へのping試験を実施しました。pingが通れば、(2)の設定は問題なしといえましょう。

>ping 192.168.128.1

(4) オペレーション・コンソール起動

オペレーション・コンソールを起動すると、いきなり次のような画面が立ち上がってきました!

f:id:no14141:20150530124607j:plain

とりあえず、「次へ」で進んでみると、ホスト名の指定画面となりましたので、サービス・ホスト名(任意)とAS400IPアドレスを設定して、さらに「次へ」と進んでいくと、完了になりました。

f:id:no14141:20150530124612j:plain

f:id:no14141:20150530124618j:plain

f:id:no14141:20150530124623j:plain

(5) ホストへの接続

(4)で登録したホスト名を選択した状態で、「接続」アイコンをクリックすると、無事に「保守ツール・サインオン画面」が起動してくれました!!

f:id:no14141:20150530124628j:plain

f:id:no14141:20150530124633j:plain

この設定であれば、とりあえずコンソール接続ができそうです。
オッケー、オッケー!!

【Glassfish4】JavaMail Sessions設定(TLS認証)

外部メール・アカウントを使って、GlassfishのJavaMail Sessionsを設定する機会があったので、アップしておきます。

Versionは、Glassfish4.1(build 13)です。

設定方法

Glassfish管理コンソールへアクセスします。

ログイン後、「JavaMail Sessions」を選択し、「New」ボタンでメール・セッションを登録します。

f:id:no14141:20150519203919j:plain

下記のような設定にてメール送信ができました!

f:id:no14141:20150519203929j:plain

メールが遅れない場合、必要な設定を確認して、Additional Propertiesに不足設定を登録する必要がありそうです。

下記のサイトを参考にさせていただきました! ありがたい!!!

qiita.com

Java EE Notes: Using JavaMail API with Glassfish and GMail

動作確認は、データベースのping試験のように、「テスト・メール送信」の機能がないので、Javaアプリケーションからコードを書きました。簡単に設定に間違いがないかどうかを確認できる方法があるといいですね。。。