2021年3月30日火曜日

Javaスレッドセーフ

Javaのプログラムはマルチスレッドで実行できる。特にServletやJSPなどはマルチスレッドで動かすことが前提なので、マルチスレッドで実行しても問題が発生しない様にスレッドセーフを意識してコーディングする必要がある。

例えば、Webアプリケーションでユーザー情報をスレッドセーフで無い変数に格納しているプログラムがあった場合、タイミングによって他のユーザーの情報が自分の画面に表示されたりといった重大な不具合を混入させてしまう恐れがあり、さらに単体テストでは気づき難い。


インスタンス変数はメソッドの外に定義された変数、クラス変数はインスタンス変数にstaticを付加した変数で、いずれも並行実行した場合、他の実行スレッドから参照される可能性がある。

下記のコードでは、ローカル変数だけがスレッドセーフ。


public class Sample01 {

	private String str01;           //インスタンス変数
	
	private static String str02;    //クラス変数
	
	public static void main(String[] args) {

		String str03;             //ローカル変数
				
	}

}

ちょっと紛らわしいのですが、下記compはstaticメソッドですが、スレッドセーフです。なぜかというと、インスタンス変数、クラス変数いずれも使用していない為です。

public class Sample01 {

	public static int comp(int arg0) {

		return arg0++;
				
	}

}

2021年3月28日日曜日

Eclipse DBViewerプラグインでCSVファイル出力

KingFisherプロジェクトとは脱線しますが、ちょっとレガシーなデータベースInterbase/Firebirdからデータの引っ越し案件が入り、調査したところデータベースに標準であるisqlではcvs出力機能が無いようでしたので、EclipseのDBViewerプラグインを使用して出力してみました。

このプラグインの良いところはJDBCドライバさえあれば同じインターフェースで様々なデータベースへアクセスできる点です。

最新のEclipse All in One(2021)には「データ・ソース・エクスプローラー」というプラグインはインストール済みですが、データベースが古いせいか、うまくいきませんでしたので、DBViewerプラグインをインストールして試みます。

インストールはこちらのサイトを参考にさせていただきました。

https://qiita.com/nkojima/items/2a865b819071e7943761


手順は

DBViewerのビューを開きます
メニュー「ウインドウ」-「ビューの表示」-「その他」をクリックします

「DBViewerプラグイン」の中から「DBツリー・ビュー」をクリックします

DBツリー・ビューが表示されました

ここからデータベースへ接続します
まず「登録」をクリックします

JDBCドライバを指定します
「ファイルの追加」をクリックします

接続対象のjdbcドライバを選択して、開くをクリックします
ここから接続に必要な情報の登録をしていきます
次へをクリックします
接続に必要な情報を登録して次へをクリックします
必要であればオプション情報を登録し完了をクリックします

無事接続できました。
テーブルの情報も見えています
CSVファイル出力したいテーブルを選択し、右クリック、CSV出力をクリックします

ファイルの格納場所とファイル名を指定して、保存をクリックします。
カンマ区切りのCSVファイルが保存されました。





2021年3月24日水曜日

決定した環境でJavaMailが正常に動くか検証

 Javaプログラムからemailを送信するライブラリがjavamailです。今回構築する環境でjavamailが正しく動作するか、検証したいと思います。

なおOpenJDK 11 以降ではjava.activation パッケージが削除されています。ただ JavaMail は内部でこれを使用していますので、javax.activationライブラリを別途用意する必要があります。

今回のタスク

  • javamailのライブラリをダウンロード
  • javax.activationライブラリをダウンロード
  • Apache commons-emailライブラリをダウンロード
  • email送信クラスを作成して検証
それでは始めましょう

まずはjavamailのライブラリをダウンロードします

https://javaee.github.io/javamail/ へアクセスします

少し下にスクロールします

Download javamail release の中からjavax.mail.jarリンクをクリックしてライブラリを取得しビルドパスに追加します

続けてjavax.activationライブラリの取得です
ここへアクセスします

Files のJar リンクをクリックしてライブラリを取得しビルドパスに追加します

