PDavid commented on PR #6262:
URL: https://github.com/apache/hbase/pull/6262#issuecomment-2363873648
> Thank you. However, I believe that you need to make the new fields
optional, otherwise the new client won't be able to read the old server's
response. Please test that case as well.
Thanks, good point. :+1: I tested multiple cases now, including the one you
mentioned and every case works and there are no errors.
Created a small and dirty Java application which calls the rest version REST
API endpoint of the HBase REST server component, then parses the response to
the `VersionModel` HBase REST model class. The application requests the
following representations:
- protobuf
- XML
- JSON
<details>
<summary>Java code</summary>
```java
package hu.paksyd.hbase.restclient;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.hadoop.hbase.rest.model.VersionModel;
import
org.apache.hbase.thirdparty.com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.apache.hbase.thirdparty.javax.ws.rs.core.MediaType;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws Exception {
checkProtobuf();
checkXml();
checkJson();
}
private static void checkProtobuf() throws IOException {
System.out.println("Protobuf:");
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
ClassicHttpRequest httpGet =
ClassicRequestBuilder.get("http://localhost:8080/version/rest")
.setHeader("Accept", "application/x-protobuf")
.build();
System.out.println("GET " + httpGet.getRequestUri());
httpClient.execute(httpGet, response -> {
System.out.println(response.getCode() + " " +
response.getReasonPhrase() + "\n");
final HttpEntity httpEntity = response.getEntity();
VersionModel versionModel =
fromProtobuf(httpEntity.getContent());
System.out.println("VersionModel: " + versionModel);
// and ensure it is fully consumed
EntityUtils.consume(httpEntity);
return null;
});
}
}
private static VersionModel fromProtobuf(InputStream inputStream) throws
IOException {
VersionModel model = new VersionModel();
model.getObjectFromMessage(inputStream);
return model;
}
private static void checkXml() throws Exception {
System.out.println("XML:");
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
ClassicHttpRequest httpGet =
ClassicRequestBuilder.get("http://localhost:8080/version/rest")
.setHeader("Accept", "text/xml")
.build();
System.out.println("GET " + httpGet.getRequestUri());
httpClient.execute(httpGet, response -> {
System.out.println(response.getCode() + " " +
response.getReasonPhrase() + "\n");
final HttpEntity httpEntity = response.getEntity();
VersionModel versionModel = fromXml(httpEntity.getContent());
System.out.println("VersionModel: " + versionModel);
// and ensure it is fully consumed
EntityUtils.consume(httpEntity);
return null;
});
}
}
private static VersionModel fromXml(InputStream inputStream) throws
IOException {
VersionModel versionModel;
try {
JAXBContext context =
JAXBContext.newInstance(VersionModel.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
versionModel = (VersionModel)
unmarshaller.unmarshal(inputStream);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
return versionModel;
}
private static void checkJson() throws Exception {
System.out.println("JSON:");
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
ClassicHttpRequest httpGet =
ClassicRequestBuilder.get("http://localhost:8080/version/rest")
.setHeader("Accept", "application/json")
.build();
System.out.println("GET " + httpGet.getRequestUri());
httpClient.execute(httpGet, response -> {
System.out.println(response.getCode() + " " +
response.getReasonPhrase() + "\n");
final HttpEntity httpEntity = response.getEntity();
VersionModel versionModel = fromJson(httpEntity);
System.out.println("VersionModel: " + versionModel);
// and ensure it is fully consumed
EntityUtils.consume(httpEntity);
return null;
});
}
}
private static VersionModel fromJson(HttpEntity httpEntity) throws
IOException {
ObjectMapper mapper = new
JacksonJaxbJsonProvider().locateMapper(VersionModel.class,
MediaType.APPLICATION_JSON_TYPE);
// Have to configure ObjectMapper to not fail on unknown properties
// as older versions of VersionModel does not have newer fields.
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
return mapper.readValue(httpEntity.getContent(), VersionModel.class);
}
}
```
</details>
### New REST server version - old client (2.5.9)
```
Protobuf:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
XML:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
JSON:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
```
### New REST server version - new client
```
Protobuf:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
[Version: 4.0.0-alpha-2-SNAPSHOT] [Revision:
de635766aea8113241a3f04f373d0dea36d848f7]
XML:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
[Version: 4.0.0-alpha-2-SNAPSHOT] [Revision:
de635766aea8113241a3f04f373d0dea36d848f7]
JSON:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Eclipse Adoptium 17.0.12-17.0.12+7] [OS:
Linux 6.8.0-45-generic amd64] [Server: jetty/9.4.55.v20240627] [Jersey: ]
[Version: 4.0.0-alpha-2-SNAPSHOT] [Revision:
de635766aea8113241a3f04f373d0dea36d848f7]
```
### Old REST server version (2.5.9) - new client
```
Protobuf:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Ubuntu
11.0.24-11.0.24+8-post-Ubuntu-1ubuntu324.04.1] [OS: Linux 6.8.0-45-generic
amd64] [Server: jetty/9.4.52.v20230823] [Jersey: ] [Version: null] [Revision:
null]
XML:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Ubuntu
11.0.24-11.0.24+8-post-Ubuntu-1ubuntu324.04.1] [OS: Linux 6.8.0-45-generic
amd64] [Server: jetty/9.4.52.v20230823] [Jersey: ] [Version: null] [Revision:
null]
JSON:
GET /version/rest
200 OK
VersionModel: rest 0.0.3 [JVM: Ubuntu
11.0.24-11.0.24+8-post-Ubuntu-1ubuntu324.04.1] [OS: Linux 6.8.0-45-generic
amd64] [Server: jetty/9.4.52.v20230823] [Jersey: ] [Version: null] [Revision:
null]
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]