PageSourceSearch

https://armeria.dev/assets/js/d77ec072.f4411378.js

js armeria.dev collected 2026-10-03 23:25:04 UTC 35,150 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkarmeria_site=self.webpackChunkarmeria_site||[]).push([["4319"],{34434(e,r,i){i.r(r),i.d(r,{metadata:()=>a,default:()=>d,frontMatter:()=>o,contentTitle:()=>s,toc:()=>l,assets:()=>c});var a=JSON.parse('{"id":"1.17.0","title":"v1.17.0","description":"\u{1F31F} New features","source":"@site/src/content/release-notes/1.17.0.mdx","sourceDirName":".","slug":"/1.17.0","permalink":"/release-notes/1.17.0","draft":false,"unlisted":false,"editUrl":"https://github.com/line/armeria/edit/main/site/src/content/release-notes/1.17.0.mdx","tags":[],"version":"current","frontMatter":{"date":"2022-07-06T00:00:00.000Z"},"sidebar":"defaultSidebar","previous":{"title":"v1.17.1","permalink":"/release-notes/1.17.1"},"next":{"title":"v1.16.2","permalink":"/release-notes/1.16.2"}}'),n=i(74848),t=i(28453);let o={date:new Date("2022-07-06T00:00:00.000Z")},s="v1.17.0",c={},l=[{value:"\u{1F31F} New features",id:"-new-features",level:2},{value:"Kotlin",id:"kotlin",level:3},{value:"\u{1F4C8} Improvements",id:"-improvements",level:2},{value:"\u{1F6E0}\uFE0F Bug fixes",id:"\uFE0F-bug-fixes",level:2},{value:"\u{1F3DA}\uFE0F Deprecations",id:"\uFE0F-deprecations",level:2},{value:"\u2622\uFE0F Breaking changes",id:"\uFE0F-breaking-changes",level:2},{value:"\u26D3 Dependencies",id:"-dependencies",level:2},{value:"\u{1F647} Thank you",id:"-thank-you",level:2}];function h(e){let r={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components},{ThankYou:i}=r;return i||function(e,r){throw Error("Expected "+(r?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("ThankYou",!0),(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(r.header,{children:[(0,n.jsx)(r.h1,{id:"v1170",children:"v1.17.0"}),(0,n.jsx)(r.p,{children:(0,n.jsx)(r.em,{children:"July 6, 2022"})})]}),"\n",(0,n.jsx)(r.h2,{id:"-new-features",children:"\u{1F31F} New features"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now easily send and receive RESTful APIs using ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/RestClient.html",children:"RestClient"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4263",children:"#4263"})]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["Java","\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'RestClient restClient = RestClient.of("...");\nCompletableFuture<ResponseEntity<Customer>> response =\n    restClient.get("/api/v1/customers/{customerId}")\n              .pathParam("customerId", "0000001")\n              .execute(Customer.class);\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["Kotlin","\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-kotlin",children:'val restClient: RestClient = RestClient.of("...");\nval response: ResponseEntity<Customer> =\n   restClient\n     .get("/api/v1/customers/{customerId}")\n     .pathParam("customerId", "0000001")\n     .execute<Customer>()  // a suspend function\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["Scala","\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-scala",children:'val restClient: ScalaRestClient = ScalaRestClient("...")\nval response: Future[ResponseEntity[Result]] =\n  restClient.post("/api/v1/customers")\n            .contentJson(new Customer(...))\n            .execute[Result]()\n'})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now configure a timeout for an ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/Endpoint.html",children:"Endpoint"})," selection of an\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/DynamicEndpointGroup.html",children:"DynamicEndpointGroup"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4246",children:"#4246"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'DnsAddressEndpointGroup delegate = DnsAddressEndpointGroup.of(...);\nHealthCheckedEndpointGroup healthGroup =\n  HealthCheckedEndpointGroup\n    .builder(delegate, "/health")\n    .selectionTimeout(Duration.ofSeconds(10)) // \u{1F448}\u{1F448}\u{1F448}\n    .build();\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now inject dependencies in an annotation using ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/DependencyInjector.html",children:"DependencyInjector"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4006",children:"#4006"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4202",children:"#4202"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'// Inject authClient that is needed to create the AuthDecorator.\nWebClient authClient = ...\nDependencyInjector injector =\n    DependencyInjector.ofSingletons(new AuthDecorator(authClient));
1\nserverBuilder.dependencyInjector(dependencyInjector, true);\n\n// An annotated service that uses AuthDecorator.\n@Get("/foo")\n@Decorator(AuthDecorator.class)\npublic FooResponse foo(FooRequest req) {\n    // Authrorized request.\n    ...\n}\n\n// authClient is injected.\nclass AuthDecorator implements DecoratingHttpServiceFunction {\n    AuthDecorator(WebClient authClient) { ... }\n\n    @Override\n    public HttpResponse serve(HttpService delegate,\n                              ServiceRequestContext ctx,\n                              HttpRequest req)\n            throws Exception {\n        // Authorize the request.\n        ...\n    }\n}\n'})}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["Set ",(0,n.jsx)(r.code,{children:"armeria.enable-auto-injection"})," to ",(0,n.jsx)(r.code,{children:"true"})," to apply ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/spring/SpringDependencyInjector.html",children:"SpringDependencyInjector"})," automatically\nwhen using Spring Boot integration.","\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-yaml",children:"// in application.yml\narmeria:\n  ports:\n    ...\n  enable-auto-injection: true  // \u{1F448}\u{1F448}\u{1F448}\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now customize the length of string fields or container fields\nof Thrift messages using ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/thrift/THttpServiceBuilder.html",children:"THttpServiceBuilder"})," or ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/thrift/ThriftClientBuilder.html",children:"ThriftClientBuilder"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4024",children:"#4024"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4226",children:"#4226"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'THttpService.builder()\n            .addService(new MyThriftService())\n            .maxRequestStringLength(MAX_STRING_LENGTH)\n            .maxRequestContainerLength(MAX_CONTAINER_LENGTH)\n            .build();\nThriftClients.builder("https://my.server.com")\n             .path("/thrift")\n             .maxResponseStringLength(MAX_STRING_LENGTH)\n             .maxResponseContainerLength(MAX_CONTAINER_LENGTH)\n             .build(HelloService.AsyncIface.class);\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now set attributes to an ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/Endpoint.html",children:"Endpoint"})," using ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/Attributes.html",children:"Attributes"})," and\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/AttributesBuilder.html",children:"AttributesBuilder"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4241",children:"#4241"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'AttributeKey<String> region = AttributeKey.valueOf(MyAttrs.class, "region");\nAttributes attrs =\n  Attributes\n    .builder()\n    .set(region, "us-west-1")\n    .build();\n\nEndpoint endpointA = ...;\nEndpoint endpointB = endpointA.withAttrs(attrs);\nassert endpointB.attr(region).equals("us-west-1");\nassert !endpointA.equals(endpointB)\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now use ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/multipart/MultipartFile.html",children:"MultipartFile"})," to get the actual filename of an uploaded file\nthrough ",(0,n.jsx)(r.code,{children:"multipart/form-data"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4262",children:"#4262"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'@Consumes(MediaTypeNames.MULTIPART_FORM_DATA)\n@Post("/upload")\npublic HttpResponse upload(MultipartFile multipartFile) {\n  // The name parameter of the "content-disposition" header\n  String name = multipartFile.name();\n  // The filename parameter of the "content-disposition" header\n  String filename = multipartFile.filename();\n  // The file that stores the multipart content.\n  File file = multipartFile.file();\n  ...\n}\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now read a range of b
1ytes using ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/ByteStreamMessage.html",children:"ByteStreamMessage"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4058",children:"#4058"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:"Path path = ...;\n// Fluently build a `StreamMessage` for a `Path`.\nByteStreamMessage pathContent =\n    StreamMessage.builder(path)\n                 .bufferSize(1024)\n                 .alloc(alloc)\n                 .executor(executor)\n                 .build();\n// Slice a range of a file data\nByteStreamMessage partialContent = pathContent.range(100, 200);\n"})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now map a specific exception to a ",(0,n.jsx)(r.code,{children:"LogLevel"})," in ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/logging/LoggingService.html",children:"LoggingService"})," and\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/logging/LoggingClient.html",children:"LoggingClient"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/3400",children:"#3400"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4090",children:"#4090"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:"LoggingService.builder()\n              .responseLogLevel(IllegalStateException.class,\n                                LogLevel.WARN)\n              .responseLogLevel(IllegalArgumentException.class,\n                                LogLevel.ERROR)\n              ...\n"})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now map a specific exception to an ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/HttpResponse.html",children:"HttpResponse"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4279",children:"#4279"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4283",children:"#4283"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'HttpResponse recovered =\n    response.recover(IllegalStateException.class,\n                     cause -> HttpResponse.of("Fallback"));\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now enable automatic compression for a gRPC response. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4258",children:"#4258"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4266",children:"#4266"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:"GrpcService.builder()\n           .addService(new MyGrpcService())\n           .autoCompression(true)\n           .build();\n"})}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["This only works when the client sends a ",(0,n.jsx)(r.code,{children:"grpc-accept-encoding"})," header and\nthe ",(0,n.jsx)(r.code,{children:"CompressorRegistry"})," has the compressor."]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now add a hook to ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/Server.html",children:"Server"})," and ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/ClientFactory.html",children:"ClientFactory"})," that is called when the\nJVM shuts down. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4015",children:"#4015"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4043",children:"#4043"})]}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-java",children:'server.closeOnJvmShutdown(() -> {\n  System.err.println("Server is stopping soon.");\n}).thenRun(() -> {\n  System.err.println("Server has stopped.");\n});\n'})}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["\n",(0,n.jsxs)(r.p,{children:["You can now customize internal Netty ",(0,n.jsx)(r.code,{children:"ChannelPipeline"})," using\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/ClientFactoryOptions.html#CHANNEL_PIPELINE_CUSTOMIZER",children:"ClientFactoryOptions#CHANNEL_PIPELINE_CUSTOMIZER"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/3907",children:"#3907"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4260",children:"#4260"})]}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"This is an advanced feature and not recommended to use if you are not familiar with\nArmeria and Netty internals."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(r.h3,{id:"kotlin",children:"Kotlin"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["You can now use the Kotlin nullable type (",(0,n.jsx)(r.code,{children:"?"}),") to indicate a nullable parameter in\nan annotated service. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4144",children:"#4144"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4225",children:"#4225"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-kotlin",children:'serverBuilder.apply {\n  annotatedService(object {\n    // Both `/foo` and `/foo?a=bar` are allowed.\n    @Get("/foo")\n    fun foo(@Param a: String?) = // \u{1F448}\u{1F448}\u{1F448}\n      HttpResponse.of("a: $a")\n  })\n}\n'})}),"\n"]}),"\n"]}),"\n","\n",(0,n.jsx)(r.h2,{id:"-improvements",children:"\u{1F4C8} Improvements"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["The ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/EndpointSelectionTimeoutException.html",children:"EndpointSelectionTimeoutException"})," is thrown if timeout occurred when selecting\nan ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/Endpoint.html",children:"Endpoint"})," from an ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/EndpointGroup.html",children:"EndpointGroup"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4269",children:"#4269"})]}),"\n",(0,n.jsxs)(r.li,{children:["You can now set multiple ",(0,n.jsx)(r.a,{href:"typeplural://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/logging/AccessLogWriter.html",children:"AccessLogWriter"})," to ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServerBuilder.html",children:"ServerBuilder"}),"\nand ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServiceBindingBuilder.html",children:"ServiceBindingBuilder"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4280",children:"#4280"})]}),"\n",(0,n.jsxs)(r.li,{children:["You can now give a performance optimization hint to a client by setting an ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/ExchangeType.html",children:"ExchangeType"})," to a\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/RequestOptions.html",children:"RequestOptions"}),".\nThe ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/ExchangeType.html",children:"ExchangeType"})," is configured automatically for:","\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"A gRPC client"}),"\n",(0,n.jsx)(r.li,{children:"A Thrift client"}),"\n",(0,n.jsxs)(r.li,{children:["A ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/WebClient.html",children:"WebClient"})," when it's used with ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/ResponseAs.html",children:"ResponseAs"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4236",children:"#4236"})]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:["Better performance for unary gRPC call. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4192",children:"#4192"})]}),"\n",(0,n.jsxs)(r.li,{children:["Annotated services perform better on unary responses. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4177",children:"#4177"})]}),"\n"]}),"\n",(0,n.jsx)(r.h2,{id:"\uFE0F-bug-fixes",children:"\u{1F6E0}\uFE0F Bug fixes"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["You can now run ",(0,n.jsx)(r.code,{children:"ServerInterceptors"})," in a blocking task executor when\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.html#useBlockingTaskExecutor(boolean)",children:"GrpcServiceBuilder#useBlockingTaskExecutor(boolean)"})," is enabled. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4275",children:"#4275"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4331",children:"#4331"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/multipart/Multiparts.html#getBoundary(com.linecorp.armeria.common.MediaType)",children:"Multiparts#getBoundary(MediaType)"})," now throws an ",(0,n.jsx)(r.code,{children:"IllegalStateException"})," instead\nof ",(0,n.jsx)(r.code,{children:"NullPointerException"}
1)," when a boundary is missing. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4193",children:"#4193"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4325",children:"#4325"})]}),"\n",(0,n.jsxs)(r.li,{children:["Armeria retrofit streaming mode now requests data to upstream when it does not have one. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4319",children:"#4319"})]}),"\n",(0,n.jsxs)(r.li,{children:["You no longer see deep recursive calls in ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/PublisherBasedStreamMessage.html",children:"PublisherBasedStreamMessage"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4298",children:"#4298"})]}),"\n",(0,n.jsxs)(r.li,{children:["You no longer see ",(0,n.jsx)(r.code,{children:"IllegalArgumentException"})," indicating the prohibited character of a header name\nin an environment where Spring integration module and Netty client are used together.\n(e.g. Spring Cloud Gateway) ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4293",children:"#4293"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/ServerCacheControl.html#DISABLED",children:"ServerCacheControl#DISABLED"})," and ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/ServerCacheControl.html#REVALIDATED",children:"ServerCacheControl#REVALIDATED"})," now have\n",(0,n.jsx)(r.code,{children:"max-age"})," set to ",(0,n.jsx)(r.code,{children:"0"})," for better compatibility with old browsers. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4290",children:"#4290"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4291",children:"#4291"})]}),"\n",(0,n.jsxs)(r.li,{children:["You no longer see a ",(0,n.jsx)(r.code,{children:"NullPointerException"})," from ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/Flags.html",children:"Flags"}),"\nwhen ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/logback/RequestContextExportingAppender.html",children:"RequestContextExportingAppender"})," is used. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4285",children:"#4285"})]}),"\n",(0,n.jsxs)(r.li,{children:["You no longer see the ",(0,n.jsx)(r.code,{children:"InputStream"})," returned by ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#toInputStream(java.util.function.Function)",children:"StreamMessage#toInputStream(Function)"})," blocks\nindefinitely in a certain situation. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4268",children:"#4268"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4271",children:"#4271"})]}),"\n",(0,n.jsxs)(r.li,{children:["A ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/WriteTimeoutException.html",children:"WriteTimeoutException"})," is now thrown when a header only request times out. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4255",children:"#4255"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4259",children:"#4259"})]}),"\n",(0,n.jsxs)(r.li,{children:["The request now completes even when the content sanitizer throws an exception. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4248",children:"#4248"})]}),"\n",(0,n.jsxs)(r.li,{children:["A proxy client doesn't resolve a hostname anymore. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4244",children:"#4244"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4245",children:"#4245"})]}),"\n",(0,n.jsxs)(r.li,{children:["The Spring Boot integration module doesn't create a new ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/WebClient.html",children:"WebClient"})," anymore every time\nit's injected. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4240",children:"#4240"})]}),"\n",(0,n.jsxs)(r.li,{children:["Armeria server sends now 400 Bad Request when an HTTP/2 upgrade request contains invali
1d headers. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4016",children:"#4016"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4224",children:"#4224"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/eureka/EurekaUpdatingListener.html",children:"EurekaUpdatingListener"})," now registers itself with the ",(0,n.jsx)(r.code,{children:"instanceId"})," which is ",(0,n.jsx)(r.code,{children:"hostname:appname:port"}),",\nso it doesn't cause a conflict when more than one app with the same name are running in the same host. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4223",children:"#4223"})]}),"\n",(0,n.jsxs)(r.li,{children:["A ramping up ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/EndpointSelectionStrategy.html",children:"EndpointSelectionStrategy"})," now works correctly in combination with\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/healthcheck/HealthCheckedEndpointGroup.html",children:"HealthCheckedEndpointGroup"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4221",children:"#4221"})]}),"\n",(0,n.jsxs)(r.li,{children:["The information of a thrown exception in gRPC service is now propagated to the client via the\n",(0,n.jsx)(r.code,{children:"grpc-status-details-bin"})," header. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4203",children:"#4203"})," ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4204",children:"#4204"})]}),"\n"]}),"\n",(0,n.jsx)(r.h2,{id:"\uFE0F-deprecations",children:"\u{1F3DA}\uFE0F Deprecations"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/client/endpoint/AbstractEndpointSelector.html#select(com.linecorp.armeria.client.ClientRequestContext,java.util.concurrent.ScheduledExecutorService,long)?full",children:"AbstractEndpointSelector#select(ClientRequestContext,ScheduledExecutorService,long)"}),"\nis deprecated in favor of\n",(0,n.jsx)(r.a,{href:"type://#",children:"AbstractEndpointSelector#select(ClientRequestContext,ScheduledExecutorService)?full"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4246",children:"#4246"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/thrift/ThriftSerializationFormats.html#protocolFactory(com.linecorp.armeria.common.SerializationFormat)?full",children:"ThriftSerializationFormats#protocolFactory(SerializationFormat)"})," is deprecated in favor of\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/thrift/ThriftSerializationFormats.html#protocolFactory(com.linecorp.armeria.common.SerializationFormat,int,int)?full",children:"ThriftSerializationFormats#protocolFactory(SerializationFormat,int,int)"}),".\n",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4226",children:"#4226"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.code,{children:"BINARY"}),", ",(0,n.jsx)(r.code,{children:"COMPACT"}),", ",(0,n.jsx)(r.code,{children:"JSON"}),", ",(0,n.jsx)(r.code,{children:"TEXT"}),", and ",(0,n.jsx)(r.code,{children:"TEXT_NAMED_ENUM"})," in ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/thrift/ThriftProtocolFactories.html",children:"ThriftProtocolFactories"})," are deprecated\nin favor of corresponding factory methods. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4226",children:"#4226"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#of(java.nio.file.Path,int)?full",children:"StreamMessage#of(Path,int)"}),", ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#of(java.nio.file.Path,io.netty.buffer.ByteBufAllocator,int)?full",children:"StreamMessage#of(Path,ByteBufAllocator,int)"})," and\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#of(java.nio.file.Path,java.util.concurrent.ExecutorService,i
1o.netty.buffer.ByteBufAllocator,int)?full",children:"StreamMessage#of(Path,ExecutorService,ByteBufAllocator,int)"})," are deprecated\nin favor of ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#builder(java.nio.file.Path)?full",children:"StreamMessage#builder(Path)"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4058",children:"#4058"})]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServiceConfig.html#shutdownBlockingTaskExecutorOnStop()",children:"ServiceConfig#shutdownBlockingTaskExecutorOnStop()"}),",\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServiceConfig.html#shutdownAccessLogWriterOnStop()",children:"ServiceConfig#shutdownAccessLogWriterOnStop()"}),",\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServerConfig.html#shutdownBlockingTaskExecutorOnStop()",children:"ServerConfig#shutdownBlockingTaskExecutorOnStop()"})," and\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/ServerConfig.html#shutdownWorkerGroupOnStop()",children:"ServerConfig#shutdownWorkerGroupOnStop()"})," are not used anymore. ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4280",children:"#4280"})]}),"\n"]}),"\n",(0,n.jsx)(r.h2,{id:"\uFE0F-breaking-changes",children:"\u2622\uFE0F Breaking changes"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/ByteStreamMessage.html",children:"ByteStreamMessage"})," is returned instead of ",(0,n.jsx)(r.code,{children:"StreamMessage<HttpData>"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4058",children:"#4058"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsxs)(r.li,{children:["e.g ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/stream/StreamMessage.html#of(java.io.File)?full",children:"StreamMessage#of(File)"}),", ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/SplitHttpMessage.html#body()",children:"SplitHttpMessage#body()"}),",\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/multipart/Multipart.html#toStreamMessage()",children:"Multipart#toStreamMessage()"})," and ",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/common/multipart/BodyPart.html#content()",children:"BodyPart#content()"})]}),"\n"]}),"\n"]}),"\n",(0,n.jsxs)(r.li,{children:[(0,n.jsx)(r.code,{children:"HttpService.exchangeType(RequestHeaders, Route)"})," is now\n",(0,n.jsx)(r.a,{href:"type://https://javadoc.io/doc/com.linecorp.armeria/armeria-javadoc/latest/com/linecorp/armeria/server/HttpService.html#exchangeType(com.linecorp.armeria.server.RoutingContext)",children:"HttpService#exchangeType(RoutingContext)"}),". ",(0,n.jsx)(r.a,{href:"https://github.com/line/armeria/issues/4177",children:"#4177"})]}),"\n"]}),"\n",(0,n.jsx)(r.h2,{id:"-dependencies",children:"\u26D3 Dependencies"}),"\n",(0,n.jsxs)(r.ul,{children:["\n",(0,n.jsx)(r.li,{children:"Brave 5.13.8 \u2192 5.13.9"}),"\n",(0,n.jsx)(r.li,{children:"Bucket4J 7.4.0 \u2192 7.5.0"}),"\n",(0,n.jsx)(r.li,{children:"Dropwizard metrics 4.2.9 \u2192 4.2.10"}),"\n",(0,n.jsx)(r.li,{children:"GraphQL 1.8.0 \u2192 1.8.2"}),"\n",(0,n.jsx)(r.li,{children:"gRPC-Java 1.45.1 \u2192 1.47.0"}),"\n",(0,n.jsx)(r.li,{children:"gRPC-Kotlin 1.2.1 \u2192 1.3.0"}),"\n",(0,n.jsx)(r.li,{children:"Jackson 2.13.2.1 \u2192 2.13.3"}),"\n",(0,n.jsx)(r.li,{children:"Kotlin 1.6.20 \u2192 1.7.0"}),"\n",(0,n.jsx)(r.li,{children:"Kotlinx 1.6.1 \u2192 1.6.3"}),"\n",(0,n.jsx)(r.li,{children:"Micrometer 1.8.5 \u2192 1.9.1"}),"\n",(0,n.jsx)(r.li,{children:"Netty 4.1.76.Final \u2192 4.1.78.Final"}),"\n",(0,n.jsx)(r.li,{children:"Netty incubator 0.0.13.Final \u2192 0.0.14.Final"}),"\n",(0,n.jsx)(r.li,{children:"Project Reactor 3.4.17 \u2192 3.4.19"}),"\n",(0,n.jsx)(r.li,{children:"Prometheus Simpleclient 0.15.0 \u2192 0.16.0"}),"\n",(0,n.jsx)(r.li,{children:"Reactive Streams 1.0.3 \u2192 1.0.4"}),"\n",(0,n.jsx)(r.li,{children:"RxJava 3.1.4 \u2192 3.1.5"}),"\n",(0,n.jsx)(r.li,{children:"ScalaPB 0.11.10 \u2192 0.11.11"}),"\n",(0,n.jsx)(r.li,{children:"Spring 5.3.19 \u2192 5.3.21"}),"\n",(0,n.jsx)(r.li,{children:"Spring Boot 2.6.6 \u2192 2.7.1"}),"\n"]}),"\n",(0,n.jsx)(r.h2,{id:"-thank-you",children:"\u{1F647} Thank you"}),"\n",(0,n.jsx)(i,{usernames:["ahnyujin","be-hase","devdynam0507","eisig","ghkim3221","ikhoon","injae-kim","Jimexist","jrhee17","kezhenxu94","kojilin","ks-yim","litols","mauhiz","minwoox","natsumehu","ngyukman","ta7uw","timothy-xflowpay","tobias-","trustin"]})]})}function d(e={}){let{wrapper:r}={...(0,t.R)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},28453(e,r,i){i.d(r,{R:()=>o,x:()=>s});var a=i(96540);let n={},t=a.createContext(n);function o(e){let r=a.useContext(t);return a.useMemo(function(){return"function"==typeof e?e(r):{...r,...e}},[r,e])}function s(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),a.createElement(t.Provider,{value:r},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.