Skip to content

Commit

Permalink
#387 增加对前缀为“不正确的请求或参数”的异常处理,使之返回400。同时增加日志。
Browse files Browse the repository at this point in the history
  • Loading branch information
kfchu committed Apr 7, 2018
1 parent 45d142d commit bafcbc6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.vip.saturn.job.console.controller.rest;

import com.vip.saturn.job.console.controller.gui.AbstractGUIController;
import com.vip.saturn.job.console.domain.RestApiErrorResult;
import com.vip.saturn.job.console.exception.SaturnJobConsoleException;
import com.vip.saturn.job.console.exception.SaturnJobConsoleHttpException;
import com.vip.saturn.job.console.utils.SaturnConstants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -21,6 +25,8 @@
@ControllerAdvice
public class RestApiExceptionHandlerController {

private static final Logger log = LoggerFactory.getLogger(RestApiExceptionHandlerController.class);

private final static String NOT_EXISTED_PREFIX = "does not exists";

@ExceptionHandler
Expand All @@ -31,24 +37,46 @@ public ResponseEntity<Object> handleSaturnJobConsoleException(SaturnJobConsoleEx
}

if (message.contains(NOT_EXISTED_PREFIX)) {
log.warn("Resource not found while calling REST API:" + message);
return constructErrorResponse(message, HttpStatus.NOT_FOUND);
} else if (message.startsWith(SaturnConstants.INVALID_PARAMETER_PREFIX)) {
String tmpMsg = StringUtils.removeStart(message, SaturnConstants.INVALID_PARAMETER_PREFIX);
log.warn("Bad request while calling REST API:" + tmpMsg);
return constructErrorResponse(tmpMsg, HttpStatus.BAD_REQUEST);
}

log.error("Internal server error happens while calling REST API:" + message);
return constructErrorResponse(message, HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler
public ResponseEntity<Object> handleSaturnJobConsoleHttpException(SaturnJobConsoleHttpException e) {
HttpHeaders httpHeaders = new HttpHeaders();

SaturnJobConsoleHttpException saturnJobConsoleHttpException = (SaturnJobConsoleHttpException) e;
int statusCode = saturnJobConsoleHttpException.getStatusCode();

int statusCode = e.getStatusCode();
if (statusCode == HttpStatus.CREATED.value()) {
return new ResponseEntity<>(httpHeaders, HttpStatus.CREATED);
}

return constructErrorResponse(e.getMessage(), HttpStatus.valueOf(statusCode));
HttpStatus httpStatus;
try {
httpStatus = HttpStatus.valueOf(statusCode);
} catch (IllegalArgumentException e1) {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
}

String message = e.getMessage();
if (StringUtils.isBlank(message)) {
message = e.toString();
}

if (httpStatus.is5xxServerError()) {
log.error("Internal server error happens while calling REST API:" + message);
} else {
log.warn("Exception happens while calling REST API:" + message);
}

return constructErrorResponse(message, httpStatus);
}

@ExceptionHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.text.ParseException;
import java.util.*;

import static com.vip.saturn.job.console.utils.SaturnConstants.INVALID_PARAMETER_PREFIX;

/**
* @author hebelala
*/
Expand Down Expand Up @@ -82,6 +84,7 @@ public class JobServiceImpl implements JobService {
private static final int DEFAULT_MAX_JOB_NUM = 100;
private static final int DEFAULT_INTERVAL_TIME_OF_ENABLED_REPORT = 5;
private static final String ERR_MSG_PENDING_STATUS = "job:[{}] item:[{}] on executor:[{}] execution status is PENDING as {}";

@Resource
private RegistryCenterService registryCenterService;

Expand Down Expand Up @@ -526,38 +529,38 @@ public void setPreferList(String namespace, String jobName, String preferList, S
private void validateJobConfig(JobConfig jobConfig) throws SaturnJobConsoleException {
// 作业名必填
if (jobConfig.getJobName() == null || jobConfig.getJobName().trim().isEmpty()) {
throw new SaturnJobConsoleException("作业名必填");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "作业名必填");
}
// 作业名只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_
if (!jobConfig.getJobName().matches("[0-9a-zA-Z_]*")) {
throw new SaturnJobConsoleException("作业名只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "作业名只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_");
}
// 依赖的作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,
if (jobConfig.getDependencies() != null && !jobConfig.getDependencies().matches("[0-9a-zA-Z_,]*")) {
throw new SaturnJobConsoleException("依赖的作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "依赖的作业只允许包含:数字0-9、小写字符a-z、大写字符A-Z、下划线_、英文逗号,");
}
// 作业类型必填
if (jobConfig.getJobType() == null || jobConfig.getJobType().trim().isEmpty()) {
throw new SaturnJobConsoleException("作业类型必填");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "作业类型必填");
}
// 验证作业类型
if (JobType.getJobType(jobConfig.getJobType()).equals(JobType.UNKOWN_JOB)) {
throw new SaturnJobConsoleException("作业类型未知");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "作业类型未知");
}
// 如果是JAVA作业
if ((jobConfig.getJobType().equals(JobType.JAVA_JOB.name()) || jobConfig.getJobType()
.equals(JobType.MSG_JOB.name())) && (jobConfig.getJobClass() == null || jobConfig.getJobClass().trim()
.isEmpty())) {
// 作业实现类必填
throw new SaturnJobConsoleException("对于JAVA或消息作业,作业实现类必填");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "对于JAVA或消息作业,作业实现类必填");
}
validateCronFieldOfJobConfig(jobConfig);

validateShardingItemFieldOfJobConfig(jobConfig);

// 不能添加系统作业
if (jobConfig.getJobMode() != null && jobConfig.getJobMode().startsWith(JobMode.SYSTEM_PREFIX)) {
throw new SaturnJobConsoleException("作业模式有误,不能添加系统作业");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "作业模式有误,不能添加系统作业");
}
}

Expand All @@ -567,13 +570,13 @@ private void validateCronFieldOfJobConfig(JobConfig jobConfig) throws SaturnJobC
.equals(JobType.SHELL_JOB.name())) {
// cron表达式必填
if (jobConfig.getCron() == null || jobConfig.getCron().trim().isEmpty()) {
throw new SaturnJobConsoleException("对于JAVA/SHELL作业,cron表达式必填");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "对于JAVA/SHELL作业,cron表达式必填");
}
// cron表达式语法验证
try {
CronExpression.validateExpression(jobConfig.getCron());
} catch (ParseException e) {
throw new SaturnJobConsoleException("cron表达式语法有误" + e);
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "cron表达式语法有误" + e);
}
} else {
jobConfig.setCron(""); // 其他类型的不需要持久化保存cron表达式
Expand All @@ -583,7 +586,7 @@ private void validateCronFieldOfJobConfig(JobConfig jobConfig) throws SaturnJobC
private void validateShardingItemFieldOfJobConfig(JobConfig jobConfig) throws SaturnJobConsoleException {
if (jobConfig.getLocalMode() != null && jobConfig.getLocalMode()) {
if (jobConfig.getShardingItemParameters() == null) {
throw new SaturnJobConsoleException("对于本地模式作业,分片参数必填。");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "对于本地模式作业,分片参数必填。");
} else {
String[] split = jobConfig.getShardingItemParameters().split(",");
boolean includeXing = false;
Expand All @@ -595,18 +598,18 @@ private void validateShardingItemFieldOfJobConfig(JobConfig jobConfig) throws Sa
}
}
if (!includeXing) {
throw new SaturnJobConsoleException("对于本地模式作业,分片参数必须包含如*=xx。");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "对于本地模式作业,分片参数必须包含如*=xx。");
}
}
} else {
// 分片参数不能小于分片总数
if (jobConfig.getShardingTotalCount() == null || jobConfig.getShardingTotalCount() < 1) {
throw new SaturnJobConsoleException("分片数不能为空,并且不能小于1");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "分片数不能为空,并且不能小于1");
}
if ((jobConfig.getShardingTotalCount() > 0) && (jobConfig.getShardingItemParameters() == null || jobConfig
.getShardingItemParameters().trim().isEmpty()
|| jobConfig.getShardingItemParameters().split(",").length < jobConfig.getShardingTotalCount())) {
throw new SaturnJobConsoleException("分片参数不能小于分片总数");
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + "分片参数不能小于分片总数");
}
}
}
Expand All @@ -630,11 +633,11 @@ private void addOrCopyJob(String namespace, JobConfig jobConfig, String jobNameC
String jobName = jobConfig.getJobName();
JobConfig4DB oldJobConfig = currentJobConfigService.findConfigByNamespaceAndJobName(namespace, jobName);
if (oldJobConfig != null) {
throw new SaturnJobConsoleException(String.format("该作业(%s)已经存在", jobName));
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + String.format("该作业(%s)已经存在", jobName));
}
int maxJobNum = getMaxJobNum();
if (jobIncExceeds(namespace, maxJobNum, 1)) {
throw new SaturnJobConsoleException(String.format("总作业数超过最大限制(%d),作业名%s创建失败", maxJobNum, jobName));
throw new SaturnJobConsoleException(INVALID_PARAMETER_PREFIX + String.format("总作业数超过最大限制(%d),作业名%s创建失败", maxJobNum, jobName));
} else {
if (jobNameCopied == null) {
persistJob(namespace, jobConfig, createdBy);
Expand Down Expand Up @@ -1615,7 +1618,7 @@ public void updateJobCron(String namespace, String jobName, String cron, Map<Str
cron0 = cron0.trim();
CronExpression.validateExpression(cron0);
} catch (ParseException e) {
throw new SaturnJobConsoleException("The cron expression is valid: " + cron);
throw new SaturnJobConsoleException("The cron expression is invalid: " + cron);
}
} else {
cron0 = "";
Expand Down Expand Up @@ -1655,7 +1658,7 @@ public void updateJobCron(String namespace, String jobName, String cron, Map<Str
curatorFrameworkOp.update(JobNodePath.getConfigNodePath(jobName, CONFIG_ITEM_CRON), newCron);
}
} else {
throw new SaturnJobConsoleException("The job is not found: " + jobName);
throw new SaturnJobConsoleException("The job does not exists: " + jobName);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ public class SaturnConstants {

public static final String NO_GROUPS_LABEL = "未分组";

public static final String INVALID_PARAMETER_PREFIX = "不正确的请求或参数:";

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.vip.saturn.job.console.springboot.test;

import static com.vip.saturn.job.console.utils.SaturnConstants.INVALID_PARAMETER_PREFIX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;
Expand Down Expand Up @@ -169,6 +170,19 @@ public void testCreateFailAsUnExpectedExceptionThrows() throws Exception {
assertEquals("error message not equal", customErrMsg, message);
}

@Test
public void testCreateFailAsJobAlreadyExisted() throws Exception {
JobEntity jobEntity = constructJobEntity("job2");
String errMsg = INVALID_PARAMETER_PREFIX + String.format("该作业(job2)已经存在");
willThrow(new SaturnJobConsoleException(errMsg)).given(restApiService).createJob(any(String.class), any(JobConfig.class));

MvcResult result = mvc.perform(post("/rest/v1/domain/jobs").contentType(MediaType.APPLICATION_JSON).content(jobEntity.toJSON()))
.andExpect(status().isBadRequest()).andReturn();

String message = fetchErrorMessage(result);
assertEquals("error message not equal", errMsg, message);
}

@Test
public void testQuerySuccessfully() throws Exception {
String jobName = "job1";
Expand Down

0 comments on commit bafcbc6

Please sign in to comment.