CheckStyleでJavaのソースコードをチェックしているとき、以下のような警告が表示されることがあります。

最初の一文はピリオドで終わらなければなりません。


ピリオドだけでなく句点「。」でコメントが終わっている場合は警告を表示させなくするために、以下のようにCheckStyleのルールを修正します。

「CheckStyle構成」->「Javaコメント」->「スタイルJavadoc」を選択した状態で「開く」ボタンをクリック。
表示されるダイアログの「endOfSentenceFormat」を次のようにします。

([。.?!][ \t\n\r\f<])|([。.?!]$)

※句点を2ヶ所追加します。

正しく動作するかを確かめるために「テキスト文字列をここに入力」と書かれているテキストボックスにいくつか文字列を入れてみましょう。句点が最後に入っている場合は、背景色がグリーンになります。

この修正を行ったことをエラーメッセージにも反映させるには、「拡張」タブの「javadoc.noperiod」のメッセージを「最初の一文はピリオド、または句点で終わらなければなりません。」(例)と修正します。
以下のような前提の時、Jarファイルをeclipseから実行させる場合に注意が必要です。

【前提】
・Jarファイルから外部ファイルを読み込み、もしくは書き込みする。
・外部ファイルのパスを相対パス指定している。

eclipseで表示されているJarファイルを実行すると、eclipseの置かれているフォルダが作業フォルダ(カレントディレクトリ)になります。例えば、「C:\Program Files\eclipse」というようなパスです。

Jarファイルで外部ファイルを相対パス指定していると、作業フォルダからのパスを取得することになります。他の環境に配布する前提なのであれば、エクスプローラ上でJarファイルを直接起動するようにしましょう。
Internet Explorerのセキュリティの設定により、Visual Studio 2003のデバッグ機能が利用できなくなることがあります。

【原因】
1. IEのセキュリティの設定で、「ユーザ認証」の項目が「ユーザ名とパスワードを入力してログオンする」となっている

【単純な解決策】
IEのデフォルトの設定では、「ユーザ認証」の項目は「イントラゾーンでのみ自動的にログオンする」となっています。まずはその設定に戻すとよいと思われます。

1点注意が必要なのが、この項目の設定が変更したにも関わらず反映されないことがあること。まだこの原因はつかめていませんが、さまざまな状態で起動してみて、設定を確認してみてください。

IEの設定

Javaで実装されたテンプレートライブラリApache Velocityは、メールのテンプレート生成等によく利用されています。そのVelocityライブラリを利用している際によく発生する ResourceNotFoundException *1 の対処法についてまとめてみます。


【基本編】 どういった状況で ResourceNotFoundException が発生するか

VelocityのJavadocはとても不親切なので分かりづらいのですが、テンプレートファイルが指定した位置に存在しないことが大きな原因の1つです。
Templateクラスのインスタンスを生成するVelocityクラスもしくはVelocityEngineクラスのgetTemplateメソッドを呼ぶ際に、引数として与えたテンプレートファイルへのパスが誤っていることをまず疑ってください。

- ファイル名は誤っていないか
- テンプレートファイルのあるディレクトリ名が誤っていないか


【発展編】 パスは誤っていないはずなのに ResourceNotFoundException が発生する場合

何度確認してもパスに間違いがない場合は、getTemplateメソッドの引数について次の点を確認しましょう。(FileResourceLoaderを利用している場合のみ)
  ・ 相対パスで指定しているか
  ・ XXX.resource.loader.path *2 プロパティからの相対パスになっているか
  ・ XXX.resource.loader.path配下にあるファイルを指定しているか(サブディレクトリ内でも可)

3つ目が案外はまりやすいんじゃないでしょうか。
デフォルトでのresource.loader.pathはカレントディレクトリになっています。つまり、カレントディレクトリ配下にテンプレートファイルが配置されていないといけません。テンプレートファイルをカレントディレクトリ以外に配置したい場合は、resource.loader.pathを適切に設定する必要があります。

また、Windows環境で実行している場合は次の点も確認してみましょう。
  ・ XXX.resource.loader.pathを指定するとき、「\」でなくて「/」を利用しているか


【参考資料】
[wiki] Velocity - 気の向くままに
[web] Velocity - TECHSCOPE
[web] Apache Velocity (本家)

