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

He-Pin pushed a commit to branch remove/deprecated-attributes-getFirst
in repository https://gitbox.apache.org/repos/asf/pekko.git

commit 953de257cd7c427057695eb85ca215110ff011b1
Author: 虎鸣 <[email protected]>
AuthorDate: Sun Jul 5 04:42:50 2026 +0800

    refactor: remove deprecated Attributes.getFirst/getFirstAttribute (since 
Akka 2.5.7)
    
    Motivation:
    The getFirst and getFirstAttribute methods were deprecated since Akka 2.5.7
    because attributes should always be accessed using the most-specific getter
    (get/getAttribute), not the least-specific getter.
    
    Modification:
    Remove the four deprecated methods: getFirstAttribute(Class, default),
    getFirstAttribute(Class), getFirst[T](default), getFirst[T]. Update tests
    to use the non-deprecated get/getAttribute methods. Remove tests that
    specifically tested getFirst behavior.
    
    Result:
    Only the most-specific attribute accessors (get/getAttribute) remain.
    
    Tests:
    Not run - deprecated API cleanup with test updates
    
    References:
    None - deprecated API cleanup
---
 .../pekko/stream/javadsl/AttributesTest.java       | 13 -------
 .../pekko/stream/scaladsl/AttributesSpec.scala     | 44 +---------------------
 .../pekko/stream/scaladsl/BidiFlowSpec.scala       |  4 +-
 .../stream/scaladsl/GraphDSLCompileSpec.scala      |  4 +-
 .../apache/pekko/stream/scaladsl/SinkSpec.scala    | 20 +---------
 ...precated-attributes-getFirst.backwards.excludes | 20 ++++++++++
 ...precated-attributes-getFirst.backwards.excludes | 20 ++++++++++
 .../remove-deprecated-attributes-getFirst.excludes | 20 ++++++++++
 .../scala/org/apache/pekko/stream/Attributes.scala | 36 ------------------
 9 files changed, 66 insertions(+), 115 deletions(-)

diff --git 
a/stream-tests/src/test/java/org/apache/pekko/stream/javadsl/AttributesTest.java
 
b/stream-tests/src/test/java/org/apache/pekko/stream/javadsl/AttributesTest.java
index 70f15cbc79..4668546ebc 100644
--- 
a/stream-tests/src/test/java/org/apache/pekko/stream/javadsl/AttributesTest.java
+++ 
b/stream-tests/src/test/java/org/apache/pekko/stream/javadsl/AttributesTest.java
@@ -64,17 +64,4 @@ public class AttributesTest extends StreamTestJupiter {
     assertEquals(
         Optional.of(new Attributes.Name("b")), 
attributes.getAttribute(Attributes.Name.class));
   }
-
-  @Deprecated
-  @Test
-  public void mustGetPossiblyMissingFirstAttributeByClass() {
-    assertEquals(
-        Optional.of(new Attributes.Name("a")), 
attributes.getFirstAttribute(Attributes.Name.class));
-  }
-
-  @Deprecated
-  @Test
-  public void mustGetMissingFirstAttributeByClass() {
-    assertEquals(Optional.empty(), 
attributes.getFirstAttribute(Attributes.LogLevels.class));
-  }
 }
diff --git 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/AttributesSpec.scala
 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/AttributesSpec.scala
index cbb797d0ea..b9fa6d0826 100644
--- 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/AttributesSpec.scala
+++ 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/AttributesSpec.scala
@@ -152,11 +152,6 @@ class AttributesSpec
 
     val attributes = Attributes.name("a") and Attributes.name("b") and 
Attributes.inputBuffer(1, 2)
 
-    "give access to the least specific attribute" in {
-      val name = attributes.getFirst[Name]
-      name should ===(Some(Attributes.Name("a")))
-    }
-
     "give access to the most specific attribute value" in {
       val name = attributes.get[Name]
       name should ===(Some(Attributes.Name("b")))
@@ -217,7 +212,7 @@ class AttributesSpec
       name shouldBe Some(Name("new-name"))
     }
 