続けて、Apache commons emailライブラリを取得です
https://commons.apache.org/proper/commons-email/ ここへアクセスします

Downloadをクリックします

今回はWindows環境にセットアップしますのでcommons-email-1.5-bin.zipをクリックします
ダウンロードされたzip内の、commons-email-1.5.jarをビルドパスに追加します

ここから検証プログラムを作成していきます

package sample02;

import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

public class Emailtest {

	public void sendEmail() {
		try {
			Email email = new SimpleEmail();
			email.setHostName("xxx.xxx.co.jp");
			email.setSmtpPort(587);
			email.setAuthenticator(new DefaultAuthenticator("xxx@xxx.co.jp", "password"));
			email.setSSLOnConnect(false);
			email.setCharset("ISO-2022-JP");
			email.setFrom("xxx@xxx.co.jp", "ウエブマスター", "ISO-2022-JP");
			email.setSubject("テストメール");
			email.setMsg("テストメールの本文です");
			email.addTo("yyy@yyy.com", "なかさん", "ISO-2022-JP");
			email.send();
		} catch (EmailException e) {
			e.printStackTrace();
		}
	}

}
 
シンプルですね上記サンプルのxxx,yyyは適宜置き換えてくださいね


package sample02;

public class Execute {

	public static void main(String[] args) {
		Emailtest obj = new Emailtest();
		obj.sendEmail();

	}

}
実行用クラスを準備してEclipseから実行します
送信先に指定したアドレスにメールが送信されました。

2021年3月23日火曜日

EclipseでJUnitを使用したユニットテストを実施

 Eclipse All in One にはユニットテストが実行できるJUnitが最初から組み込まれています。今回は、これを使ってユニットテストを実施する手順を纏めました。

Eclipseのセットアップおよびテスト対象のクラスについてはこの回で作成済みのものを使用します。

ただし、サーブレットクラスをテストするには、JUnit単独ではできないため、今回はユニットテスト用に、一部ソースを書き換えます。(改変後のgetTextメソッドをテストします)

package sample01;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/S01")
public class Servlet01 extends HttpServlet {

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

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println(getText());

	}

	protected String getText() {
		StringBuffer sb = new StringBuffer();
		sb.append("<html><head></head><body>");
		sb.append("<p>Simple Application</p>");
		sb.append("<p>Servlet01</p>");
		sb.append("</body></html>");
		return  sb.toString();
	}
}


それでは、始めて行きましょう。

リリース時にテストクラスを除外しやすくなるなどのメリットがありますのでテストクラス専用のソースフォルダを作成します。

プロジェクト上で右クリック「新規」-「その他」をクリックします

「Java」-「ソースフォルダ」を選択して次へをクリックします

テスト専用フォルダのフォルダ名(今回はtestsrcとしました)を指定して完了をクリックします

「testsrc」が作成されています(パッケージエクスプローラーで確認できます)

ここからテストクラスを作成していきます
テスト対象のクラス上で右クリックし「新規」-「その他」をクリックします
「Junitテストケース」を選択して次へをクリックします

ソース・フォルダを先ほど作成したテストクラス専用のtestsrcとし、名前はテスト対象クラスにTestの文字を付加したもの、テスト元クラスは最初に選択したクラスが設定されている状態で次へをクリックします

テスト対象のメソッドはgetTextなので、これをチェックで選択し完了をクリックします

対象のプロジェクトのビルドパスにJUnitが無い場合、このダイアログが表示されるので、OKボタンをクリックしビルドパスに追加します

テスト対象のクラスに対になるようにテストクラスが作成されました。
続けて、テストクラスを実装します作成されたテストクラスを次の様に変更してください。
メソッドassertEquals([x],[y])は、xとyが同じ場合OKとなる
※テストNGの様子が分かるように、わざとchk変数の先頭に「!」を入れています

package sample01;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class Servlet01Test {

	@Test
	void testGetText() {
		final String chk =
		"!<html><head></head><body><p>Simple Application</p><p>Servlet01</p></body></html>");


		Servlet01 obj = new Servlet01();
		assertEquals(chk,obj.getText());
	}

}
ここからユニットテストを実行します
テストクラス上で右クリックし、「実行」-「JUnitテスト」をクリックします