*1 : org.apache.velocity.exception.ResourceNotFoundException
*2 : XXXは、リソースローダ名
行列式を手で簡単に解く方法として、サラスの方法があります。
もちろんプログラムでもサラスの方法は利用することはできるのですが、この方法では4次以上の行列に対して行列式を求めることができません。そこで、4次以上の行列の行列式を求めるために、余因子展開を用いたJavaプログラムのサンプルを紹介します。

(なお、確実にテストを行ったわけではないので、自己責任の範囲内で利用してください。バグの報告はコメントにお願いします。)

public class Sample {
	private static interface ArrayAccess {
		
		int size();
		double get(int r, int c);
	}
	
	private static class WrapEntity implements ArrayAccess {

		private ArrayAccess array;
		private int row;
		private int col;
		private int size;
		
		public WrapEntity(ArrayAccess a, int r, int c){
			this.array = a;
			this.row = r;
			this.col = c;
			this.size = a.size()-1;
		}
		
		public double get(int r, int c) {
			r = r>=row ? r+1: r;
			c = c>=col ? c+1: c;
			return array.get(r, c);
		}

		public int size() {
			return size;
		}
		
	}
	
	private static class Entity implements ArrayAccess {
		
		private double[][] array;
		private int row;		
		private int col;
		private int size;
		
		public Entity(double[][] a, int r, int c){
			this.array = a;
			this.row = r;
			this.col = c;
			this.size = a.length-1;
		}
		
		public int size(){
			return size;
		}
		
		public double get(int r, int c){
			r = r>=row ? r+1: r;
			c = c>=col ? c+1: c;
			return array[r][c];
		}
	}
	
	private static double sub(ArrayAccess array){
		if(array.size()==1){
			return array.get(0, 0);
		}
		if(array.size()==2){
			return array.get(0, 0)*array.get(1, 1)
					-array.get(0, 1)*array.get(1, 0);
		}
		// 行列式の計算
		double det = 0;
		final int length = array.size();
		for(int i=0;i<length;i++){
			double v = array.get(0, i);
			if(v!=0){
				double d = v*sub(new WrapEntity(array,0,i));
				det += i%2==0? d: -d;
			}
		}
		return det;
	}
	
	public static double cofactor(double[][] array){
		// 引数チェック
		if(array==null){
			throw new NullPointerException();
		}
		final int length = array[0].length;
		for(int i=0; i<array.length; i++){
			if(array[i].length!=length)
				throw new IllegalArgumentException();
		}

		// 行列式の計算
		double det = 0;
		for(int i=0;i<length;i++){
			double v = array[0][i];
			if(v!=0){
				double d = v*sub(new Entity(array,0,i));
				det += i%2==0? d: -d;
			}
		}
		return det;
	}

// サンプル用メインメソッド
public static void main(String[] args){ double[][] array = {{1,2,3},{4,5,6},{7,8,9}}; System.out.println(cofactor(array)); } }
ここで、簡単にソースの説明を。
前半のArrayAccessインターフェース、WrapEntityクラス、Entityクラスは、配列の配列を余因子行列のように見せるためのエンティティクラスです。このクラスを利用しない場合は、配列の内容を毎回コピーする必要があるので、処理速度を高めるために導入しています。

後半のsubメソッド、cofactorメソッドが行列式を計算するメソッドになります。
2つのメソッドはほぼ同じ処理をしていますが、cofactorでは引数チェックを行っている点が異なります。また、subメソッドでは余因子展開を再帰を用いて計算しています。

もう少し考えればもっと効率は良くなるかと思いますが、とりあえずは処理の流れが理解しやすい今の状態を公開することにします。
ApacheプロジェクトのうちのApache Commons Mathライブラリでは、行列計算を簡単に行うためのAPIが提供されています。もし、Javaで行列計算をさっさとやってしまいたい場合などは非常に役に立つと思います。

Apache Commons Mathは次のページからダウンロードできます。
[web] Aapche Commons Math
このページの「Releases」と書かれたタイトルの下にあるリンクから、ダウンロードページに行けます。現在の最新リリースは、Ver.1.2 です。

Commons Mathのライブラリを取得してきたら、javadocを見ながら早速作成してみましょう。
このライブラリの中で、行列計算をするために重要なのは、MatrixUtilsクラス、BigMatrixインターフェース、RealMatrixインターフェースです。
(パッケージは全てorg.apache.commons.math.linear です。)

