You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by do...@apache.org on 2026/03/23 19:17:41 UTC
(spark-kubernetes-operator) branch main updated: [SPARK-56162] Prevent Jackson from using reflection on final fields during deserialization for `JEP-500`
This is an automated email from the ASF dual-hosted git repository.
dongjoon pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/spark-kubernetes-operator.git
The following commit(s) were added to refs/heads/main by this push:
new 21b10c2 [SPARK-56162] Prevent Jackson from using reflection on final fields during deserialization for `JEP-500`
21b10c2 is described below
commit 21b10c26b89eef3fd43532e6445516cdec647e52
Author: Dongjoon Hyun <do...@apache.org>
AuthorDate: Mon Mar 23 12:17:30 2026 -0700
[SPARK-56162] Prevent Jackson from using reflection on final fields during deserialization for `JEP-500`
### What changes were proposed in this pull request?
This PR resolves Jackson reflection warnings on `final` fields by adding explicit `JsonCreator` and `JsonProperty` annotations to the constructors:
It also replaces Lombok's `AllArgsConstructor` and `RequiredArgsConstructor` with explicitly written constructors on these classes where necessary to allow Jackson to properly map JSON properties to constructor arguments.
### Why are the changes needed?
To fix warnings introduced ahead of JDK 26 due to **JEP 500 (Prepare to Make Final Mean Final)**.
- https://openjdk.org/jeps/500
> WARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled
Previously, Jackson was bypassing constructors and using deep reflection (`Field.set()`) to inject values directly into `final` fields during deserialization. This caused warnings such as `WARNING: Final field <fieldName> in class <className> has been mutated reflectively` to be logged repeatedly during the build and test execution.
By explicitly declaring `JsonCreator` constructors, Jackson is forced to initialize these `final` fields via normal constructor calls rather than deep reflection, eliminating the warnings and ensuring compatibility with future JDK releases where this reflective mutation will be strictly blocked.
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Pass the CIs.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: `Gemini 3.1 Pro (High)` on `Antigravity`
Closes #580 from dongjoon-hyun/SPARK-56162.
Authored-by: Dongjoon Hyun <do...@apache.org>
Signed-off-by: Dongjoon Hyun <do...@apache.org>
---
.../operator/status/ApplicationAttemptInfo.java | 10 ++++++++--
.../operator/status/ApplicationAttemptSummary.java | 9 +++++++--
.../k8s/operator/status/ApplicationStatus.java | 11 +++++++----
.../spark/k8s/operator/status/BaseAttemptInfo.java | 23 ++++++++++++++++------
.../k8s/operator/status/BaseAttemptSummary.java | 9 +++++++--
.../spark/k8s/operator/status/BaseStatus.java | 11 +++++++----
.../k8s/operator/status/ClusterAttemptSummary.java | 7 ++++++-
.../spark/k8s/operator/status/ClusterStatus.java | 11 +++++++----
8 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptInfo.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptInfo.java
index c9bf414..f1649e1 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptInfo.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptInfo.java
@@ -19,8 +19,10 @@
package org.apache.spark.k8s.operator.status;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@@ -55,8 +57,12 @@ public class ApplicationAttemptInfo extends BaseAttemptInfo {
schedulingFailureRestartCounter = 0L;
}
- public ApplicationAttemptInfo(long id, long restartCounter, long failureRestartCounter,
- long schedulingFailureRestartCounter) {
+ @JsonCreator
+ public ApplicationAttemptInfo(
+ @JsonProperty("id") long id,
+ @JsonProperty("restartCounter") long restartCounter,
+ @JsonProperty("failureRestartCounter") long failureRestartCounter,
+ @JsonProperty("schedulingFailureRestartCounter") long schedulingFailureRestartCounter) {
super(id, restartCounter);
this.failureRestartCounter = failureRestartCounter;
this.schedulingFailureRestartCounter = schedulingFailureRestartCounter;
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptSummary.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptSummary.java
index 37ff296..68d6f21 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptSummary.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationAttemptSummary.java
@@ -21,8 +21,10 @@ package org.apache.spark.k8s.operator.status;
import java.util.SortedMap;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -41,8 +43,11 @@ public class ApplicationAttemptSummary extends BaseAttemptSummary<ApplicationAtt
// This is used when state history trimming is enabled
@Getter protected final SortedMap<Long, ApplicationState> stateTransitionHistory;
- public ApplicationAttemptSummary(ApplicationAttemptInfo attemptInfo,
- SortedMap<Long, ApplicationState> stateTransitionHistory) {
+ @JsonCreator
+ public ApplicationAttemptSummary(
+ @JsonProperty("attemptInfo") ApplicationAttemptInfo attemptInfo,
+ @JsonProperty("stateTransitionHistory")
+ SortedMap<Long, ApplicationState> stateTransitionHistory) {
super(attemptInfo);
this.stateTransitionHistory = stateTransitionHistory;
}
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationStatus.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationStatus.java
index 26dc36d..9d544f1 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationStatus.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ApplicationStatus.java
@@ -26,8 +26,10 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -61,11 +63,12 @@ public class ApplicationStatus
* @param previousAttemptSummary Summary of the previous application attempt.
* @param currentAttemptSummary Summary of the current application attempt.
*/
+ @JsonCreator
public ApplicationStatus(
- ApplicationState currentState,
- Map<Long, ApplicationState> stateTransitionHistory,
- ApplicationAttemptSummary previousAttemptSummary,
- ApplicationAttemptSummary currentAttemptSummary) {
+ @JsonProperty("currentState") ApplicationState currentState,
+ @JsonProperty("stateTransitionHistory") Map<Long, ApplicationState> stateTransitionHistory,
+ @JsonProperty("previousAttemptSummary") ApplicationAttemptSummary previousAttemptSummary,
+ @JsonProperty("currentAttemptSummary") ApplicationAttemptSummary currentAttemptSummary) {
super(currentState, stateTransitionHistory, previousAttemptSummary, currentAttemptSummary);
}
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptInfo.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptInfo.java
index 44a8783..549e859 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptInfo.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptInfo.java
@@ -19,13 +19,13 @@
package org.apache.spark.k8s.operator.status;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.AllArgsConstructor;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
-import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@@ -35,14 +35,25 @@ import lombok.ToString;
* @since 0.8.0
*/
@Getter
-@NoArgsConstructor
-@AllArgsConstructor
@Builder
@EqualsAndHashCode
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class BaseAttemptInfo {
- @Builder.Default protected final long id = 0L;
- @Builder.Default @Setter protected long restartCounter = 0L;
+ protected final long id;
+ @Setter protected long restartCounter;
+
+ public BaseAttemptInfo() {
+ this.id = 0L;
+ this.restartCounter = 0L;
+ }
+
+ @JsonCreator
+ public BaseAttemptInfo(
+ @JsonProperty("id") long id,
+ @JsonProperty("restartCounter") long restartCounter) {
+ this.id = id;
+ this.restartCounter = restartCounter;
+ }
}
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptSummary.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptSummary.java
index f0e701c..05a88fc 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptSummary.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseAttemptSummary.java
@@ -19,11 +19,12 @@
package org.apache.spark.k8s.operator.status;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
-import lombok.RequiredArgsConstructor;
import lombok.ToString;
/**
@@ -34,9 +35,13 @@ import lombok.ToString;
@EqualsAndHashCode
@ToString
@Getter
-@RequiredArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class BaseAttemptSummary<I extends BaseAttemptInfo> {
protected final I attemptInfo;
+
+ @JsonCreator
+ public BaseAttemptSummary(@JsonProperty("attemptInfo") I attemptInfo) {
+ this.attemptInfo = attemptInfo;
+ }
}
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseStatus.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseStatus.java
index 4e04253..3c5bae8 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseStatus.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/BaseStatus.java
@@ -23,8 +23,10 @@ import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -70,11 +72,12 @@ public class BaseStatus<S, STATE extends BaseState<S>, AS extends BaseAttemptSum
* @param previousAttemptSummary The summary of the previous attempt.
* @param currentAttemptSummary The summary of the current attempt.
*/
+ @JsonCreator
public BaseStatus(
- STATE currentState,
- Map<Long, STATE> stateTransitionHistory,
- AS previousAttemptSummary,
- AS currentAttemptSummary) {
+ @JsonProperty("currentState") STATE currentState,
+ @JsonProperty("stateTransitionHistory") Map<Long, STATE> stateTransitionHistory,
+ @JsonProperty("previousAttemptSummary") AS previousAttemptSummary,
+ @JsonProperty("currentAttemptSummary") AS currentAttemptSummary) {
this.currentState = currentState;
this.stateTransitionHistory = new TreeMap<>(stateTransitionHistory);
this.previousAttemptSummary = previousAttemptSummary;
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterAttemptSummary.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterAttemptSummary.java
index d8fbaf3..0af01ea 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterAttemptSummary.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterAttemptSummary.java
@@ -21,8 +21,10 @@ package org.apache.spark.k8s.operator.status;
import java.util.SortedMap;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -40,8 +42,11 @@ import lombok.ToString;
public class ClusterAttemptSummary extends BaseAttemptSummary<BaseAttemptInfo> {
protected final SortedMap<Long, ClusterState> stateTransitionHistory;
+ @JsonCreator
public ClusterAttemptSummary(
- BaseAttemptInfo attemptInfo, SortedMap<Long, ClusterState> stateTransitionHistory) {
+ @JsonProperty("attemptInfo") BaseAttemptInfo attemptInfo,
+ @JsonProperty("stateTransitionHistory")
+ SortedMap<Long, ClusterState> stateTransitionHistory) {
super(attemptInfo);
this.stateTransitionHistory = stateTransitionHistory;
}
diff --git a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterStatus.java b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterStatus.java
index 4962590..427080a 100644
--- a/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterStatus.java
+++ b/spark-operator-api/src/main/java/org/apache/spark/k8s/operator/status/ClusterStatus.java
@@ -22,8 +22,10 @@ package org.apache.spark.k8s.operator.status;
import java.util.Map;
import java.util.TreeMap;
+import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -52,11 +54,12 @@ public class ClusterStatus
* @param previousAttemptSummary Summary of the previous cluster attempt.
* @param currentAttemptSummary Summary of the current cluster attempt.
*/
+ @JsonCreator
public ClusterStatus(
- ClusterState currentState,
- Map<Long, ClusterState> stateTransitionHistory,
- ClusterAttemptSummary previousAttemptSummary,
- ClusterAttemptSummary currentAttemptSummary) {
+ @JsonProperty("currentState") ClusterState currentState,
+ @JsonProperty("stateTransitionHistory") Map<Long, ClusterState> stateTransitionHistory,
+ @JsonProperty("previousAttemptSummary") ClusterAttemptSummary previousAttemptSummary,
+ @JsonProperty("currentAttemptSummary") ClusterAttemptSummary currentAttemptSummary) {
super(currentState, stateTransitionHistory, previousAttemptSummary, currentAttemptSummary);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org