title: HttpClient throws exception on response code 404. Is this by design or am I doing something wrong?
body: <p>I am starting today with Micronaut.
  I built this controller:</p>
  
  <pre><code>@Controller
  public class MyController implements MyApi{
  
  @Override
  public String doit() {
      throw new NotFoundException();
      }
  }
  </code></pre>
  
  <p>and this exception handler:</p>
  
  <pre><code>@Produces
  @Singleton
  @Requires(classes = { NotFoundException.class, ExceptionHandler.class})
  public class NotFoundExceptionHandler implements ExceptionHandler&lt;NotFoundException, HttpResponse&gt; {
  
  @Override
  public HttpResponse handle(HttpRequest request, NotFoundException exception) {
      return HttpResponseFactory.INSTANCE.status(HttpStatus.NOT_FOUND);
  }
  </code></pre>
  
  <p>}</p>
  
  <p>And this test:</p>
  
  <pre><code>@MicronautTest
  public class MyControllerIT {
  
  @Inject
  @Client("/")
  HttpClient client;
  
  @Test
  public void testHello() {
      HttpRequest&lt;String&gt; request = HttpRequest.GET("/myController");
      HttpResponse&lt;String&gt; body = client.toBlocking().exchange(request);
  
      assertThat(body.getStatus(), is(HttpStatus.NOT_FOUND));
      }
  }
  </code></pre>
  
  <p>My expectation is that it would pass: I would get a response back with no content, HTTP code 404, message "Not found" and I would be done.</p>
  
  <p>But, instead, I get:</p>
  
  <pre><code>io.micronaut.http.client.exceptions.HttpClientResponseException: Not Found
  
  at io.micronaut.http.client.DefaultHttpClient$10.channelRead0(DefaultHttpClient.java:1799)
  at io.micronaut.http.client.DefaultHttpClient$10.channelRead0(DefaultHttpClient.java:1739)
  at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.micronaut.http.netty.stream.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:185)
  at io.micronaut.http.netty.stream.HttpStreamsClientHandler.channelRead(HttpStreamsClientHandler.java:180)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
  at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328)
  at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302)
  at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
  at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1421)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
  at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
  at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)
  at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
  at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:697)
  at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:632)
  at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:549)
  at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:511)
  at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:918)
  at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
  at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
  at java.base/java.lang.Thread.run(Thread.java:834)
  </code></pre>
  
  <p>I found this <a href="https://docs.micronaut.io/latest/api/io/micronaut/http/client/exceptions/HttpClientResponseException.html" rel="nofollow noreferrer">HttpClientResponseException</a> documentation that describes <code>An exception that occurs when a response returns an error code equal to or greater than 400.</code></p>
  
  <p>Is this really the expected behavior? It seems a little bit odd that it forces me to handle it as an exception when the error code > 400.</p>
  
  <p>Did I do something wrong in my setup?</p>