-    "keep the outermost attribute as the least specific" in {
+    "keep the stage attribute as the most specific" in {
       val attributes = Source
         .fromGraph(new AttributesSource(Attributes.name("original-name")))
         .map(identity)
@@ -227,9 +222,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("original-name"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("whole-graph"))
     }
   }
 
@@ -245,9 +237,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("new-name"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("new-name"))
     }
 
     "make the attributes on Source.fromGraph source behave the same as the 
stage itself" in {
@@ -263,11 +252,6 @@ class AttributesSpec
       mostSpecificName shouldBe Some(Name("replaced"))
       val mostSpecificWhatever = attributes.get[WhateverAttribute]
       mostSpecificWhatever shouldBe None
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("whole-graph"))
-      val leastSpecificWhatever = attributes.getFirst[WhateverAttribute]
-      leastSpecificWhatever shouldBe None
     }
 
     "not replace stage specific attributes with attributes on surrounding 
composite source" in {
@@ -281,9 +265,6 @@ class AttributesSpec
       // still the original as the attribute was added on the composite source
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("original-name"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("composite-graph"))
     }
 
     "make the attributes on Sink.fromGraph source behave the same as the stage 
itself" in {
@@ -299,9 +280,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("replaced"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("whole-graph"))
     }
 
     "use the initial attributes for dispatcher" in {
@@ -414,8 +392,6 @@ class AttributesSpec
 
       val name = attributes.get[Name]
       name shouldBe Some(Name("replaced"))
-      val firstName = attributes.getFirst[Name]
-      firstName shouldBe Some(Name("whole-graph"))
     }
 
     "handle attributes on a composed flow" in {
@@ -438,11 +414,6 @@ class AttributesSpec
       name shouldBe Some(Name("original-name"))
       val whatever = attributes.get[WhateverAttribute]
       whatever shouldBe Some(WhateverAttribute("replaced"))
-
-      val firstName = attributes.getFirst[Name]
-      firstName shouldBe Some(Name("replaced-again"))
-      val firstWhatever = attributes.getFirst[WhateverAttribute]
-      firstWhatever shouldBe Some(WhateverAttribute("replaced"))
     }
 
     "get input buffer size from surrounding .addAttributes (closest)" in {
@@ -572,9 +543,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("replaced"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("whole-graph"))
     }
 
   }
@@ -621,9 +589,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName shouldBe Some(Name("replaced"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName shouldBe Some(Name("whole-graph"))
     }
 
     "make the attributes on Flow.fromGraph source behave the same as the stage 
itself" in {
@@ -643,9 +608,6 @@ class AttributesSpec
 
       val mostSpecificName = attributes.get[Name]
       mostSpecificName should contain(Name("replaced"))
-
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName should contain(Name("whole-graph"))
     }
 
     "make the attributes on Sink.fromGraph source behave the same as the stage 
itself" in {
@@ -664,10 +626,6 @@ class AttributesSpec
       // most specific
       val mostSpecificName = attributes.get[Name]
       mostSpecificName should contain(Name("replaced"))
-
-      // least specific
-      val leastSpecificName = attributes.getFirst[Name]
-      leastSpecificName should contain(Name("whole-graph"))
     }
 
   }
diff --git 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/BidiFlowSpec.scala
 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/BidiFlowSpec.scala
index fbb9b53e24..caa3cea759 100644
--- 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/BidiFlowSpec.scala
+++ 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/BidiFlowSpec.scala
@@ -127,9 +127,9 @@ class BidiFlowSpec extends StreamSpec {
       import Attributes._
       val b: BidiFlow[Int, Long, ByteString, String, NotUsed] = 
bidi.async.addAttributes(none).named("name")
 
-      val name = b.traversalBuilder.attributes.getFirst[Name]
+      val name = b.traversalBuilder.attributes.get[Name]
       name shouldEqual Some(Name("name"))
-      val boundary = b.traversalBuilder.attributes.getFirst[AsyncBoundary.type]
+      val boundary = b.traversalBuilder.attributes.get[AsyncBoundary.type]
       boundary shouldEqual Some(AsyncBoundary)
     }
 
