tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Exceptionエラーの対応

Visualforceを開発した際のExceptionエラー発生時の対応について考えてみました。


通常Exceptionエラーが発生した際には次のような画面が表示されます。
f:id:tyoshikawa1106:20130127112637p:plain


このエラーはID型に文字列をセットしようとして発生しています。
コードはこんな感じ。

public with sharing class ExceptionMessegeController {
	
	public ExceptionMessegeController() {
		Id exceptionId = 'error';	
	}
}


単純な処理の場合はどこでエラーが発生したのかすぐに見つかりますが、複雑になってくるとこれだけでは探すのが大変になってきます。デバックログなどで探す方法もありますが、本番環境などでアクセスできないケースもあるかなと思います。


そういうことからもっと詳細なエラー情報をメッセージとして表示してみようと下記のようにExceptionメッセージを表示するメソッドを作ってみました。

/*
 * 異常系メッセージ表示
 * @param	: Exception  [e]
 * @return	: なし
 */
public static void msgError(Exception e) {
	// エラーメッセージを表示
	ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'システムエラーが発生しました。'));
	// Exceptionメッセージを表示
	ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,e.getMessage()));
	// エラー発生原因を表示
	ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,
		'Line:' + String.valueOf(e.getLineNumber()) + '【' + e.getTypeName() + '】'));
}

次の処理でExceptionメッセージ、エラー発生行、Excetionの種別を取得できます。

  • e.getMessage()
  • e.getLineNumber()
  • e.getTypeName()


これをCommonUtil等の共通クラスに用意し、try-catchのcatch処理で呼び出します。
コードは次のようになります。

public with sharing class ExceptionMessegeController {
	
	public ExceptionMessegeController() {
		try {
			Id exceptionId = 'error';
		} catch (Exception e) {
			CommonUtil.msgError(e);
			return;
		}	
	}
}


これでExcetionエラー発生時に詳細な情報をメッセージで表示できます。
表示されるメッセージは次のようになります。
f:id:tyoshikawa1106:20130127114344p:plain


行番号やExceptionの種別も一目でわかるので、本番環境にアクセスできなくてもSandbox環境で大体のエラー発生箇所を確認できます。エラー発生時にこんな画面が表示されたと画面キャプチャが届いた時もエラー発生箇所が確認しやすくなるかなと思います。


DaoクラスやActionクラスなどに処理を分ける場合も、呼び出し元のクラスだけにtry-catchがあれば大丈夫です。


例えば次のようなDaoクラスをControllerクラスから呼び出します。

public with sharing class ExceptionMessegeDao {
	
	public User getUser() {
		return [
			select
				Id
			from
				User
			where
				Id =: UserInfo.getUserId()
			and
				IsActive = false
		];
	}
}

このDaoクラスではログインユーザのIDと一致し、無効になっているユーザを取得するという取得不可条件でユーザ取得クエリを実行しています。

呼び出し元のController側はこんな感じ。

public with sharing class ExceptionMessegeController {
	
	// Daoクラス
	private ExceptionMessegeDao dao;
	
	public ExceptionMessegeController() {
		
		// Daoクラス
		this.dao = new ExceptionMessegeDao();
		
		try {
			// Daoクラスからユーザ情報取得
			User objUser = this.dao.getUser();
		} catch (Exception e) {
			CommonUtil.msgError(e);
			return;
		}   
	}
}


これを実行すると次のようにエラーメッセージが表示されます。
f:id:tyoshikawa1106:20130127122252p:plain

エラー内容としては次のとおり
①List has no rows for assignment to SObject
クエリ取得件数が0件
②Line:4【System.QueryException】
4行目でSystem.QueryExceptionが発生

※ここでの4行目というのはDaoクラス側の行番号となりました。


どこのクラスで発生しているかまで確認したい場合は、「e.getStackTraceString()」を使用すると確認できます。

ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getStackTraceString()));

f:id:tyoshikawa1106:20130127125124p:plain


Exceptionエラー発生時にはこんな感じでメッセージが表示されると対応しやすくなるかと思います。開発中でも予期せぬエラーが発生した際にこんなケースもあったんだと気づきやすいです。