Подтвердить что ты не робот

Как вернуть HTTP 404 JSON/XML-ответ в JAX-RS (Джерси) на Tomcat?

У меня есть следующий код:

@Path("/users/{id}")
public class UserResource {

    @Autowired
    private UserDao userDao;

    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public User getUser(@PathParam("id") int id) {
        User user = userDao.getUserById(id);
        if (user == null) {
            throw new NotFoundException();
        }
        return user;
    }

Если я запрашиваю пользователя, который не существует, например /users/1234, с "Accept: application/json", этот код возвращает ответ HTTP 404, как и следовало ожидать, но возвращает Content-Type на text/html и сообщение тела html. Аннотация @Produces игнорируется.

Это проблема кода или проблемы конфигурации?

4b9b3361

Ответ 1

Ваша аннотация @Produces игнорируется, потому что неперехваченные исключения обрабатываются во время выполнения jax-rs с использованием предопределенного (по умолчанию) ExceptionMapper. Если вы хотите настроить возвращенное сообщение в случае конкретного исключения, вы можете создать свой собственный ExceptionMapper, чтобы справиться с этим. В вашем случае вам нужно обработать исключение NotFoundException и запросить заголовок "accept" для запрошенного типа ответа:

@Provider
public class NotFoundExceptionHandler implements ExceptionMapper<NotFoundException>{

    @Context
    private HttpHeaders headers;

    public Response toResponse(NotFoundException ex){
        return Response.status(404).entity(yourMessage).type( getAcceptType()).build();
    }

    private String getAcceptType(){
         List<MediaType> accepts = headers.getAcceptableMediaTypes();
         if (accepts!=null && accepts.size() > 0) {
             //choose one
         }else {
             //return a default one like Application/json
         }
    }
}

Ответ 2

Вы можете использовать ответ Response. Пример ниже:

@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response get(@PathParam("id") Long id) {
    ExampleEntity exampleEntity = getExampleEntityById(id);

    if (exampleEntity != null) {
        return Response.ok(exampleEntity).build();
    }

    return Response.status(Status.NOT_FOUND).build();
}

Ответ 3

что 404 возвращается вашим сервером, так как ожидается, что вы передадите вещи в следующей форме

/users/{id}

но вы передаете его как

/users/user/{id}

какой ресурс вообще не существует

попробуйте доступ к ресурсу как /users/1234

EDIT:

создать класс, например

class RestResponse<T>{
private String status;
private String message;
private List<T> objectList;
//gettrs and setters
}

теперь, если вы хотите отклик для User, вы можете создать его как следующий

RestResponse<User> resp = new RestResponse<User>();
resp.setStatus("400");
resp.setMessage("User does not exist");

и подпись вашего метода отдыха будет выглядеть следующим образом

public RestResponse<User> getUser(@PathParam("id") int id)

в то время как в случае успешного ответа вы можете установить такие вещи, как

RestResponse<User> resp = new RestResponse<User>();
List<User> userList = new ArrayList<User>();
userList.add(user);//the user object you want to return
resp.setStatus("200");
resp.setMessage("User exist");
resp.setObjectList(userList);

Ответ 4

Просто это сработало для меня - ничего необычного. Это было с Jboss EAP 7 и JAX-RS:

jsonText = "{\n" + "   \"account\": {\n" + "       \"billing_account\": \"" + ipResponse.getResult().getParentGUID() + "\",\n" + "}" + ",\n" + "}";
parser = new JSONParser();

//build our JSON response object
try {
    jSONObject = (JSONObject) parser.parse(jsonText);
    return Response.status(200).entity(jSONObject.toJSONString()).build();
} catch (ParseException e) {
    e.printStackTrace();
    jsonEText = "{\n" + "   \"account\": {\n" + "       \"billing_account\": \"" + e.getMessage() + "\",\n" + "}" + ",\n" + "}";
    jSONObject = (JSONObject) parser.parse(jsonEText);
    return Response.status(404).entity(jSONObject.toJSONString()).build();
}