Skip to main content
info

You're seeing the release note of an old version. Check out the latest release note.

v0.85.0

May 17, 2019

New features

  • You can now bind your Service to a certain HTTP method or enable HTTP content-type negotiation very easily with the new ServerBuilder.route() method. #1737

    ServerBuilder sb = new ServerBuilder();
    sb.route()
    .get("/users/{id}")
    .delete("/users/{id}")
    .post("/users")
    .consumes(MediaType.JSON)
    .produces(MediaType.JSON_UTF_8)
    .build(new MyUserService());

    // You can also configure using a lambda expression.
    sb.withRoute(b -> {
    b.path("/foo")
    .build(new MyFooService());
    });
  • It is now also possible to specify different settings for different services using the new route() method. It means you can specify a large timeout for a certain service only conveniently. #1737

    ServerBuilder sb = new ServerBuilder();
    sb.route()
    .path("/long_poll")
    .requestTimeoutMillis(0) // Disable timeout for /service.
    .build(new MyLongPollingService());
    sb.route()
    .path("/get_now")
    .build(new MyOtherService()); // Use the default timeout.
    ```java

  • We revamped our HttpHeaders API to make it cleaner and safer. #1731

    • HttpHeaders has been split into three types:

      • RequestHeaders for request headers with :method and :path header
      • ResponseHeaders for response headers with :status header
      • HttpHeaders for trailers and other headers
      • RequestHeaders and ResponseHeaders extend HttpHeaders.
    • HttpHeaders and its subtypes are immutable and thus must be built using a factory method or a builder.

    • Quick examples:

      RequestHeaders reqHdrs = RequestHeaders.of(HttpMethod.GET, "/get",
      HttpHeaderNames.ACCEPT, MediaType.JSON_UTF_8);
      RequestHeaders newReqHdrs = reqHdrs.toBuilder()
      .add("foo", "bar")
      .build();
      ResponseHeaders resHdrs = ResponseHeaders.of(200 /* OK */);

      HttpHeaders hdrs = HttpHeaders.builder()
      .add("alice", "bob");
      .build();
      HttpHeaders newHdrs = hdrs.withMutations(builder -> {
      builder.add("charlie", "debora");
      });
    • See HttpHeaders Javadoc for more examples.

  • You can now test your Armeria app with JUnit 5. A new module armeria-testing-junit5 has been added with the following extensions: #1736

    • com.linecorp.armeria.testing.junit.server.ServerExtension
    • com.linecorp.armeria.testing.junit.server.SelfSignedCertificateExtension
    • com.linecorp.armeria.testing.junit.common.EventLoopGroupExtension
    • com.linecorp.armeria.testing.junit.common.EventLoopExtension
  • You can now customize the behavior of gRPC JSON marshaller. #1696 #1753

    ServerBuilder sb = new ServerBuilder();
    sb.service(new GrpcServiceBuilder()
    .addService(new MyServiceImpl())
    .supportedSerializationFormats(GrpcSerializationFormats.values())
    .jsonMarshallerCustomizer(marshaller -> {
    marshaller.preservingProtoFieldNames(true);
    })
    .build());
  • You can now write a unary gRPC client without depending on grpc-java at all. #1703 #1748 #1751

    HelloRequest req = HelloRequest.newBuilder()
    .setName("Alice")
    .build();
    UnaryGrpcClient client = new UnaryGrpcClient(HttpClient.of("http://127.0.0.1:8080"));
    byte[] resBytes = client.execute("/com.example.HelloService/Greet",
    req.toByteArray()).join();
    HelloResponse res = HelloResponse.parseFrom(resBytes);
  • You can now use GrpcServiceRegistrationBean to register a gRPC service when using Spring Boot integration. #1749

    @Bean
    public GrpcServiceRegistrationBean helloService() {
    return new GrpcServiceRegistrationBean()
    .setServiceName("helloService")
    .setService(new GrpcServiceBuilder()
    .addService(new HelloService())
    .supportedSerializationFormats(GrpcSerializationFormats.values())
    .enableUnframedRequests(true)
    .build())
    .setDecorators(LoggingService.newDecorator())
    .setExampleRequests(List.of(ExampleRequest.of(HelloServiceGrpc.SERVICE_NAME,
    "Hello",
    HelloRequest.newBuilder()
    .setName("Armeria")
    .build())));
    }
  • You can now use wildcard pattern when specifying built-in properties in Logback RequestContextExportingAppender. #489 #1742

Bug fixes

  • Trailing slashes in a path pattern is now handled correctly. #1741
  • It is now disallowed to apply CorsDecorator more than once. #1740
  • HttpTracingClient and HttpTracingService now adds a valid addressable http.url tag. #1733 #1762
  • SessionProtocol and SerializationFormat are now added to http.protocol and http.serfmt tag instead.

Breaking changes

  • Artifact armeria-testing has been renamed to armeria-testing-junit4. Please update your project dependencies. #1736
  • Many places in the public API that use HttpHeaders as a parameter or a return value have been changed due to the revamped HttpHeaders API. #1731
  • The following ServerBuilder methods were removed:
    • virtualHost(VirtualHost)
    • defaultVirtualHost(VirtualHost)

Deprecations

  • The default prefix found in various configuration properties has been deprecated. Use the property setters without the default prefix. #1737

    ServerBuilder sb = new ServerBuilder();
    // Do NOT use this:
    sb.defaultRequestTimeout(...);
    // Use this:
    sb.requestTimeout(...);
  • HttpHeaders.EMPTY has been deprecated. Use HttpHeaders.of().

Dependencies

  • Dropwizard Metrics 4.0.5 -> 4.1.0
  • Jetty 9.4.17 -> 9.4.18
  • Project Reactor 3.2.8 -> 3.2.9

Thank you

This release was possible thanks to the following contributors who shared their brilliant ideas and awesome pull requests:

@hyangtack@ejona86@anuraaga@masonshin@huydx@trustin@minwoox@codefromthecrypt@karthikraman22@delegacy@matsumana

Like Armeria?
Star us ⭐️

×