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]

Reply via email to