行列計算をさせる流れは以下の通り。
1.行列として扱いたいデータ(配列の配列)を用意する。
2.MatrixUtilsクラスのcreateXXXMatrixメソッド *1 を使って、BigMatixもしくはRealMatrixのインスタンスを生成。
3.生成したインスタンスを利用して、行列計算

ちなみに、このRealMatrixインターフェース等を見てもらうと分かる通り、生成されるインスタンスは不変ではありません。複数のスレッド間で参照・変更をする場合は、必ず同期をとる必要があります。

public static void main(String[] args){
  double[][] array = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
  };
  RealMatrix matrix = MatrixUtils.createRealMatrix(array);
  System.out.println(matrix.getDeterminant());  # 行列式の表示
}

*1 : XXXは、RealやBig等と置き換わります。詳細はAPIを参照。
VMWare Server 2.0をインストールして、「VMWare Server Home Page」と書かれたリンク(管理コンソール)をクリックすると、立ち上がったブラウザの中でユーザIDとパスワードの入力を求められます。

VMWare Server 2.0をインストールした時にID/PWを決定した覚えもないし、いったい何を入力すれば?と戸惑った方も多いかと思います。

実は、ここで入力するユーザID/パスワードは、VMWare Server 2.0がインストールされているWindowsのアカウントID/パスワードを入力すれば大丈夫。ただし、アカウントのパスワードが何も設定されていない場合はどうしても弾かれてしまうので、アカウントのパスワードを設定した後に再挑戦してみてください。

【参考記事】
[blog] VMWare Server 2.0をインストール - プログラマーになりたい!
VMGINA.DLLがPCにインストールされることによって、Windowsのようこそ画面が利用できなくなる場合があります。このVMGINA.DLLは、VMWare Serverをインストールする際に同時にシステムにコピーされるようです。

ようこそ画面を利用できるようにするには、以下のようにします。
(レジストリを操作するため、バックアップを取るようにしましょう。)

レジストリの、
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GinaDLL
を削除し、再起動してください。

【参考ページ】
[web] サードパーティ製のプログラムをインストールするとデフォルトのWindowsログオンインターフェースが表示されない場合がある - Microsoft
Velocityには独自に処理内容をログに出力する機能が含まれています。
特に気にしない場合はいいのですが、実際に運用する場面では冗長な機能ともいえます。そんな時にどのようにしてログを出力させないようにするかを紹介します。

まず、単純な方法は、Velocityにプロパティとして与えることです。

Velocity.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, 
    "org.apache.velocity.runtime.log.NullLogSystem");
これを初期化処理と一緒にやってしまうといいでしょう。
その他にも、プロパティファイルに定義したい場合は以下のようにします。

runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogSystem
この一行をプロパティファイルに追記してください。

【参考文献】
[blog] Velocityのログ出力をオフにする - Oddwit
[web] Velocityの設定キー - TECHSCORE
ある定型のメールの文章のうち、一部分だけを変えて送信したいということは往々にしてあり得ます。しかし、その処理を実装しようと思うと案外面倒だったりします。そこで、その処理を簡単にするために、Apache Velocityを用いたメールテンプレートの利用方法について紹介します。

【前提条件】
- J2SE 1.2以上
- Apache Velocity1.5
- Apache Commons Collection3.1, Apache Commons Lang2.1
- テンプレートファイル(.vm)
- プロパティファイル(.properties):必須ではない。以下の例では利用

【使い方】
Apache VelocityはJ2SE以降で動作する汎用テンプレートエンジンです。これを利用することで、メールテンプレートはもちろん、XMLやSQLなど、あらゆるテンプレートに利用可能です。使い方はアイデア次第といったところです。

で、実際に利用するためにApacheプロジェクトのサイトからjarファイルをダウンロードしてきます。
[web] Apache Velocity

このページの左側に「Downloads」と書かれたリンクがあるので、その先のページからzipファイルかtar.gzファイルをダウンロードします。

そして、ダウンロードしてきたファイルを解凍するとVelocityのjarファイルが手に入ります。ただ単に試したいだけならvelocity-dep-X.jarを利用すればいいでしょう。velocity-X.jarは、Velocityが利用している外部ライブラリを含んでいないjarファイルです。