diff --git 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/GraphDSLCompileSpec.scala
 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/GraphDSLCompileSpec.scala
index dd01622097..034390ee6b 100644
--- 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/GraphDSLCompileSpec.scala
+++ 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/GraphDSLCompileSpec.scala
@@ -420,9 +420,9 @@ class GraphDSLCompileSpec extends StreamSpec {
         .addAttributes(none)
         .named("useless")
 
-      val name = ga.traversalBuilder.attributes.getFirst[Name]
+      val name = ga.traversalBuilder.attributes.get[Name]
       name shouldEqual Some(Name("useless"))
-      val boundary = 
ga.traversalBuilder.attributes.getFirst[AsyncBoundary.type]
+      val boundary = ga.traversalBuilder.attributes.get[AsyncBoundary.type]
       boundary shouldEqual (Some(AsyncBoundary))
     }
 
diff --git 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/SinkSpec.scala 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/SinkSpec.scala
index 11689a3ac7..2a0a23bd63 100644
--- 
a/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/SinkSpec.scala
+++ 
b/stream-tests/src/test/scala/org/apache/pekko/stream/scaladsl/SinkSpec.scala
@@ -236,8 +236,7 @@ class SinkSpec extends StreamSpec with DefaultTimeout with 
ScalaFutures {
       val s: Sink[Int, Future[Int]] = 
Sink.head[Int].async.addAttributes(none).named("name")
 
       s.traversalBuilder.attributes.filtered[Name] shouldEqual 
List(Name("name"), Name("headSink"))
-      @nowarn("msg=deprecated")
-      val res = 
s.traversalBuilder.attributes.getFirst[Attributes.AsyncBoundary.type]
+      val res = 
s.traversalBuilder.attributes.get[Attributes.AsyncBoundary.type]
       res shouldEqual (Some(AsyncBoundary))
     }
 
@@ -255,15 +254,6 @@ class SinkSpec extends StreamSpec with DefaultTimeout with 
ScalaFutures {
       s.traversalBuilder.attributes.get[Name](Name("default")) shouldEqual 
Name("name")
     }
 
-    "given no attributes of a class when getting first attribute with default 
value should get default value" in {
-      import Attributes._
-      val s: Sink[Int, Future[Int]] = Sink.head[Int].withAttributes(none).async
-
-      @nowarn("msg=deprecated")
-      val res = s.traversalBuilder.attributes.getFirst[Name](Name("default"))
-      res shouldEqual Name("default")
-    }
-
     "given no attributes of a class when getting last attribute with default 
value should get default value" in {
       import Attributes._
       val s: Sink[Int, Future[Int]] = Sink.head[Int].withAttributes(none).async
@@ -271,14 +261,6 @@ class SinkSpec extends StreamSpec with DefaultTimeout with 
ScalaFutures {
       s.traversalBuilder.attributes.get[Name](Name("default")) shouldEqual 
Name("default")
     }
 
-    "given multiple attributes of a class when getting first attribute with 
default value should get first attribute" in {
-      import Attributes._
-      val s: Sink[Int, Future[Int]] = 
Sink.head[Int].withAttributes(none).async.named("name").named("another_name")
-      @nowarn("msg=deprecated")
-      val res = s.traversalBuilder.attributes.getFirst[Name](Name("default"))
-      res shouldEqual Name("name")
-    }
-
     "given multiple attributes of a class when getting last attribute with 
default value should get last attribute" in {
       import Attributes._
       val s: Sink[Int, Future[Int]] = 
