Skip to content

Commit 7bd9042

Browse files
authored
Java duration in javadsl (#780)
* allow java durations to be used in pekko-http javadsl * web socket settings * Update WebSocketSettings.scala * compile issue * more changes * mima * ClientConnectionSettings * ConnectionPoolSettings * javafmt * Update java-duration-support-javadsl.excludes * imports * Update CachingDirectivesExamplesTest.java * examples * update tests
1 parent ef2a12e commit 7bd9042

File tree

22 files changed

+353
-48
lines changed

22 files changed

+353
-48
lines changed

docs/src/test/java/docs/http/javadsl/HttpClientExampleDocTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import static org.apache.pekko.util.ByteString.emptyByteString;
3232

3333
import java.net.InetSocketAddress;
34+
import java.time.Duration;
3435
import java.util.ArrayList;
3536
import java.util.List;
3637
import java.util.concurrent.CompletionStage;
@@ -42,7 +43,6 @@
4243
import java.util.function.Function;
4344
import org.apache.pekko.stream.javadsl.Framing;
4445
import org.apache.pekko.http.javadsl.model.*;
45-
import scala.concurrent.duration.FiniteDuration;
4646
// #manual-entity-consume-example-1
4747

4848
// #single-request-in-actor-example
@@ -106,7 +106,7 @@ public ExamplePerson parse(ByteString line) {
106106

107107
// toStrict to enforce all data be loaded into memory from the connection
108108
final CompletionStage<HttpEntity.Strict> strictEntity =
109-
response.entity().toStrict(FiniteDuration.create(3, TimeUnit.SECONDS).toMillis(), system);
109+
response.entity().toStrict(Duration.ofSeconds(3).toMillis(), system);
110110

111111
// You can now use `getData` to get the data directly...
112112
final CompletionStage<ExamplePerson> person1 =

docs/src/test/java/docs/http/javadsl/server/directives/BasicDirectivesExamplesTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@
4141
import org.junit.Ignore;
4242
import org.junit.Test;
4343
import scala.concurrent.ExecutionContextExecutor;
44-
import scala.concurrent.duration.FiniteDuration;
4544

45+
import java.time.Duration;
4646
import java.util.Arrays;
4747
import java.util.Collections;
4848
import java.util.Iterator;
@@ -1144,7 +1144,7 @@ public void testExtractDataBytes() {
11441144
@Test
11451145
public void testExtractStrictEntity() {
11461146
// #extractStrictEntity
1147-
final FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS);
1147+
final java.time.Duration timeout = java.time.Duration.ofSeconds(3);
11481148
final Route route =
11491149
extractStrictEntity(timeout, strict -> complete(strict.getData().utf8String()));
11501150

@@ -1165,7 +1165,7 @@ public void testExtractStrictEntity() {
11651165
@Test
11661166
public void testToStrictEntity() {
11671167
// #toStrictEntity
1168-
final FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS);
1168+
final Duration timeout = Duration.ofSeconds(3);
11691169
final Route route =
11701170
toStrictEntity(
11711171
timeout,

docs/src/test/java/docs/http/javadsl/server/directives/CachingDirectivesExamplesTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
// #caching-directives-import
2727
import static org.apache.pekko.http.javadsl.server.directives.CachingDirectives.*;
2828
// #caching-directives-import
29-
import scala.concurrent.duration.Duration;
3029
// #time-unit-import
30+
import java.time.Duration;
3131
import java.util.concurrent.TimeUnit;
3232
// #time-unit-import
3333
import org.apache.pekko.http.javadsl.testkit.JUnitRouteTest;
@@ -198,8 +198,8 @@ public Uri apply(RequestContext in, boolean isCheck) {
198198
.lfuCacheSettings()
199199
.withInitialCapacity(25)
200200
.withMaxCapacity(50)
201-
.withTimeToLive(Duration.create(20, TimeUnit.SECONDS))
202-
.withTimeToIdle(Duration.create(10, TimeUnit.SECONDS));
201+
.withTimeToLive(Duration.ofSeconds(20))
202+
.withTimeToIdle(Duration.ofSeconds(10));
203203
final CachingSettings cachingSettings =
204204
defaultCachingSettings.withLfuCacheSettings(lfuCacheSettings);
205205
final Cache<Uri, RouteResult> lfuCache = LfuCache.create(cachingSettings);

docs/src/test/java/docs/http/javadsl/server/directives/TimeoutDirectivesExamplesTest.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
import org.apache.pekko.http.javadsl.server.AllDirectives;
2424
import org.apache.pekko.http.javadsl.server.Route;
2525
import org.apache.pekko.testkit.TestKit;
26+
import org.apache.pekko.util.JavaDurationConverters;
2627
import com.typesafe.config.Config;
2728
import com.typesafe.config.ConfigFactory;
2829
import org.junit.After;
2930
import org.junit.Ignore;
3031
import org.junit.Test;
31-
import scala.concurrent.duration.Duration;
3232

33+
import java.time.Duration;
3334
import java.util.Optional;
3435
import java.util.concurrent.CompletableFuture;
3536
import java.util.concurrent.CompletionStage;
@@ -84,13 +85,14 @@ private Optional<HttpResponse> runRoute(Route route, String routePath) throws Ex
8485

8586
@After
8687
public void shutDown() {
87-
TestKit.shutdownActorSystem(system, Duration.create(1, TimeUnit.SECONDS), false);
88+
TestKit.shutdownActorSystem(
89+
system, scala.concurrent.duration.Duration.create(1, TimeUnit.SECONDS), false);
8890
}
8991

9092
@Test
9193
public void testRequestTimeoutIsConfigurable() throws Exception {
9294
// #withRequestTimeout-plain
93-
final Duration timeout = Duration.create(1, TimeUnit.SECONDS);
95+
final Duration timeout = Duration.ofSeconds(1);
9496
CompletionStage<String> slowFuture = new CompletableFuture<>();
9597

9698
final Route route =
@@ -132,7 +134,7 @@ public void testRequestWithoutTimeoutCancelsTimeout() throws Exception {
132134
@Test
133135
public void testRequestTimeoutAllowsCustomResponse() throws Exception {
134136
// #withRequestTimeout-with-handler
135-
final Duration timeout = Duration.create(1, TimeUnit.MILLISECONDS);
137+
final Duration timeout = Duration.ofMillis(1);
136138
CompletionStage<String> slowFuture = new CompletableFuture<>();
137139

138140
HttpResponse enhanceYourCalmResponse =
@@ -162,7 +164,7 @@ public void testRequestTimeoutAllowsCustomResponse() throws Exception {
162164
@Test
163165
public void testRequestTimeoutCustomResponseCanBeAddedSeparately() throws Exception {
164166
// #withRequestTimeoutResponse
165-
final Duration timeout = Duration.create(100, TimeUnit.MILLISECONDS);
167+
final Duration timeout = Duration.ofMillis(100);
166168
CompletionStage<String> slowFuture = new CompletableFuture<>();
167169

168170
HttpResponse enhanceYourCalmResponse =
@@ -193,8 +195,8 @@ public void testRequestTimeoutCustomResponseCanBeAddedSeparately() throws Except
193195
@Test
194196
public void extractRequestTimeout() throws Exception {
195197
// #extractRequestTimeout
196-
Duration timeout1 = Duration.create(500, TimeUnit.MILLISECONDS);
197-
Duration timeout2 = Duration.create(1000, TimeUnit.MILLISECONDS);
198+
Duration timeout1 = Duration.ofMillis(500);
199+
Duration timeout2 = Duration.ofMillis(1000);
198200
Route route =
199201
path(
200202
"timeout",
@@ -209,7 +211,12 @@ public void extractRequestTimeout() throws Exception {
209211
() ->
210212
extractRequestTimeout(
211213
t2 -> {
212-
if (t1 == timeout1 && t2 == timeout2)
214+
if (t1.equals(
215+
JavaDurationConverters.asFiniteDuration(
216+
timeout1))
217+
&& t2.equals(
218+
JavaDurationConverters.asFiniteDuration(
219+
timeout2)))
213220
return complete(StatusCodes.OK);
214221
else
215222
return complete(StatusCodes.INTERNAL_SERVER_ERROR);

docs/src/test/java/docs/http/javadsl/server/directives/WebSocketDirectivesExamplesTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import org.apache.pekko.stream.javadsl.Source;
3131
import org.apache.pekko.util.ByteString;
3232
import org.junit.Test;
33-
import scala.concurrent.duration.FiniteDuration;
3433

34+
import java.time.Duration;
3535
import java.util.Arrays;
3636
import java.util.Collections;
3737
import java.util.concurrent.TimeUnit;
@@ -97,7 +97,7 @@ public void testHandleWebSocketMessages() {
9797
wsClient.expectMessage("Hello Peter!");
9898

9999
wsClient.sendMessage(BinaryMessage.create(ByteString.fromString("abcdef")));
100-
wsClient.expectNoMessage(FiniteDuration.create(100, TimeUnit.MILLISECONDS));
100+
wsClient.expectNoMessage(Duration.ofMillis(100));
101101

102102
wsClient.sendMessage("John");
103103
wsClient.expectMessage("Hello John!");

http-caching/src/main/scala/org/apache/pekko/http/caching/javadsl/LfuCacheSettings.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.apache.pekko
1717
import pekko.annotation.DoNotInherit
1818
import pekko.http.caching.impl.settings.LfuCachingSettingsImpl
1919
import pekko.http.javadsl.settings.SettingsCompanion
20+
import pekko.util.JavaDurationConverters._
2021
import com.typesafe.config.Config
2122

2223
import scala.concurrent.duration.Duration
@@ -36,7 +37,21 @@ abstract class LfuCacheSettings private[http] () { self: LfuCachingSettingsImpl
3637
def withMaxCapacity(newMaxCapacity: Int): LfuCacheSettings = self.copy(maxCapacity = newMaxCapacity)
3738
def withInitialCapacity(newInitialCapacity: Int): LfuCacheSettings = self.copy(initialCapacity = newInitialCapacity)
3839
def withTimeToLive(newTimeToLive: Duration): LfuCacheSettings = self.copy(timeToLive = newTimeToLive)
40+
41+
/**
42+
* Java API
43+
* @since 1.3.0
44+
*/
45+
def withTimeToLive(newTimeToLive: java.time.Duration): LfuCacheSettings =
46+
self.copy(timeToLive = newTimeToLive.asScala)
3947
def withTimeToIdle(newTimeToIdle: Duration): LfuCacheSettings = self.copy(timeToIdle = newTimeToIdle)
48+
49+
/**
50+
* Java API
51+
* @since 1.3.0
52+
*/
53+
def withTimeToIdle(newTimeToIdle: java.time.Duration): LfuCacheSettings =
54+
self.copy(timeToIdle = newTimeToIdle.asScala)
4055
}
4156

4257
object LfuCacheSettings extends SettingsCompanion[LfuCacheSettings] {

http-core/src/main/java/org/apache/pekko/http/javadsl/TimeoutAccess.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import org.apache.pekko.http.javadsl.model.HttpRequest;
1818
import org.apache.pekko.http.javadsl.model.HttpResponse;
1919
import org.apache.pekko.japi.Function;
20-
import scala.concurrent.duration.Duration;
2120

2221
/**
2322
* Enables programmatic access to the server-side request timeout logic.
@@ -34,17 +33,31 @@ public interface TimeoutAccess {
3433
* <p>Due to the inherent raciness it is not guaranteed that the returned timeout was applied
3534
* before the previously set timeout has expired!
3635
*/
37-
Duration getTimeout();
36+
scala.concurrent.duration.Duration getTimeout();
3837

3938
/**
4039
* Tries to set a new timeout. The timeout period is measured as of the point in time that the end
41-
* of the request has been received, which may be in the past or in the future! Use `Duration.Inf`
42-
* to completely disable request timeout checking for this request.
40+
* of the request has been received, which may be in the past or in the future! Use
41+
* `scala.concurrent.duration.Duration.Inf` to completely disable request timeout checking for
42+
* this request.
4343
*
4444
* <p>Due to the inherent raciness it is not guaranteed that the update will be applied before the
4545
* previously set timeout has expired!
4646
*/
47-
void updateTimeout(Duration timeout);
47+
void updateTimeout(scala.concurrent.duration.Duration timeout);
48+
49+
/**
50+
* Tries to set a new timeout. The timeout period is measured as of the point in time that the end
51+
* of the request has been received, which may be in the past or in the future! Use a
52+
* `java.time.Duration` with a long duration to disable request timeout checking for this request
53+
* (e.g. `java.time.temporal.ChronoUnit.FOREVER.getDuration()`).
54+
*
55+
* <p>Due to the inherent raciness it is not guaranteed that the update will be applied before the
56+
* previously set timeout has expired!
57+
*
58+
* @since 1.3.0
59+
*/
60+
void updateTimeout(java.time.Duration timeout);
4861

4962
/**
5063
* Tries to set a new timeout handler, which produces the timeout response for a given request.
@@ -61,5 +74,16 @@ public interface TimeoutAccess {
6174
* <p>Due to the inherent raciness it is not guaranteed that the update will be applied before the
6275
* previously set timeout has expired!
6376
*/
64-
void update(Duration timeout, Function<HttpRequest, HttpResponse> handler);
77+
void update(
78+
scala.concurrent.duration.Duration timeout, Function<HttpRequest, HttpResponse> handler);
79+
80+
/**
81+
* Tries to set a new timeout and handler at the same time.
82+
*
83+
* <p>Due to the inherent raciness it is not guaranteed that the update will be applied before the
84+
* previously set timeout has expired!
85+
*
86+
* @since 1.3.0
87+
*/
88+
void update(java.time.Duration timeout, Function<HttpRequest, HttpResponse> handler);
6589
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
# Add more support for java.time.Duration in Java DSL
19+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.TimeoutAccess.updateTimeout")
20+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.TimeoutAccess.update")
21+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.WebSocketSettings.getPeriodicKeepAliveMaxIdle")
22+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.withConnectingTimeout")
23+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.withIdleTimeout")
24+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.withStreamCancellationDelay")
25+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withBaseConnectionBackoff")
26+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withMaxConnectionBackoff")
27+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withIdleTimeout")
28+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withKeepAliveTimeout")
29+
ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withMaxConnectionLifetime")

http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
package org.apache.pekko.http.impl.engine.server
1515

1616
import java.util.concurrent.atomic.AtomicReference
17-
import scala.concurrent.{ Future, Promise }
18-
import scala.concurrent.duration.{ Deadline, Duration, FiniteDuration }
19-
import scala.collection.immutable
20-
import scala.util.control.{ NoStackTrace, NonFatal }
17+
2118
import org.apache.pekko
2219
import pekko.NotUsed
2320
import pekko.actor.Cancellable
@@ -27,6 +24,7 @@ import pekko.japi.Function
2724
import pekko.event.LoggingAdapter
2825
import pekko.http.ParsingErrorHandler
2926
import pekko.util.ByteString
27+
import pekko.util.JavaDurationConverters._
3028
import pekko.stream._
3129
import pekko.stream.TLSProtocol._
3230
import pekko.stream.scaladsl._
@@ -42,15 +40,19 @@ import pekko.http.impl.engine.rendering.{
4240
ResponseRenderingOutput
4341
}
4442
import pekko.http.impl.util._
43+
import pekko.http.javadsl.model
4544
import pekko.http.scaladsl.util.FastFuture.EnhancedFuture
4645
import pekko.http.scaladsl.{ Http, TimeoutAccess }
4746
import pekko.http.scaladsl.model.headers.`Timeout-Access`
48-
import pekko.http.javadsl.model
4947
import pekko.http.scaladsl.model._
5048
import pekko.http.impl.util.LogByteStringTools._
5149

5250
import scala.annotation.nowarn
51+
import scala.concurrent.{ Future, Promise }
52+
import scala.concurrent.duration.{ Deadline, Duration, FiniteDuration }
53+
import scala.collection.immutable
5354
import scala.util.Failure
55+
import scala.util.control.{ NoStackTrace, NonFatal }
5456

5557
/**
5658
* INTERNAL API
@@ -388,7 +390,8 @@ private[http] object HttpServerBluePrint {
388390
get.fast.foreach(setup => if (setup.scheduledTask ne null) setup.scheduledTask.cancel())
389391

390392
override def updateTimeout(timeout: Duration): Unit = update(timeout, null: HttpRequest => HttpResponse)
391-
override def updateHandler(handler: HttpRequest => HttpResponse): Unit = update(null, handler)
393+
override def updateHandler(handler: HttpRequest => HttpResponse): Unit =
394+
update(null.asInstanceOf[Duration], handler)
392395
override def update(timeout: Duration, handler: HttpRequest => HttpResponse): Unit = {
393396
val promise = Promise[TimeoutSetup]()
394397
for (old <- getAndSet(promise.future).fast)
@@ -411,9 +414,18 @@ private[http] object HttpServerBluePrint {
411414
import pekko.http.impl.util.JavaMapping.Implicits._
412415

413416
/** JAVA API * */
414-
def update(timeout: Duration, handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
417+
override def updateTimeout(timeout: java.time.Duration): Unit = {
418+
val stimeout = if (timeout eq null) null else timeout.asScala
419+
update(stimeout, null: HttpRequest => HttpResponse)
420+
}
421+
override def update(timeout: Duration, handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
415422
update(timeout, handler(_: HttpRequest).asScala)
416-
def updateHandler(handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
423+
override def update(
424+
timeout: java.time.Duration, handler: Function[model.HttpRequest, model.HttpResponse]): Unit = {
425+
val stimeout = if (timeout eq null) null else timeout.asScala
426+
update(stimeout, handler(_: HttpRequest).asScala)
427+
}
428+
override def updateHandler(handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
417429
updateHandler(handler(_: HttpRequest).asScala)
418430

419431
def timeout = currentTimeout

http-core/src/main/scala/org/apache/pekko/http/impl/settings/ClientConnectionSettingsImpl.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import pekko.http.scaladsl.settings.ClientConnectionSettings.LogUnencryptedNetwo
2525
import pekko.http.scaladsl.settings.Http2ClientSettings.Http2ClientSettingsImpl
2626
import pekko.http.scaladsl.settings.{ Http2ClientSettings, ParserSettings, WebSocketSettings }
2727
import pekko.io.Inet.SocketOption
28+
import pekko.util.JavaDurationConverters._
2829
import com.typesafe.config.Config
2930

3031
import scala.collection.immutable
@@ -55,6 +56,17 @@ private[pekko] final case class ClientConnectionSettingsImpl(
5556
"The provided ParserSettings is a generic object that does not contain the client-specific settings.")
5657
override def productPrefix = "ClientConnectionSettings"
5758

59+
override def withConnectingTimeout(
60+
newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
61+
withConnectingTimeout(newValue.asScala)
62+
63+
override def withIdleTimeout(newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
64+
withIdleTimeout(newValue.asScala)
65+
66+
override def withStreamCancellationDelay(
67+
newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
68+
withStreamCancellationDelay(newValue.asScala)
69+
5870
override def websocketRandomFactory: () => Random = websocketSettings.randomFactory
5971
}
6072

0 commit comments

Comments
 (0)