ユニットテストが実行されて、エラーが1件発生している状態です

JUnitビューの「org.opentest4j...」部分をダブルクリックすると比較ダイアログが表示され先頭1文字が想定と異なることが確認できます

テストクラスの変数chkの先頭「!」を削除して再実行すると、エラーなく終了することが出来ました。


2021年3月22日月曜日

EclipseでwebアプリケーションのDebug

 JavaのIDEであるEclipseを使ってWebアプリケーションをデバックする方法を纏めました

Eclipseのセットアップはこの回で完了していることが前提。

作成したソースコードにブレークポイントを設定します
(行ナンバーの場所でダブルクリック)

デバッグ・モードでサーバーを始動をクリックします

アプリケーションサーバーTomcatが起動します

ブラウザを立ち上げてhttp://localhost:8080/sample01/S01へアクセスします

パースペクティブがデバッグに切り替わります
先ほど設定したブレイクポイントで一時停止しています。
カーソルをオブジェクトに合わせるとポップアップが表示され、変数の内容が細かく確認できます

デバッグ情報が取得できたら、継続してプログラムを実行するため、再開をクリックします

レスポンスを返却した状態

ブラウザにもレスポンスが帰りました

一通りの確認が完了したら、サーバーを停止をクリックしサーバーを停止します




2021年3月21日日曜日

Java servletでHello World

 一連の開発環境が整ったところで、Java servletで簡単なサンプルを作って動作検証してみます。

作成するものは「ブラウザからアクセスされたら、HTMLを生成して応答を返す」です。

Eclipseを起動しておきます。(Eclipseのセットアップはこの回で説明した通り)

メニュー「ファイル」-「新規」-「プロジェクト」を選択します

「Web」-「動的Webプロジェクト」を選択して次へをクリックします

プロジェクト名を指定し(今回はsample01としました)次へをクリックします

次へをクリックします
完了をクリックします

プロジェクトが完成しました。

ここからJavaのservletクラスを作っていきます
ソース(src)を右クリックして「新規」-「クラス」を選択します

クラス名を指定します(Servlet01としています)
Javaクラスの編集準備が出来ました。
このクラスを以下のコードにします

※ソースコードの表示部分に一部HTMLタグが含まれており、正しく表示されていなかったので3/23改変しています。


package sample01;

import java.io.IOException;
import java.io.PrintWriter;

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

@WebServlet("/S01")
public class Servlet01 extends HttpServlet {

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

		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<html><head></head><body>");
		out.println("<p>Simple Application</p>");
		out.println("<p>Servlet01</p>");
		out.println("</body></html>");

	}

}
Tomcatの設定ファイルを極力変更したくないので、@WebServletアノテーションにURL「/S01」を指定しています

アプリケーションサーバーtomcatへ組み込みます
サーバービューのlocalhost tomcatを右クリックして「追加および削除」をクリックします
作成したプロジェクト「sample01」を選択状態で「追加」をクリックします(この時点で「sample01」が使用可能から構成済みに移動します。
そして完了をクリックします

サーバービューのlocalhost tomcatに「sample01」が追加になっていますのでサーバーを始動ボタンをクリックします

コンソールビューにtomcatの起動メッセージが流れて起動が完了します

ブラウザを立ち上げて、作成したWebアプリケーションにアクセスします
http://localhost:8080/sample01/S01

URLの意味
httpプロトコル
localhostサーバー
8080Tomcatの実行ポート番号
sample01Webアプリケーション名
S01サーブレットマッピング

プログラムで指定した下記の文字が表示されていれば成功です
Simple Application
Servlet01

適格請求書等保存方式(インボイス制度)と消費税の端数処理

消費税の税額計算は 売上税額-仕入れ税額=納税額 2023年10月以降、この納税額の計算の元になる請求書は適格請求書(インボイス)の保存が必要となる。 2019年10月から消費税が10%に引き上げられる際に、日用品等は8%に据え置かれ複数税率を扱う事業者が発生する。 この軽減税率...