You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pekko.apache.org by fa...@apache.org on 2025/09/20 07:49:29 UTC

(pekko-http) branch main updated: breaking Java DSL api changes (Duration) (#788)

This is an automated email from the ASF dual-hosted git repository.

fanningpj pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-http.git


The following commit(s) were added to refs/heads/main by this push:
     new 4cf616ef1 breaking Java DSL api changes (Duration) (#788)
4cf616ef1 is described below

commit 4cf616ef135a8d9faac93a3c392deae90bb32933
Author: PJ Fanning <pj...@users.noreply.github.com>
AuthorDate: Sat Sep 20 08:49:23 2025 +0100

    breaking Java DSL api changes (Duration) (#788)
    
    * breaking Java DSL api changes (Duration)
    
    * adjust APIs
    
    * mima
    
    * switch file
    
    * Create javadsl-change-duration-return-types.excludes
    
    * Remove unused import for FiniteDuration
    
    * Create JavaDurationConverterSpec.scala
    
    * Update JavaDurationConverterSpec.scala
---
 .../http/javadsl/HttpClientExampleDocTest.java     |  2 -
 .../directives/TimeoutDirectivesExamplesTest.java  | 10 ++--
 .../javadsl-change-duration-return-types.excludes  | 24 +++++++++
 .../http/caching/javadsl/LfuCacheSettings.scala    | 26 ++++++++--
 .../http/caching/scaladsl/LfuCacheSettings.scala   |  5 +-
 .../apache/pekko/http/javadsl/TimeoutAccess.java   |  5 +-
 .../java-duration-support-javadsl.excludes         |  1 +
 .../javadsl-change-duration-return-types.excludes  | 30 +++++++++++
 .../impl/engine/server/HttpServerBluePrint.scala   |  6 +--
 .../settings/ClientConnectionSettingsImpl.scala    |  8 +--
 .../impl/settings/ConnectionPoolSettingsImpl.scala | 15 +++---
 .../http/impl/util/JavaDurationConverter.scala     | 38 ++++++++++++++
 .../settings/ClientConnectionSettings.scala        | 23 +++++++--
 .../javadsl/settings/ConnectionPoolSettings.scala  | 46 ++++++++++++++---
 .../apache/pekko/http/scaladsl/TimeoutAccess.scala |  6 +--
 .../http/impl/util/JavaDurationConverterSpec.scala | 59 ++++++++++++++++++++++
 .../pekko/http/javadsl/model/MultipartsSpec.scala  |  1 -
 .../javadsl-change-duration-return-types.excludes  | 20 ++++++++
 .../server/directives/TimeoutDirectives.scala      | 24 ++++++---
 .../server/directives/TimeoutDirectives.scala      |  2 +-
 20 files changed, 299 insertions(+), 52 deletions(-)

diff --git a/docs/src/test/java/docs/http/javadsl/HttpClientExampleDocTest.java b/docs/src/test/java/docs/http/javadsl/HttpClientExampleDocTest.java
index 6b7b3ab86..e6d0a8f77 100644
--- a/docs/src/test/java/docs/http/javadsl/HttpClientExampleDocTest.java
+++ b/docs/src/test/java/docs/http/javadsl/HttpClientExampleDocTest.java
@@ -41,8 +41,6 @@ import java.io.File;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
-import scala.concurrent.duration.FiniteDuration;
-
 import org.apache.pekko.stream.javadsl.Framing;
 import org.apache.pekko.http.javadsl.model.*;
 // #manual-entity-consume-example-1
diff --git a/docs/src/test/java/docs/http/javadsl/server/directives/TimeoutDirectivesExamplesTest.java b/docs/src/test/java/docs/http/javadsl/server/directives/TimeoutDirectivesExamplesTest.java
index 12698ad23..5bc11e43c 100644
--- a/docs/src/test/java/docs/http/javadsl/server/directives/TimeoutDirectivesExamplesTest.java
+++ b/docs/src/test/java/docs/http/javadsl/server/directives/TimeoutDirectivesExamplesTest.java
@@ -23,7 +23,6 @@ import org.apache.pekko.http.javadsl.model.StatusCodes;
 import org.apache.pekko.http.javadsl.server.AllDirectives;
 import org.apache.pekko.http.javadsl.server.Route;
 import org.apache.pekko.testkit.TestKit;
-import org.apache.pekko.util.JavaDurationConverters;
 import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
 import org.junit.After;
@@ -36,6 +35,8 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.TimeUnit;
 
+import scala.jdk.javaapi.DurationConverters;
+
 public class TimeoutDirectivesExamplesTest extends AllDirectives {
   // #testSetup
   private final Config testConf =
@@ -211,12 +212,9 @@ public class TimeoutDirectivesExamplesTest extends AllDirectives {
                                     () ->
                                         extractRequestTimeout(
                                             t2 -> {
-                                              if (t1.equals(
-                                                      JavaDurationConverters.asFiniteDuration(
-                                                          timeout1))
+                                              if (t1.equals(DurationConverters.toScala(timeout1))
                                                   && t2.equals(
-                                                      JavaDurationConverters.asFiniteDuration(
-                                                          timeout2)))
+                                                      DurationConverters.toScala(timeout2)))
                                                 return complete(StatusCodes.OK);
                                               else
                                                 return complete(StatusCodes.INTERNAL_SERVER_ERROR);
diff --git a/http-caching/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes b/http-caching/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
new file mode 100644
index 000000000..5f388bc5d
--- /dev/null
+++ b/http-caching/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Change some Java DSL methods that return Scala Durations to return Java Durations
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.caching.javadsl.LfuCacheSettings.getTimeToLive")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.caching.javadsl.LfuCacheSettings.getTimeToIdle")
+ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.caching.javadsl.LfuCacheSettings.getTimeToLive")
+ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.caching.javadsl.LfuCacheSettings.getTimeToIdle")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.caching.scaladsl.LfuCacheSettings.getTimeToLive")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.caching.scaladsl.LfuCacheSettings.getTimeToIdle")
diff --git a/http-caching/src/main/scala/org/apache/pekko/http/caching/javadsl/LfuCacheSettings.scala b/http-caching/src/main/scala/org/apache/pekko/http/caching/javadsl/LfuCacheSettings.scala
index cd229279e..ececd622f 100644
--- a/http-caching/src/main/scala/org/apache/pekko/http/caching/javadsl/LfuCacheSettings.scala
+++ b/http-caching/src/main/scala/org/apache/pekko/http/caching/javadsl/LfuCacheSettings.scala
@@ -17,10 +17,10 @@ import org.apache.pekko
 import pekko.annotation.DoNotInherit
 import pekko.http.caching.impl.settings.LfuCachingSettingsImpl
 import pekko.http.javadsl.settings.SettingsCompanion
-import pekko.util.JavaDurationConverters._
 import com.typesafe.config.Config
 
 import scala.concurrent.duration.Duration
+import scala.jdk.DurationConverters._
 
 /**
  * Public API but not intended for subclassing
@@ -31,8 +31,24 @@ abstract class LfuCacheSettings private[http] () { self: LfuCachingSettingsImpl
   /* JAVA APIs */
   def getMaxCapacity: Int
   def getInitialCapacity: Int
-  def getTimeToLive: Duration
-  def getTimeToIdle: Duration
+
+  /**
+   * Java API
+   * <p>
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
+   * </p>
+   */
+  def getTimeToLive: java.time.Duration
+
+  /**
+   * Java API
+   * <p>
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
+   * </p>
+   */
+  def getTimeToIdle: java.time.Duration
 
   def withMaxCapacity(newMaxCapacity: Int): LfuCacheSettings = self.copy(maxCapacity = newMaxCapacity)
   def withInitialCapacity(newInitialCapacity: Int): LfuCacheSettings = self.copy(initialCapacity = newInitialCapacity)
@@ -43,7 +59,7 @@ abstract class LfuCacheSettings private[http] () { self: LfuCachingSettingsImpl
    * @since 1.3.0
    */
   def withTimeToLive(newTimeToLive: java.time.Duration): LfuCacheSettings =
-    self.copy(timeToLive = newTimeToLive.asScala)
+    self.copy(timeToLive = newTimeToLive.toScala)
   def withTimeToIdle(newTimeToIdle: Duration): LfuCacheSettings = self.copy(timeToIdle = newTimeToIdle)
 
   /**
@@ -51,7 +67,7 @@ abstract class LfuCacheSettings private[http] () { self: LfuCachingSettingsImpl
    * @since 1.3.0
    */
   def withTimeToIdle(newTimeToIdle: java.time.Duration): LfuCacheSettings =
-    self.copy(timeToIdle = newTimeToIdle.asScala)
+    self.copy(timeToIdle = newTimeToIdle.toScala)
 }
 
 object LfuCacheSettings extends SettingsCompanion[LfuCacheSettings] {
diff --git a/http-caching/src/main/scala/org/apache/pekko/http/caching/scaladsl/LfuCacheSettings.scala b/http-caching/src/main/scala/org/apache/pekko/http/caching/scaladsl/LfuCacheSettings.scala
index b8adae981..53f92350c 100644
--- a/http-caching/src/main/scala/org/apache/pekko/http/caching/scaladsl/LfuCacheSettings.scala
+++ b/http-caching/src/main/scala/org/apache/pekko/http/caching/scaladsl/LfuCacheSettings.scala
@@ -17,6 +17,7 @@ import org.apache.pekko
 import pekko.annotation.DoNotInherit
 import pekko.http.caching.impl.settings.LfuCachingSettingsImpl
 import pekko.http.caching.javadsl
+import pekko.http.impl.util.JavaDurationConverter
 import pekko.http.scaladsl.settings.SettingsCompanion
 import com.typesafe.config.Config
 
@@ -34,8 +35,8 @@ abstract class LfuCacheSettings private[http] () extends javadsl.LfuCacheSetting
 
   final def getMaxCapacity: Int = self.maxCapacity
   final def getInitialCapacity: Int = self.initialCapacity
-  final def getTimeToLive: Duration = self.timeToLive
-  final def getTimeToIdle: Duration = self.timeToIdle
+  final def getTimeToLive: java.time.Duration = JavaDurationConverter.toJava(self.timeToLive)
+  final def getTimeToIdle: java.time.Duration = JavaDurationConverter.toJava(self.timeToIdle)
 
   override def withMaxCapacity(newMaxCapacity: Int): LfuCacheSettings = self.copy(maxCapacity = newMaxCapacity)
   override def withInitialCapacity(newInitialCapacity: Int): LfuCacheSettings =
diff --git a/http-core/src/main/java/org/apache/pekko/http/javadsl/TimeoutAccess.java b/http-core/src/main/java/org/apache/pekko/http/javadsl/TimeoutAccess.java
index b98abc814..0dcd862ec 100644
--- a/http-core/src/main/java/org/apache/pekko/http/javadsl/TimeoutAccess.java
+++ b/http-core/src/main/java/org/apache/pekko/http/javadsl/TimeoutAccess.java
@@ -32,8 +32,11 @@ public interface TimeoutAccess {
    *
    * <p>Due to the inherent raciness it is not guaranteed that the returned timeout was applied
    * before the previously set timeout has expired!
+   *
+   * <p>In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
    */
-  scala.concurrent.duration.Duration getTimeout();
+  java.time.Duration getTimeout();
 
   /**
    * Tries to set a new timeout. The timeout period is measured as of the point in time that the end
diff --git a/http-core/src/main/mima-filters/1.3.x.backwards.excludes/java-duration-support-javadsl.excludes b/http-core/src/main/mima-filters/1.3.x.backwards.excludes/java-duration-support-javadsl.excludes
index 201a40d36..7b44d7832 100644
--- a/http-core/src/main/mima-filters/1.3.x.backwards.excludes/java-duration-support-javadsl.excludes
+++ b/http-core/src/main/mima-filters/1.3.x.backwards.excludes/java-duration-support-javadsl.excludes
@@ -27,3 +27,4 @@ ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.java
 ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withIdleTimeout")
 ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withKeepAliveTimeout")
 ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withMaxConnectionLifetime")
+ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.withResponseEntitySubscriptionTimeout")
diff --git a/http-core/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes b/http-core/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
new file mode 100644
index 000000000..7cb891a06
--- /dev/null
+++ b/http-core/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Change some Java DSL methods that return Scala Durations to return Java Durations
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.getConnectingTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.getIdleTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ClientConnectionSettings.getStreamCancellationDelay")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.getBaseConnectionBackoff")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.getMaxConnectionBackoff")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.getIdleTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.getKeepAliveTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.settings.ConnectionPoolSettings.getResponseEntitySubscriptionTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.impl.engine.server.HttpServerBluePrint#TimeoutAccessImpl.getTimeout")
+ProblemFilters.exclude[IncompatibleResultTypeProblem]("org.apache.pekko.http.javadsl.TimeoutAccess.getTimeout")
+ProblemFilters.exclude[ReversedMissingMethodProblem]("org.apache.pekko.http.javadsl.TimeoutAccess.getTimeout")
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.http.scaladsl.TimeoutAccess.getTimeout")
diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
index 0e2579a9f..9019443c6 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/server/HttpServerBluePrint.scala
@@ -22,7 +22,6 @@ import pekko.annotation.InternalApi
 import pekko.japi.function.Function
 import pekko.event.LoggingAdapter
 import pekko.util.ByteString
-import pekko.util.JavaDurationConverters._
 import pekko.stream._
 import pekko.stream.TLSProtocol._
 import pekko.stream.scaladsl._
@@ -49,6 +48,7 @@ import pekko.http.impl.util.LogByteStringTools._
 import scala.concurrent.{ ExecutionContext, Future, Promise }
 import scala.concurrent.duration.{ Deadline, Duration, FiniteDuration }
 import scala.collection.immutable
+import scala.jdk.DurationConverters._
 import scala.util.Failure
 import scala.util.control.{ NoStackTrace, NonFatal }
 
@@ -407,12 +407,12 @@ private[http] object HttpServerBluePrint {
 
     /** JAVA API * */
     override def updateTimeout(timeout: java.time.Duration): Unit =
-      update(timeout.asScala, null: HttpRequest => HttpResponse)
+      update(timeout.toScala, null: HttpRequest => HttpResponse)
     override def update(timeout: Duration, handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
       update(timeout, handler(_: HttpRequest).asScala)
     override def update(
         timeout: java.time.Duration, handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
-      update(timeout.asScala, handler(_: HttpRequest).asScala)
+      update(timeout.toScala, handler(_: HttpRequest).asScala)
     override def updateHandler(handler: Function[model.HttpRequest, model.HttpResponse]): Unit =
       updateHandler(handler(_: HttpRequest).asScala)
 
diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ClientConnectionSettingsImpl.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ClientConnectionSettingsImpl.scala
index 3ea468f7f..9da508eac 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ClientConnectionSettingsImpl.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ClientConnectionSettingsImpl.scala
@@ -25,11 +25,11 @@ import pekko.http.scaladsl.settings.ClientConnectionSettings.LogUnencryptedNetwo
 import pekko.http.scaladsl.settings.Http2ClientSettings.Http2ClientSettingsImpl
 import pekko.http.scaladsl.settings.{ Http2ClientSettings, ParserSettings, WebSocketSettings }
 import pekko.io.Inet.SocketOption
-import pekko.util.JavaDurationConverters._
 import com.typesafe.config.Config
 
 import scala.collection.immutable
 import scala.concurrent.duration.{ Duration, FiniteDuration }
+import scala.jdk.DurationConverters._
 import scala.util.Try
 
 /** INTERNAL API */
@@ -58,14 +58,14 @@ private[pekko] final case class ClientConnectionSettingsImpl(
 
   override def withConnectingTimeout(
       newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
-    withConnectingTimeout(newValue.asScala)
+    withConnectingTimeout(newValue.toScala)
 
   override def withIdleTimeout(newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
-    withIdleTimeout(newValue.asScala)
+    withIdleTimeout(newValue.toScala)
 
   override def withStreamCancellationDelay(
       newValue: java.time.Duration): pekko.http.scaladsl.settings.ClientConnectionSettings =
-    withStreamCancellationDelay(newValue.asScala)
+    withStreamCancellationDelay(newValue.toScala)
 
   override def websocketRandomFactory: () => Random = websocketSettings.randomFactory
 }
diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ConnectionPoolSettingsImpl.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ConnectionPoolSettingsImpl.scala
index cf24a3bde..02a18db6d 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ConnectionPoolSettingsImpl.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/impl/settings/ConnectionPoolSettingsImpl.scala
@@ -17,12 +17,12 @@ import org.apache.pekko
 import pekko.annotation.InternalApi
 import pekko.http.impl.util._
 import pekko.http.scaladsl.settings._
-import pekko.util.JavaDurationConverters._
 import com.typesafe.config.Config
 
 import scala.collection.immutable
 import scala.concurrent.duration.Duration
 import scala.concurrent.duration.FiniteDuration
+import scala.jdk.DurationConverters._
 import scala.util.matching.Regex
 
 /** INTERNAL API */
@@ -61,25 +61,28 @@ private[pekko] final case class ConnectionPoolSettingsImpl(
   override def productPrefix = "ConnectionPoolSettings"
 
   override def withBaseConnectionBackoff(newValue: java.time.Duration): ConnectionPoolSettings =
-    withBaseConnectionBackoff(newValue.asScala)
+    withBaseConnectionBackoff(newValue.toScala)
 
   override def withMaxConnectionBackoff(newValue: java.time.Duration): ConnectionPoolSettings =
-    withMaxConnectionBackoff(newValue.asScala)
+    withMaxConnectionBackoff(newValue.toScala)
 
   override def withIdleTimeout(newValue: java.time.Duration): ConnectionPoolSettings =
-    withIdleTimeout(newValue.asScala)
+    withIdleTimeout(newValue.toScala)
 
   override def withKeepAliveTimeout(newValue: java.time.Duration): ConnectionPoolSettings =
-    withKeepAliveTimeout(newValue.asScala)
+    withKeepAliveTimeout(newValue.toScala)
 
   override def withMaxConnectionLifetime(newValue: java.time.Duration): ConnectionPoolSettings =
-    withMaxConnectionLifetime(newValue.asScala)
+    withMaxConnectionLifetime(newValue.toScala)
 
   def withUpdatedConnectionSettings(
       f: ClientConnectionSettings => ClientConnectionSettings): ConnectionPoolSettingsImpl =
     copy(connectionSettings = f(connectionSettings),
       hostOverrides = hostOverrides.map { case (k, v) => k -> v.withUpdatedConnectionSettings(f) })
 
+  override def withResponseEntitySubscriptionTimeout(newValue: java.time.Duration): ConnectionPoolSettings =
+    withResponseEntitySubscriptionTimeout(newValue.toScala)
+
   /** INTERNAL API */
   private[http] def copyDeep(
       mapHostOverrides: ConnectionPoolSettings => ConnectionPoolSettings,
diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/util/JavaDurationConverter.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/util/JavaDurationConverter.scala
new file mode 100644
index 000000000..ef13bbde3
--- /dev/null
+++ b/http-core/src/main/scala/org/apache/pekko/http/impl/util/JavaDurationConverter.scala
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.http.impl.util
+
+import java.time.temporal.ChronoUnit
+
+import org.apache.pekko
+import pekko.annotation.InternalApi
+
+import scala.jdk.DurationConverters._
+
+/**
+ * Internal Pekko HTTP API
+ */
+@InternalApi
+private[http] object JavaDurationConverter {
+  def toJava(d: scala.concurrent.duration.Duration): java.time.Duration = d match {
+    case fd: scala.concurrent.duration.FiniteDuration => fd.toJava
+    case scala.concurrent.duration.Duration.Inf       => ChronoUnit.FOREVER.getDuration
+    case scala.concurrent.duration.Duration.MinusInf  => ChronoUnit.FOREVER.getDuration.negated()
+    case _                                            => ChronoUnit.FOREVER.getDuration
+  }
+}
diff --git a/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ClientConnectionSettings.scala b/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ClientConnectionSettings.scala
index 33c310719..3060fe603 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ClientConnectionSettings.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ClientConnectionSettings.scala
@@ -14,6 +14,7 @@
 package org.apache.pekko.http.javadsl.settings
 
 import java.net.InetSocketAddress
+import java.time.{ Duration => JDuration }
 import java.util.function.Supplier
 import java.util.{ Optional, Random }
 
@@ -23,6 +24,7 @@ import pekko.actor.ActorSystem
 import pekko.annotation.ApiMayChange
 import pekko.annotation.DoNotInherit
 import pekko.http.impl.settings.ClientConnectionSettingsImpl
+import pekko.http.impl.util.JavaDurationConverter
 import pekko.http.impl.util.JavaMapping.Implicits._
 import pekko.http.javadsl.ClientTransport
 import pekko.http.javadsl.model.headers.UserAgent
@@ -30,6 +32,7 @@ import pekko.io.Inet.SocketOption
 
 import scala.concurrent.duration.{ Duration, FiniteDuration }
 import scala.jdk.CollectionConverters._
+import scala.jdk.DurationConverters._
 import scala.jdk.OptionConverters._
 
 /**
@@ -39,13 +42,27 @@ import scala.jdk.OptionConverters._
 abstract class ClientConnectionSettings private[pekko] () { self: ClientConnectionSettingsImpl =>
 
   /* JAVA APIs */
-  final def getConnectingTimeout: FiniteDuration = connectingTimeout
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
+   */
+  final def getConnectingTimeout: JDuration = connectingTimeout.toJava
   final def getParserSettings: ParserSettings = parserSettings
-  final def getIdleTimeout: Duration = idleTimeout
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
+   */
+  final def getIdleTimeout: JDuration = JavaDurationConverter.toJava(idleTimeout)
   final def getSocketOptions: java.lang.Iterable[SocketOption] = socketOptions.asJava
   final def getUserAgentHeader: Optional[UserAgent] = (userAgentHeader: Option[UserAgent]).asJava
   final def getLogUnencryptedNetworkBytes: Optional[Int] = (logUnencryptedNetworkBytes: Option[Int]).asJava
-  final def getStreamCancellationDelay: FiniteDuration = streamCancellationDelay
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.Duration`
+   * to `java.time.Duration`.
+   */
+  final def getStreamCancellationDelay: JDuration = streamCancellationDelay.toJava
   final def getRequestHeaderSizeHint: Int = requestHeaderSizeHint
   final def getWebsocketSettings: WebSocketSettings = websocketSettings
   final def getWebsocketRandomFactory: Supplier[Random] = new Supplier[Random] {
diff --git a/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ConnectionPoolSettings.scala b/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ConnectionPoolSettings.scala
index 312b85d88..c49741b2d 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ConnectionPoolSettings.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/javadsl/settings/ConnectionPoolSettings.scala
@@ -18,14 +18,15 @@ import java.time.{ Duration => JDuration }
 import com.typesafe.config.Config
 
 import scala.concurrent.duration.{ Duration, FiniteDuration }
+import scala.jdk.DurationConverters._
 
 import org.apache.pekko
 import pekko.actor.ActorSystem
 import pekko.annotation.{ ApiMayChange, DoNotInherit }
 import pekko.http.impl.settings.ConnectionPoolSettingsImpl
+import pekko.http.impl.util.JavaDurationConverter
 import pekko.http.impl.util.JavaMapping.Implicits._
 import pekko.http.javadsl.ClientTransport
-import pekko.util.JavaDurationConverters._
 
 /**
  * Public API but not intended for subclassing
@@ -37,15 +38,40 @@ abstract class ConnectionPoolSettings private[pekko] () { self: ConnectionPoolSe
   def getMaxRetries: Int = maxRetries
   def getMaxOpenRequests: Int = maxOpenRequests
   def getPipeliningLimit: Int = pipeliningLimit
-  def getMaxConnectionLifetime: JDuration = maxConnectionLifetime.asJava
-  def getBaseConnectionBackoff: FiniteDuration = baseConnectionBackoff
-  def getMaxConnectionBackoff: FiniteDuration = maxConnectionBackoff
-  def getIdleTimeout: Duration = idleTimeout
-  def getKeepAliveTimeout: Duration = keepAliveTimeout
+  def getMaxConnectionLifetime: JDuration = JavaDurationConverter.toJava(maxConnectionLifetime)
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.FiniteDuration`
+   * to `java.time.Duration`.
+   */
+  def getBaseConnectionBackoff: JDuration = baseConnectionBackoff.toJava
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.FiniteDuration`
+   * to `java.time.Duration`.
+   */
+  def getMaxConnectionBackoff: JDuration = maxConnectionBackoff.toJava
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.FiniteDuration`
+   * to `java.time.Duration`.
+   */
+  def getIdleTimeout: JDuration = JavaDurationConverter.toJava(idleTimeout)
+
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.FiniteDuration`
+   * to `java.time.Duration`.
+   */
+  def getKeepAliveTimeout: JDuration = JavaDurationConverter.toJava(keepAliveTimeout)
   def getConnectionSettings: ClientConnectionSettings = connectionSettings
 
+  /**
+   * In 2.0.0, the return type of this method changed from `scala.concurrent.duration.FiniteDuration`
+   * to `java.time.Duration`.
+   */
   @ApiMayChange
-  def getResponseEntitySubscriptionTimeout: Duration = responseEntitySubscriptionTimeout
+  def getResponseEntitySubscriptionTimeout: JDuration =
+    JavaDurationConverter.toJava(responseEntitySubscriptionTimeout)
 
   // ---
 
@@ -109,6 +135,12 @@ abstract class ConnectionPoolSettings private[pekko] () { self: ConnectionPoolSe
   @ApiMayChange
   def withResponseEntitySubscriptionTimeout(newValue: Duration): ConnectionPoolSettings
 
+  /**
+   * Java API
+   * @since 1.3.0
+   */
+  def withResponseEntitySubscriptionTimeout(newValue: java.time.Duration): ConnectionPoolSettings
+
   def withTransport(newValue: ClientTransport): ConnectionPoolSettings =
     withUpdatedConnectionSettings(_.withTransport(newValue.asScala))
 }
diff --git a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/TimeoutAccess.scala b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/TimeoutAccess.scala
index 8c7249032..570e5cff5 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/TimeoutAccess.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/TimeoutAccess.scala
@@ -15,9 +15,10 @@ package org.apache.pekko.http.scaladsl
 
 import org.apache.pekko
 import pekko.annotation.DoNotInherit
+import pekko.http.impl.util.JavaDurationConverter
+import pekko.http.scaladsl.model.{ HttpRequest, HttpResponse }
 
 import scala.concurrent.duration.Duration
-import pekko.http.scaladsl.model.{ HttpRequest, HttpResponse }
 
 /**
  * Enables programmatic access to the server-side request timeout logic.
@@ -37,8 +38,7 @@ trait TimeoutAccess extends pekko.http.javadsl.TimeoutAccess {
    */
   def timeout: Duration
 
-  /** Java API */
-  def getTimeout: Duration = timeout
+  override def getTimeout: java.time.Duration = JavaDurationConverter.toJava(timeout)
 
   /**
    * Tries to set a new timeout.
diff --git a/http-core/src/test/scala/org/apache/pekko/http/impl/util/JavaDurationConverterSpec.scala b/http-core/src/test/scala/org/apache/pekko/http/impl/util/JavaDurationConverterSpec.scala
new file mode 100644
index 000000000..35c5d8143
--- /dev/null
+++ b/http-core/src/test/scala/org/apache/pekko/http/impl/util/JavaDurationConverterSpec.scala
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.http.impl.util
+
+import java.time.temporal.ChronoUnit
+
+import org.apache.pekko
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.wordspec.AnyWordSpec
+
+import scala.concurrent.duration._
+
+class JavaDurationConverterSpec extends AnyWordSpec with Matchers {
+
+  "JavaDurationConverter" must {
+
+    "convert from scala.concurrent.duration.FiniteDuration to java.time.Duration" in {
+      val scalaDuration: FiniteDuration = 5.seconds + 3.nanoseconds
+      val javaDuration: java.time.Duration = JavaDurationConverter.toJava(scalaDuration)
+      javaDuration should ===(java.time.Duration.ofSeconds(5, 3))
+    }
+
+    "convert from Duration.Zero to java.time.Duration" in {
+      val javaDuration: java.time.Duration = JavaDurationConverter.toJava(Duration.Zero)
+      javaDuration should ===(java.time.Duration.ZERO)
+    }
+
+    "convert infinite duration to java.time.Duration" in {
+      val scalaDuration: Duration = Duration.Inf
+      JavaDurationConverter.toJava(scalaDuration) should ===(ChronoUnit.FOREVER.getDuration)
+    }
+
+    "convert minus infinite duration to java.time.Duration" in {
+      val scalaDuration: Duration = Duration.MinusInf
+      JavaDurationConverter.toJava(scalaDuration) should ===(ChronoUnit.FOREVER.getDuration().negated())
+    }
+
+    "convert undefined duration to java.time.Duration" in {
+      val scalaDuration: Duration = Duration.Undefined
+      JavaDurationConverter.toJava(scalaDuration) should ===(ChronoUnit.FOREVER.getDuration())
+    }
+
+  }
+}
diff --git a/http-core/src/test/scala/org/apache/pekko/http/javadsl/model/MultipartsSpec.scala b/http-core/src/test/scala/org/apache/pekko/http/javadsl/model/MultipartsSpec.scala
index 19c6f335d..7196cd3f9 100644
--- a/http-core/src/test/scala/org/apache/pekko/http/javadsl/model/MultipartsSpec.scala
+++ b/http-core/src/test/scala/org/apache/pekko/http/javadsl/model/MultipartsSpec.scala
@@ -20,7 +20,6 @@ import scala.concurrent.duration.DurationInt
 import scala.jdk.FutureConverters._
 
 import com.typesafe.config.{ Config, ConfigFactory }
-import org.scalatest.{ BeforeAndAfterAll, Inside }
 import org.apache.pekko
 import pekko.actor.ActorSystem
 import pekko.stream.SystemMaterializer
diff --git a/http/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes b/http/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
new file mode 100644
index 000000000..e3ac474e8
--- /dev/null
+++ b/http/src/main/mima-filters/2.0.x.backwards.excludes/javadsl-change-duration-return-types.excludes
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Change some Java DSL methods that return Scala Durations to return Java Durations
+ProblemFilters.exclude[IncompatibleSignatureProblem]("org.apache.pekko.http.javadsl.server.Directives.extractRequestTimeout")
+ProblemFilters.exclude[IncompatibleSignatureProblem]("org.apache.pekko.http.javadsl.server.directives.TimeoutDirectives.extractRequestTimeout")
diff --git a/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/TimeoutDirectives.scala b/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/TimeoutDirectives.scala
index 492b4111d..d108786e6 100644
--- a/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/TimeoutDirectives.scala
+++ b/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/TimeoutDirectives.scala
@@ -16,20 +16,28 @@ package org.apache.pekko.http.javadsl.server.directives
 import java.time.{ Duration => JDuration }
 import java.util.function.{ Function => JFunction, Supplier }
 
-import scala.concurrent.duration.Duration
+import scala.jdk.DurationConverters._
 
 import org.apache.pekko
+import pekko.http.impl.util.JavaDurationConverter
+import pekko.http.impl.util.JavaMapping.Implicits._
 import pekko.http.javadsl.model.{ HttpRequest, HttpResponse }
 import pekko.http.javadsl.server.Route
 import pekko.http.scaladsl.server.{ Directives => D }
-import pekko.util.JavaDurationConverters._
-
-import pekko.http.impl.util.JavaMapping.Implicits._
 
 abstract class TimeoutDirectives extends WebSocketDirectives {
 
-  def extractRequestTimeout(inner: JFunction[Duration, Route]): RouteAdapter = RouteAdapter {
-    D.extractRequestTimeout { timeout => inner.apply(timeout).delegate }
+  /**
+   * Java API
+   * <p>
+   * In 2.0.0, the input function changed from expecting `scala.concurrent.duration.Duration`
+   * as input to `java.time.Duration`.
+   * </p>
+   */
+  def extractRequestTimeout(inner: JFunction[java.time.Duration, Route]): RouteAdapter = RouteAdapter {
+    D.extractRequestTimeout { timeout =>
+      inner.apply(JavaDurationConverter.toJava(timeout)).delegate
+    }
   }
 
   /**
@@ -55,7 +63,7 @@ abstract class TimeoutDirectives extends WebSocketDirectives {
    */
   def withRequestTimeout(timeout: JDuration, inner: Supplier[Route]): RouteAdapter =
     RouteAdapter {
-      D.withRequestTimeout(timeout.asScala) { inner.get.delegate }
+      D.withRequestTimeout(timeout.toScala) { inner.get.delegate }
     }
 
   /**
@@ -83,7 +91,7 @@ abstract class TimeoutDirectives extends WebSocketDirectives {
   def withRequestTimeout(timeout: JDuration,
       timeoutHandler: JFunction[HttpRequest, HttpResponse],
       inner: Supplier[Route]): RouteAdapter = RouteAdapter {
-    D.withRequestTimeout(timeout.asScala, in => timeoutHandler(in.asJava).asScala) { inner.get.delegate }
+    D.withRequestTimeout(timeout.toScala, in => timeoutHandler(in.asJava).asScala) { inner.get.delegate }
   }
 
   def withoutRequestTimeout(inner: Supplier[Route]): RouteAdapter = RouteAdapter {
diff --git a/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/TimeoutDirectives.scala b/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/TimeoutDirectives.scala
index 552971945..2b03f348f 100644
--- a/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/TimeoutDirectives.scala
+++ b/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/TimeoutDirectives.scala
@@ -34,7 +34,7 @@ trait TimeoutDirectives {
    */
   def extractRequestTimeout: Directive1[Duration] = Directive { inner => ctx =>
     val timeout = ctx.request.header[`Timeout-Access`] match {
-      case Some(t) => t.timeoutAccess.getTimeout
+      case Some(t) => t.timeoutAccess.timeout
       case _ =>
         ctx.log.warning("extractRequestTimeout was used in route however no request-timeout is set!")
         Duration.Inf


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pekko.apache.org
For additional commands, e-mail: commits-help@pekko.apache.org