我正在尝试使用具有异常映射的Jersey 2.22.2
和Jetty 9.1.1.v20140108
来实现Web服务。下列类表示已实现Mapper的Exception类。
@Provider
public class NotFoundException extends Exception implements ExceptionMapper<NotFoundException> {
private static final long serialVersionUID = 1L;
public NotFoundException() {
}
public NotFoundException(String s) {
super(s);
}
@Context
private UriInfo uriInfo;
@Override
public Response toResponse(NotFoundException e) {
Status status = Status.NOT_FOUND;
ErrorWrapper errorWrapper = new ErrorWrapper();
errorWrapper.setStatusCode(status.getStatusCode());
errorWrapper.setTitle(status.getReasonPhrase());
errorWrapper.setErrorMessage("The resource you're looking for cannot be found.");
errorWrapper.setApiPath(uriInfo.getAbsolutePath().getPath());
return Response.status(status).entity(errorWrapper).type(MediaType.APPLICATION_JSON).build();
}
}
为了测试它是否正常工作,我创建了一个仅抛出上述异常的端点,如下所示:
@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public Response test() throws NotFoundException {
throw new NotFoundException();
}
调用此端点将返回一个JSON
,如下所示:
{
"statusCode": 404,
"title": "Not Found",
"errorMessage": "The resource you're looking for cannot be found.",
"apiPath": "/users/test"
}
因此,我可以肯定地认为异常映射正在工作。
现在,如果DAO
方法返回null
对象,例如,当尝试获取尚不存在的数据库行时,我想做的就是抛出此异常。以下是我的实现尝试:
DAO:
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id)
.fetchOne()
.into(User.class);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
服务:
public User getUserById(Integer id) throws NotFoundException {
return userDao.getUserById(id);
}
资源:
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserById(@PathParam("id") Integer id) throws NotFoundException {
User user = new UserService().getUserById(id);
return Response.ok(user).build();
}
但是,当我使用尚不存在的ID调用端点(2)并获得NullPointerException
时,我仍然从Jetty获得了HTTP 500 Request Failed
,而不是从NotFoundException
中获得了404,例如这个:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" />
<title>Error 500 </title>
</head>
<body>
<h2>HTTP ERROR: 500</h2>
<p>Problem accessing /users/2. Reason:
<pre> Request failed.</pre>
</p>
<hr /><i><small>Powered by Jetty://</small></i>
</body>
</html>
真的可以为此提供一些帮助。
您没有抛出NotFoundException。您的代码抛出NullPointerException。
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id)
//The NullPointerException is coming from the following line
.fetchOne()
.into(User.class);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
您需要将代码更改为以下内容:
public User getUserById(Integer id) throws NotFoundException {
try (DSLContext ctx = new DSLContextFactory("iotrest")
.getDSLContext(getDbDataSource("iotrest"))) {
User user = queries.getUserById(ctx, id);
if (user == null
|| user.getId() == null) {
throw new NotFoundException("User with id " + id + " not found");
}
user.fetchOne()
.into(User.class);
}
UserAccessRights userAccessRights = queries.getUserAccessRights(ctx, user.getId())
.fetchOne()
.into(UserAccessRights.class);
if (userAccessRights == null) {
throw new NotFoundException("Access rights not found for user id " + id);
}
setUserAccessRights(user, userAccessRights);
return user;
}
}
@galusben
的建议有助于找到解决方案。显然,这条线正在引发NPE。
User user = queries.getUserById(ctx, id)
.fetchOne()
.into(User.class);
所以,基本上我所做的就是,在将结果集放入User
之前,我像这样检查了记录本身是否存在于表中。
UsersRecord usersRecord = queries.getUserById(ctx, id).fetchOne();
然后,对该对象进行空检查,然后将记录存储到pojo中。
if (usersRecord == null) {
throw new NotFoundException("User with id " + id + " not found");
}
User user = usersRecord.into(User.class);
像这样测试端点:
http://localhost:7000/users/2
服务器现在终于返回NotFoundException
{
"statusCode": 404,
"title": "Not Found",
"errorMessage": "The resource you're looking for cannot be found.",
"apiPath": "/users/2"
}