This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 253942db07 [#4377] fix(common): Deprecate the DeleteResponse and use
DropResponse instead (#8146)
253942db07 is described below
commit 253942db079002341a188a31535765cb7fb22d91
Author: Jerry Shao <[email protected]>
AuthorDate: Tue Aug 19 11:40:55 2025 +0800
[#4377] fix(common): Deprecate the DeleteResponse and use DropResponse
instead (#8146)
### What changes were proposed in this pull request?
`DeleteResponse` is duplicated with `DropResponse`, so deprecate the
`DeleteResponse` and use `DropResponse` instead.
### Why are the changes needed?
Fix: #4377
### Does this PR introduce _any_ user-facing change?
Yes
### How was this patch tested?
Add UTs to test the compability.
---
.../apache/gravitino/client/GravitinoMetalake.java | 7 +-
.../apache/gravitino/client/TestDropResponse.java | 83 +++++++++++++++++++++
.../java/org/apache/gravitino/client/TestRole.java | 10 +--
.../gravitino/dto/responses/DeleteResponse.java | 6 +-
.../gravitino/dto/responses/DropResponse.java | 56 ++++++++++++--
.../gravitino/dto/requests/TestDropResponse.java | 87 ++++++++++++++++++++++
.../gravitino/dto/responses/TestResponses.java | 4 +-
.../gravitino/server/web/rest/RoleOperations.java | 4 +-
.../server/web/rest/TestRoleOperations.java | 14 ++--
9 files changed, 245 insertions(+), 26 deletions(-)
diff --git
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
index bc193169be..fe2ade5c4c 100644
---
a/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
+++
b/clients/client-java/src/main/java/org/apache/gravitino/client/GravitinoMetalake.java
@@ -73,7 +73,6 @@ import org.apache.gravitino.dto.requests.UserAddRequest;
import org.apache.gravitino.dto.responses.BaseResponse;
import org.apache.gravitino.dto.responses.CatalogListResponse;
import org.apache.gravitino.dto.responses.CatalogResponse;
-import org.apache.gravitino.dto.responses.DeleteResponse;
import org.apache.gravitino.dto.responses.DropResponse;
import org.apache.gravitino.dto.responses.EntityListResponse;
import org.apache.gravitino.dto.responses.ErrorResponse;
@@ -1017,18 +1016,18 @@ public class GravitinoMetalake extends MetalakeDTO
* @throws RuntimeException If deleting the Role encounters storage issues.
*/
public boolean deleteRole(String role) throws NoSuchMetalakeException {
- DeleteResponse resp =
+ DropResponse resp =
restClient.delete(
String.format(
API_METALAKES_ROLES_PATH,
RESTUtils.encodeString(this.name()),
RESTUtils.encodeString(role)),
- DeleteResponse.class,
+ DropResponse.class,
Collections.emptyMap(),
ErrorHandlers.roleErrorHandler());
resp.validate();
- return resp.deleted();
+ return resp.dropped();
}
/**
diff --git
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestDropResponse.java
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestDropResponse.java
new file mode 100644
index 0000000000..caabe3b51d
--- /dev/null
+++
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestDropResponse.java
@@ -0,0 +1,83 @@
+/*
+ * 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.gravitino.client;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.gravitino.dto.responses.DeleteResponse;
+import org.apache.gravitino.dto.responses.DropResponse;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestDropResponse {
+
+ @Test
+ public void testSupportDropResponseSerDe() throws JsonProcessingException {
+ // test new server with new client
+ String json = "{\"dropped\":true,\"deleted\":null}";
+ DropResponse resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertTrue(resp.dropped());
+
+ json = "{\"dropped\":true,\"deleted\":true}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertTrue(resp.dropped());
+
+ json = "{\"dropped\":false,\"deleted\":false}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertFalse(resp.dropped());
+
+ json = "{\"dropped\":false}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertFalse(resp.dropped());
+
+ json = "{\"dropped\":true}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertTrue(resp.dropped());
+
+ // test old server with new client
+ json = "{\"deleted\":true}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertTrue(resp.dropped());
+
+ json = "{\"deleted\":false}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertFalse(resp.dropped());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testSupportDeleteResponseSerDe() throws JsonProcessingException {
+ // New server with old client
+ String json = "{\"dropped\":true,\"deleted\":true}";
+ DeleteResponse resp = ObjectMapperProvider.objectMapper().readValue(json,
DeleteResponse.class);
+ Assertions.assertTrue(resp.deleted());
+
+ json = "{\"dropped\":false,\"deleted\":false}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DeleteResponse.class);
+ Assertions.assertFalse(resp.deleted());
+
+ // Old server with old client
+ json = "{\"deleted\":true}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DeleteResponse.class);
+ Assertions.assertTrue(resp.deleted());
+
+ json = "{\"deleted\":false}";
+ resp = ObjectMapperProvider.objectMapper().readValue(json,
DeleteResponse.class);
+ Assertions.assertFalse(resp.deleted());
+ }
+}
diff --git
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
index 3d0771fc5f..035d330afc 100644
---
a/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
+++
b/clients/client-java/src/test/java/org/apache/gravitino/client/TestRole.java
@@ -37,7 +37,7 @@ import org.apache.gravitino.dto.authorization.PrivilegeDTO;
import org.apache.gravitino.dto.authorization.RoleDTO;
import org.apache.gravitino.dto.authorization.SecurableObjectDTO;
import org.apache.gravitino.dto.requests.RoleCreateRequest;
-import org.apache.gravitino.dto.responses.DeleteResponse;
+import org.apache.gravitino.dto.responses.DropResponse;
import org.apache.gravitino.dto.responses.ErrorResponse;
import org.apache.gravitino.dto.responses.MetalakeResponse;
import org.apache.gravitino.dto.responses.NameListResponse;
@@ -197,13 +197,13 @@ public class TestRole extends TestBase {
String roleName = "role";
String rolePath = withSlash(String.format(API_METALAKES_ROLES_PATH,
metalakeName, roleName));
- DeleteResponse deleteResponse = new DeleteResponse(true);
- buildMockResource(Method.DELETE, rolePath, null, deleteResponse, SC_OK);
+ DropResponse dropResponse = new DropResponse(true, true);
+ buildMockResource(Method.DELETE, rolePath, null, dropResponse, SC_OK);
Assertions.assertTrue(gravitinoClient.deleteRole(roleName));
- deleteResponse = new DeleteResponse(false);
- buildMockResource(Method.DELETE, rolePath, null, deleteResponse, SC_OK);
+ dropResponse = new DropResponse(false, false);
+ buildMockResource(Method.DELETE, rolePath, null, dropResponse, SC_OK);
Assertions.assertFalse(gravitinoClient.deleteRole(roleName));
// test RuntimeException
diff --git
a/common/src/main/java/org/apache/gravitino/dto/responses/DeleteResponse.java
b/common/src/main/java/org/apache/gravitino/dto/responses/DeleteResponse.java
index 69204b47dd..77f312cc76 100644
---
a/common/src/main/java/org/apache/gravitino/dto/responses/DeleteResponse.java
+++
b/common/src/main/java/org/apache/gravitino/dto/responses/DeleteResponse.java
@@ -22,7 +22,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-/** Represents a response for a delete operation. */
+/**
+ * Represents a response for a delete operation. This class is deprecated and
will be removed in
+ * future versions, please use {@link DropResponse} instead.
+ */
+@Deprecated(since = "1.0.0")
@ToString
@EqualsAndHashCode(callSuper = true)
public class DeleteResponse extends BaseResponse {
diff --git
a/common/src/main/java/org/apache/gravitino/dto/responses/DropResponse.java
b/common/src/main/java/org/apache/gravitino/dto/responses/DropResponse.java
index db4f0031b4..5c6db9be88 100644
--- a/common/src/main/java/org/apache/gravitino/dto/responses/DropResponse.java
+++ b/common/src/main/java/org/apache/gravitino/dto/responses/DropResponse.java
@@ -19,6 +19,8 @@
package org.apache.gravitino.dto.responses;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -28,22 +30,44 @@ import lombok.ToString;
public class DropResponse extends BaseResponse {
@JsonProperty("dropped")
- private final boolean dropped;
+ private final Boolean dropped;
+
+ /**
+ * This field is added to be compatible with DeleteResponse. This field will
only be set for
+ * deleteRole operation. For other drop operations, it will be null. This
field will be leveraged
+ * by the old client, for new client it will never be leveraged.
+ */
+ @JsonProperty("deleted")
+ private final Boolean deleted;
/**
* Constructor for DropResponse.
*
* @param dropped Whether the drop operation was successful.
*/
- public DropResponse(boolean dropped) {
+ public DropResponse(Boolean dropped) {
super(0);
this.dropped = dropped;
+ this.deleted = null;
+ }
+
+ /**
+ * Constructor for DropResponse with both dropped and deleted fields.
+ *
+ * @param dropped Whether the drop operation was successful.
+ * @param deleted Whether the delete operation was successful (used for
backward compatibility).
+ */
+ public DropResponse(Boolean dropped, Boolean deleted) {
+ super(0);
+ this.dropped = dropped;
+ this.deleted = deleted;
}
/** Default constructor for DropResponse (used by Jackson deserializer). */
public DropResponse() {
super();
- this.dropped = false;
+ this.dropped = null;
+ this.deleted = null;
}
/**
@@ -51,7 +75,29 @@ public class DropResponse extends BaseResponse {
*
* @return True if the drop operation was successful, otherwise false.
*/
- public boolean dropped() {
- return dropped;
+ public Boolean dropped() {
+ // If the dropped field is null, it means we use the new client to handle
the old server
+ // `DeleteResponse` response, so we should return the deleted field.
+ return dropped != null ? dropped : deleted;
+ }
+
+ /**
+ * Returns whether the delete operation was successful. This method will
only be called in test.
+ *
+ * @return True if the delete operation was successful, otherwise false.
+ */
+ @VisibleForTesting
+ public Boolean deleted() {
+ return deleted;
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+
+ // Ensure that at least one of dropped or deleted is set
+ Preconditions.checkArgument(
+ dropped != null || deleted != null,
+ "Either 'dropped' or 'deleted' must be set in DropResponse");
}
}
diff --git
a/common/src/test/java/org/apache/gravitino/dto/requests/TestDropResponse.java
b/common/src/test/java/org/apache/gravitino/dto/requests/TestDropResponse.java
new file mode 100644
index 0000000000..14ee74c3da
--- /dev/null
+++
b/common/src/test/java/org/apache/gravitino/dto/requests/TestDropResponse.java
@@ -0,0 +1,87 @@
+/*
+ * 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.gravitino.dto.requests;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.gravitino.dto.responses.DropResponse;
+import org.apache.gravitino.json.JsonUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestDropResponse {
+
+ @Test
+ public void testDropResponseSerDe() throws JsonProcessingException {
+ DropResponse resp = new DropResponse(true);
+ String serJson = JsonUtils.objectMapper().writeValueAsString(resp);
+ DropResponse deserResp = JsonUtils.objectMapper().readValue(serJson,
DropResponse.class);
+ Assertions.assertTrue(deserResp.dropped());
+ Assertions.assertNull(deserResp.deleted());
+
+ resp = new DropResponse(true, true);
+ serJson = JsonUtils.objectMapper().writeValueAsString(resp);
+ deserResp = JsonUtils.objectMapper().readValue(serJson,
DropResponse.class);
+ Assertions.assertTrue(deserResp.dropped());
+ Assertions.assertTrue(deserResp.deleted() != null && deserResp.deleted());
+
+ resp = new DropResponse(false, false);
+ serJson = JsonUtils.objectMapper().writeValueAsString(resp);
+ deserResp = JsonUtils.objectMapper().readValue(serJson,
DropResponse.class);
+ Assertions.assertFalse(deserResp.dropped());
+ Assertions.assertTrue(deserResp.deleted() != null && !deserResp.deleted());
+ }
+
+ @Test
+ public void deserializeFromString() throws JsonProcessingException {
+ String json = "{\"dropped\":true,\"deleted\":null}";
+ DropResponse response = JsonUtils.objectMapper().readValue(json,
DropResponse.class);
+ Assertions.assertTrue(response.dropped());
+ Assertions.assertNull(response.deleted());
+
+ json = "{\"dropped\":true,\"deleted\":true}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertTrue(response.dropped());
+ Assertions.assertTrue(response.deleted() != null && response.deleted());
+
+ json = "{\"dropped\":false,\"deleted\":false}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertFalse(response.dropped());
+ Assertions.assertTrue(response.deleted() != null && !response.deleted());
+
+ json = "{\"dropped\":false}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertFalse(response.dropped());
+ Assertions.assertNull(response.deleted());
+
+ json = "{\"dropped\":true}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertTrue(response.dropped());
+ Assertions.assertNull(response.deleted());
+
+ json = "{\"deleted\":true}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertTrue(response.dropped());
+ Assertions.assertTrue(response.deleted() != null && response.deleted());
+
+ json = "{\"deleted\":false}";
+ response = JsonUtils.objectMapper().readValue(json, DropResponse.class);
+ Assertions.assertFalse(response.dropped());
+ Assertions.assertTrue(response.deleted() != null && !response.deleted());
+ }
+}
diff --git
a/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
b/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
index 9e3b1904c0..c3385cb9e8 100644
--- a/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
+++ b/common/src/test/java/org/apache/gravitino/dto/responses/TestResponses.java
@@ -21,7 +21,7 @@ package org.apache.gravitino.dto.responses;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -77,7 +77,7 @@ public class TestResponses {
void testDropped() throws IllegalArgumentException {
DropResponse drop = new DropResponse();
- assertFalse(drop.dropped());
+ assertNull(drop.dropped());
}
@Test
diff --git
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
index c54a6be497..934478c0dd 100644
---
a/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
+++
b/server/src/main/java/org/apache/gravitino/server/web/rest/RoleOperations.java
@@ -47,7 +47,7 @@ import org.apache.gravitino.authorization.SecurableObjects;
import org.apache.gravitino.dto.authorization.PrivilegeDTO;
import org.apache.gravitino.dto.authorization.SecurableObjectDTO;
import org.apache.gravitino.dto.requests.RoleCreateRequest;
-import org.apache.gravitino.dto.responses.DeleteResponse;
+import org.apache.gravitino.dto.responses.DropResponse;
import org.apache.gravitino.dto.responses.NameListResponse;
import org.apache.gravitino.dto.responses.RoleResponse;
import org.apache.gravitino.dto.util.DTOConverters;
@@ -220,7 +220,7 @@ public class RoleOperations {
if (!deleted) {
LOG.warn("Failed to delete role {} under metalake {}", role,
metalake);
}
- return Utils.ok(new DeleteResponse(deleted));
+ return Utils.ok(new DropResponse(deleted, deleted));
});
} catch (Exception e) {
return ExceptionHandlers.handleRoleException(OperationType.DELETE, role,
metalake, e);
diff --git
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
index 708c8603cf..c2436cc284 100644
---
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
+++
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestRoleOperations.java
@@ -57,7 +57,7 @@ import org.apache.gravitino.dto.authorization.PrivilegeDTO;
import org.apache.gravitino.dto.authorization.RoleDTO;
import org.apache.gravitino.dto.authorization.SecurableObjectDTO;
import org.apache.gravitino.dto.requests.RoleCreateRequest;
-import org.apache.gravitino.dto.responses.DeleteResponse;
+import org.apache.gravitino.dto.responses.DropResponse;
import org.apache.gravitino.dto.responses.ErrorConstants;
import org.apache.gravitino.dto.responses.ErrorResponse;
import org.apache.gravitino.dto.responses.NameListResponse;
@@ -454,9 +454,9 @@ public class TestRoleOperations extends BaseOperationsTest {
.delete();
Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp.getStatus());
- DeleteResponse deleteResponse = resp.readEntity(DeleteResponse.class);
- Assertions.assertEquals(0, deleteResponse.getCode());
- Assertions.assertTrue(deleteResponse.deleted());
+ DropResponse dropResponse = resp.readEntity(DropResponse.class);
+ Assertions.assertEquals(0, dropResponse.getCode());
+ Assertions.assertTrue(dropResponse.dropped());
// Test when failed to delete role
when(manager.deleteRole(any(), any())).thenReturn(false);
@@ -467,9 +467,9 @@ public class TestRoleOperations extends BaseOperationsTest {
.delete();
Assertions.assertEquals(Response.Status.OK.getStatusCode(),
resp2.getStatus());
- DeleteResponse deleteResponse2 = resp2.readEntity(DeleteResponse.class);
- Assertions.assertEquals(0, deleteResponse2.getCode());
- Assertions.assertFalse(deleteResponse2.deleted());
+ DropResponse dropResponse2 = resp2.readEntity(DropResponse.class);
+ Assertions.assertEquals(0, dropResponse2.getCode());
+ Assertions.assertFalse(dropResponse2.dropped());
doThrow(new RuntimeException("mock
error")).when(manager).deleteRole(any(), any());
Response resp3 =