Obrigado, Abelardo, é isso mesmo!
Com o código do final do curso, mudei o start do servidor de teste com o ajuste que você passou.
Uma chamada a removeProduto() com um carrinho inexistente
curl -v -X DELETE http://localhost:8080/carrinhos/2/produtos/1
gera o seguinte log no console somente se o ajuste for feito:
nov 28, 2016 5:19:07 PM org.glassfish.grizzly.http.server.HttpHandler$1 run
DETALHADO: service exception
java.lang.NullPointerException
at br.com.alura.loja.resource.CarrinhoResource.removeProduto(CarrinhoResource.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
.......
E o resultado do comando curl:
> DELETE /carrinhos/2/produtos/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.50.1
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Date: Mon, 28 Nov 2016 19:19:07 GMT
< Connection: close
< Content-Length: 0
Importante notar que um GET para um carrinho inexistente não dá exceção nem erro 500, apenas uma mensagem de sucesso 204.
O código do final do curso retorna o próprio carrinho, ou seja, retorna null neste caso.
Ou seja: retorno de null não é considerado erro pela API!
$ curl -v http://localhost:8080/carrinhos/2
* timeout on name lookup is not supported
* Trying ::1...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /carrinhos/2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.50.1
> Accept: */*
>
< HTTP/1.1 204 No Content
< Date: Mon, 28 Nov 2016 19:21:45 GMT