
⇧ やはり、お金かね...
Javaで独自例外クラスにフィールドを追加してみる
背景として、early return patternを使っている処理でエラーにしたい場合の戻り値がModelAndViewになっていて、正常に処理された場合の戻り値とデータ型が異なるため、メソッドに切り出せないという...
致し方ないので、エラーにしたい時は独自例外クラスを投げるようにすることを考えました。
で、独自例外クラスにフィールドを追加したいと思い、
⇧ 上記サイト様を参考にさせていただきました。
利用してるMavenプロジェクトは、
⇧ 上記の記事の時のもので。
以下、追加と変更したソースコード。
■/spring-mvc-jsp/src/main/java/com/controller/exception/BusinessException.java
package com.controller.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@AllArgsConstructor
@Data
@EqualsAndHashCode(callSuper=true)
public class BusinessException extends Exception {
private String code;
}
■/spring-mvc-jsp/src/main/java/com/controller/helper/SettingControllerHelper.java
package com.controller.helper;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.controller.exception.BusinessException;
import com.dto.form.RadioButtonDto;
@Component
public class SettingControllerHelper {
public List<RadioButtonDto> makeRadioButton(String currentValue) throws BusinessException {
Map<String, String> map = makeMapForHandlingFlg();
if (CollectionUtils.isEmpty(map)) {
throw new BusinessException("00000001");
}
List<RadioButtonDto> RadioButtonDtoList = makeRadioButton(map, currentValue);
if (CollectionUtils.isEmpty(RadioButtonDtoList)) {
throw new BusinessException("00000002");
}
return RadioButtonDtoList;
}
/**
* ラジオボタンを作成
* @param radioButtonMap
* @param currentValue
* @return
*/
private static List<RadioButtonDto> makeRadioButton(Map<String, String> radioButtonMap, String currentValue) {
List<RadioButtonDto> radioButtonDtoList = new ArrayList<>();
for (Map.Entry<String, String> entry: radioButtonMap.entrySet()) {
RadioButtonDto radioButtonDto = new RadioButtonDto();
radioButtonDto.setLabel(entry.getKey());
radioButtonDto.setValue(entry.getValue());
if (entry.getValue().equals(currentValue)) {
radioButtonDto.setChecked(true);
} else {
radioButtonDto.setChecked(false);
}
radioButtonDtoList.add(radioButtonDto);
}
return radioButtonDtoList;
}
/**
* 二択(有・無)のラジオボタン
* @return
*/
public static Map<String, String> makeMapForHandlingFlg() {
Map<String, String> handlingFlgMap = new LinkedHashMap<String, String>(){
{
put("有", "1");
put("無", "0");
}
};
return handlingFlgMap;
}
}
■/spring-mvc-jsp/src/main/java/com/controller/SettingController.java
package com.controller;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.controller.exception.BusinessException;
import com.controller.helper.SettingControllerHelper;
import com.dto.form.RadioButtonDto;
import com.form.SettingForm;
@Controller
@RequestMapping("settingController")
public class SettingController {
@Autowired
private SettingControllerHelper settingControllerHelper;
@ModelAttribute
public SettingForm initForm() {
SettingForm settingForm = new SettingForm();
return settingForm;
}
/**
* 表示
* @param settingForm
* @return
*/
@RequestMapping("currentSetting")
public ModelAndView settingForm(SettingForm settingForm) {
ModelAndView mv = new ModelAndView("setting/index");
// TODO:データベースから取得
// ラジオボタンを生成
// List<RadioButtonDto> elevetorHandlingFlgList = makeRadioButton(makeMapForHandlingFlg(), settingForm.getElevetorHandlingFlg());
// List<RadioButtonDto> wheelchairHandlingFlgList = makeRadioButton(makeMapForHandlingFlg(), settingForm.getWheelchairHandlingFlg());
// List<RadioButtonDto> aedHandlingFlgList = makeRadioButton(makeMapForHandlingFlg(), settingForm.getAedHandlingFlg());
List<RadioButtonDto> elevetorHandlingFlgList = Collections.emptyList();
List<RadioButtonDto> wheelchairHandlingFlgList = Collections.emptyList();
List<RadioButtonDto> aedHandlingFlgList = Collections.emptyList();
try {
elevetorHandlingFlgList = settingControllerHelper.makeRadioButton(settingForm.getElevetorHandlingFlg());
wheelchairHandlingFlgList = settingControllerHelper.makeRadioButton(settingForm.getWheelchairHandlingFlg());
aedHandlingFlgList = settingControllerHelper.makeRadioButton(settingForm.getAedHandlingFlg());
} catch (BusinessException e) {
if ("00000001".equals(e.getCode())) {
mv.addObject("displayMessage", "【エラーコード】00000001");
return mv;
}
if ("00000002".equals(e.getCode())) {
mv.addObject("displayMessage", "【エラーコード】00000002");
return mv;
}
}
mv.addObject("elevetorHandlingFlgList", elevetorHandlingFlgList);
mv.addObject("wheelchairHandlingFlgList", wheelchairHandlingFlgList);
mv.addObject("aedHandlingFlgList", aedHandlingFlgList);
if (Objects.nonNull(settingForm.getCompleteUpdate())
&& settingForm.getCompleteUpdate()) {
settingForm.setCompleteUpdate(false);
mv.addObject("completeUpdate", true);
int updateCount = settingForm.getUpdateCount();
settingForm.setUpdateCount(++updateCount);
} else {
mv.addObject("completeUpdate", false);
settingForm.setUpdateCount(0);
}
return mv;
}
/**
* 更新
* @param settingForm
* @return
*/
@RequestMapping("update")
public ModelAndView updateSetting(SettingForm settingForm) {
// TODO:データベースの更新
settingForm.setCompleteUpdate(true);
return settingForm(settingForm);
}
/**
* 削除
* @param settingForm
* @return
*/
@RequestMapping("delete")
public ModelAndView deleteSetting(SettingForm settingForm) {
// TODO:データベースの更新
// フォームをリセット
settingForm = deleteForm(settingForm);
settingForm.setCompleteUpdate(true);
return settingForm(settingForm);
}
// /**
// * ラジオボタンを作成
// * @param radioButtonMap
// * @param currentValue
// * @return
// */
// private static List<RadioButtonDto> makeRadioButton(Map<String, String> radioButtonMap, String currentValue) {
//
// List<RadioButtonDto> radioButtonDtoList = new ArrayList<>();
// for (Map.Entry<String, String> entry: radioButtonMap.entrySet()) {
// RadioButtonDto radioButtonDto = new RadioButtonDto();
// radioButtonDto.setLabel(entry.getKey());
// radioButtonDto.setValue(entry.getValue());
//
// if (entry.getValue().equals(currentValue)) {
// radioButtonDto.setChecked(true);
// } else {
// radioButtonDto.setChecked(false);
// }
// radioButtonDtoList.add(radioButtonDto);
// }
// return radioButtonDtoList;
// }
//
// /**
// * 二択(有・無)のラジオボタン
// * @return
// */
// private static Map<String, String> makeMapForHandlingFlg() {
// Map<String, String> handlingFlgMap = new LinkedHashMap<String, String>(){
// {
// put("有", "1");
// put("無", "0");
// }
// };
// return handlingFlgMap;
// }
/**
* 削除の場合のフォームの内容をリセット
* @param settingForm
* @return
*/
private static SettingForm deleteForm(SettingForm settingForm) {
settingForm.setElevetorHandlingFlg(null);
settingForm.setWheelchairHandlingFlg(null);
settingForm.setAedHandlingFlg(null);
return settingForm;
}
}
■/spring-mvc-jsp/src/main/webapp/WEB-INF/views/setting/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>設定画面</title>
</head>
<body>
<c:if test="${not empty displayMessage}">
<script>
alert("${displayMessage}");
</script>
</c:if>
<form:form method="post" modelAttribute="settingForm">
<c:if test="${settingForm.updateCount ge 0 }">
更新回数:${settingForm.updateCount}
<div>
<span>エレベーター取扱有無</span>
</div>
<c:forEach var="obj" items="${elevetorHandlingFlgList}"
varStatus="status">
<c:choose>
<c:when test="${obj.checked}">
<form:radiobutton path="elevetorHandlingFlg"
id="elevetor-${status.index}" label="${obj.label}"
value="${obj.value}" checked="checked" />
</c:when>
<c:otherwise>
<form:radiobutton path="elevetorHandlingFlg"
id="elevetor-${status.index}" label="${obj.label}"
value="${obj.value}" />
</c:otherwise>
</c:choose>
</c:forEach>
<div>
<span>車椅子利用可能有無</span>
</div>
<c:forEach var="obj" items="${wheelchairHandlingFlgList}"
varStatus="status">
<c:choose>
<c:when test="${obj.checked}">
<form:radiobutton path="wheelchairHandlingFlg"
id="wheelchair-${obj.checked }" label="${obj.label}"
value="${obj.value}" checked="checked" />
</c:when>
<c:otherwise>
<form:radiobutton path="wheelchairHandlingFlg"
id="wheelchair-${obj.checked }" label="${obj.label}"
value="${obj.value}" />
</c:otherwise>
</c:choose>
</c:forEach>
<div>
<span>AED設置有無</span>
</div>
<c:forEach var="obj" items="${aedHandlingFlgList}" varStatus="status">
<c:choose>
<c:when test="${obj.checked }">
<form:radiobutton path="aedHandlingFlg"
id="aedHandlingFlg-${obj.checked }" label="${obj.label}"
value="${obj.value}" checked="checked" />
</c:when>
<c:otherwise>
<form:radiobutton path="aedHandlingFlg"
id="aedHandlingFlg-${obj.checked }" label="${obj.label}"
value="${obj.value}" />
</c:otherwise>
</c:choose>
</c:forEach>
</c:if>
<form:hidden path="updateCount" value="${updateCount}" />
<div>
<input type="submit" value="更新"
formAction="${pageContext.request.contextPath}/settingController/update" />
<input type="submit" value="削除"
formAction="${pageContext.request.contextPath}/settingController/delete" />
</div>
</form:form>
</body>
</html>
で、意図的に例外をスローさせたいので、ブレークポイントを貼っておく。

そしたらば、「サーバー」タブで、該当するアプリケーションサーバーを選択して右クリックし、「デバッグ(D)」を選択。

アプリケーションサーバーが起動したら、ブラウザでアクセス。

「パースペクティブ」を「デバッグ」に切り替えて、「変数」タブで該当する変数を選択した状態で右クリックし、「値の変更(C)...」を選択。

nullと入力し、「OK」押下。

で、「F6」キーを押下で、デバッグを進めると、独自例外クラスをスローする処理に勧めることが確認できました。

あとは、「F8」でデバッグを進めます。

⇧ エラーメッセージを表示できました。
というわけで、Javaだと、戻り値は1つのデータ型しか返せないので、処理をsuccessかerrorかで変えたい場合は、
- 独自のクラスで、successかerrorか判別できるフィールドを持たせる
- errorの場合は例外を投げてしまう
のどっちかになるのかしら?
毎度モヤモヤ感が半端ない...
今回はこのへんで。