jax-rs异常映射器实现问题

问题描述 投票:0回答:2

我正在尝试使用具有异常映射的Jersey 2.22.2Jetty 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>

真的可以为此提供一些帮助。

exception jersey mapping jax-rs
2个回答
0
投票

您没有抛出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;
        }
    }

0
投票

@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"
}
© www.soinside.com 2019 - 2024. All rights reserved.