velocity-dep-X.jarをクラスパスで指定し、以下のプログラムを実行することで動作を確かめられます。Velocityで提供されている主要なクラスは、VelocityContextクラスとVelocityEngineクラスです。

    public static void main(String[] args) throws Exception{
        // 購入者情報
        Member member = new Member();
        member.setLastName( "佐藤" );
        member.setFirstName( "太郎" );
        member.setEmail("aaa@example.com");
        
        // 購入商品情報
        Item item1 = new Item();
        item1.setItemCode("0000-1111" );
        item1.setName( "健康食品1" );
        item1.setPrice(1000);

        Item item2 = new Item();
        item2.setItemCode("0000-1112" );
        item2.setName( "健康食品2" );
        item2.setPrice(2000);
        
        // 注文情報
        Order order = new Order();
        order.setMember( member );
        order.setOrderNumber("0001-AAAA");
        
        order.addItem(item1);
        order.addItem(item2);
        
        // 会社情報
        Company company = new Company();
        company.setName("なんでも.com");
        company.setEmail("bbb@example.com");        
        
        VelocityWrapper va = new VelocityWrapper( "mail.vm" );
        va.put( "order" , order );
        va.put( "company" , company );
        String body = va.merge();
        
        System.out.println(body);  
    }

    public class Company {

	private String name;
	private String email;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
    }

    public class Item {

	private String itemCode;
	private String name;
	private int price;
	
	public String getItemCode() {
		return itemCode;
	}
	public void setItemCode(String itemCode) {
		this.itemCode = itemCode;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int i) {
		this.price = i;
	}
    }

    public class Member {

	private String lastName;
	private String firstName;
	private String email;

	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}	
    }

    public class Order {

	private Member member;
	private String orderNumber;
	private List itemList = new ArrayList();
	
	public Member getMember() {
		return member;
	}
	public void setMember(Member member) {
		this.member = member;
	}
	public String getOrderNumber() {
		return orderNumber;
	}
	public void setOrderNumber(String orderNumber) {
		this.orderNumber = orderNumber;
	}
	public List getItemList() {
		return itemList;
	}
	public void setItemList(List itemList) {
		this.itemList = itemList;
	}
	public void addItem(Item item1) {
		itemList.add(item1);		
	}
    }

    public class VelocityWrapper {

	/** テンプレートファイルの内容を格納したクラス */
	private Template template = null;

	/**
	 * テンプレート変換時に使用する オブジェクトを格納するためのクラス
	 */
	private VelocityContext context = new VelocityContext();

	/** Velocityエンジンにアクセスするためのクラス */
	private VelocityEngine engine = new VelocityEngine();

	public VelocityWrapper(String templateFileName) throws IOException,
			Exception {

		// velocity.propertiesによるVelocityEngineの初期化
		Properties props = new Properties();
		props.load(new FileInputStream("velocity.properties"));
		engine.init(props);

		// テンプレートの取得
		template = engine.getTemplate(templateFileName);
	}

	public void put(String key, Object value) {
		context.put(key, value);
	}

	public String merge() throws ResourceNotFoundException,
			ParseErrorException, MethodInvocationException, Exception {
		StringWriter sw = new StringWriter();
		template.merge(context, sw);
		return sw.toString();
	}
    }
以下がvelocity.propertiesです。
input.encoding=Windows-31J
output.encoding=Windows-31J
以下がテンプレートファイル(mail.vm)です。
$order.member.lastName $order.member.firstName 様

$company.nameをご利用頂きありがとうございます。

以下の注文を承りました。
注文番号:$order.orderNumber

≪購入商品情報≫
-----------------------------
商品番号 |注文商品名|価格
-----------------------------
#set ($amount=0)
#foreach ( $item in $order.itemList)
$item.itemCode|$item.name|  $item.price
#set( $amount=$amount+$item.price)
#end
-----------------------------
         合計          $amount
#set ($point=0)
#if($amount<1000)
#set ($point=10)
#elseif($amount<2000)
#set ($point=20)
#else
#set ($point=30)
#end

獲得ポイントは$pointです。

=================================================
$company.name
メールアドレス:$company.email
=================================================
なお、この記事を書くために、CodeZine様のページをとても参考にさせていただいています。(ただし、本文中の誤記が非常に多いです。)
[web] Jakarta Velicityでテンプレートを変換しメールを送信する - CodeZine

Advertizement

Powered by Movable Type 5.0