Sink.head[Int].async.addAttributes(none).named("name").named("another_name")
diff --git 
a/stream/src/main/mima-filters/1.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.excludes
 
b/stream/src/main/mima-filters/1.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.excludes
new file mode 100644
index 0000000000..7100072d65
--- /dev/null
+++ 
b/stream/src/main/mima-filters/1.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.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.
+
+# Remove deprecated Attributes.getFirst/getFirstAttribute (deprecated since 
Akka 2.5.7)
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirstAttribute")
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirst")
diff --git 
a/stream/src/main/mima-filters/1.1.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.excludes
 
b/stream/src/main/mima-filters/1.1.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.excludes
new file mode 100644
index 0000000000..7100072d65
--- /dev/null
+++ 
b/stream/src/main/mima-filters/1.1.x.backwards.excludes/remove-deprecated-attributes-getFirst.backwards.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.
+
+# Remove deprecated Attributes.getFirst/getFirstAttribute (deprecated since 
Akka 2.5.7)
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirstAttribute")
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirst")
diff --git 
a/stream/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.excludes
 
b/stream/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.excludes
new file mode 100644
index 0000000000..7100072d65
--- /dev/null
+++ 
b/stream/src/main/mima-filters/2.0.x.backwards.excludes/remove-deprecated-attributes-getFirst.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.
+
+# Remove deprecated Attributes.getFirst/getFirstAttribute (deprecated since 
Akka 2.5.7)
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirstAttribute")
+ProblemFilters.exclude[DirectMissingMethodProblem]("org.apache.pekko.stream.Attributes.getFirst")
diff --git a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala 
b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
index 5cb9235886..af96356427 100644
--- a/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
+++ b/stream/src/main/scala/org/apache/pekko/stream/Attributes.scala
@@ -302,42 +302,6 @@ final class Attributes private[pekko] (
     attributeList.collect { case attr if c.isAssignableFrom(attr.getClass) => 
c.cast(attr) }
   }
 
-  /**
-   * Java API: Get the least specific attribute (added first) of a given 
`Class` or subclass thereof.
-   * If no such attribute exists the `default` value is returned.
-   */
-  @deprecated("Attributes should always be most specific, use 
getAttribute[T]", "Akka 2.5.7")
-  def getFirstAttribute[T <: Attribute](c: Class[T], default: T): T =
-    getFirstAttribute(c).orElse(default)
-
-  /**
-   * Java API: Get the least specific attribute (added first) of a given 
`Class` or subclass thereof.
-   */
-  @deprecated("Attributes should always be most specific, use get[T]", "Akka 
2.5.7")
-  def getFirstAttribute[T <: Attribute](c: Class[T]): Optional[T] =
-    attributeList.reverseIterator.collectFirst { case attr if 
c.isInstance(attr) => c.cast(attr) }.toJava
-
-  /**
-   * Scala API: Get the least specific attribute (added first) of a given type 
parameter T `Class` or subclass thereof.
-   * If no such attribute exists the `default` value is returned.
-   */
-  @deprecated("Attributes should always be most specific, use get[T]", "Akka 
2.5.7")
-  def getFirst[T <: Attribute: ClassTag](default: T): T = {
-    getFirst[T] match {
-      case Some(a) => a
-      case None    => default
-    }
-  }
-
-  /**
-   * Scala API: Get the least specific attribute (added first) of a given type 
parameter T `Class` or subclass thereof.
-   */
-  @deprecated("Attributes should always be most specific, use get[T]", "Akka 
2.5.7")
-  def getFirst[T <: Attribute: ClassTag]: Option[T] = {
-    val c = classTag[T].runtimeClass.asInstanceOf[Class[T]]
-    attributeList.reverseIterator.collectFirst { case attr if 
c.isInstance(attr) => c.cast(attr) }
-  }
-
   // for binary compatibility (used to be a case class)
 
   @deprecated("Use explicit methods on Attributes to interact, not the ones 
provided by Product", "2.0.0")


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to