From ee9ec6500b99ab7089e09a86e287a41cbf37a4fe Mon Sep 17 00:00:00 2001 From: Ron Sigal Date: Fri, 5 Jan 2024 15:58:31 -0500 Subject: [PATCH 1/3] Added blog about arrays in resteasy-grpc --- _posts/2024-01-05-grpc-jakarta-rs-arrays.md | 158 ++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 _posts/2024-01-05-grpc-jakarta-rs-arrays.md diff --git a/_posts/2024-01-05-grpc-jakarta-rs-arrays.md b/_posts/2024-01-05-grpc-jakarta-rs-arrays.md new file mode 100644 index 0000000..12f05a0 --- /dev/null +++ b/_posts/2024-01-05-grpc-jakarta-rs-arrays.md @@ -0,0 +1,158 @@ +--- +layout: post +title: "resteasy-grpc: Handling arrays" +subtitle: "" +date: 2024-01-02 +author: Ron Sigal +--- + +Release 1.0.0.Alpha3 of resteasy-grpc has a new feature for handling arbitrary arrays. Although protobuf comes +with a representation of one dimension arrays, e.g. + +``` + message ints { + repeated int64 is = 1; + } +``` + +represents an array `int[]`, there is no built-in way of handling multidimensional arrays like `int[][]`, so we +have to do it explicitly. + +The mechanism has two parts: + +1. arrays.proto, which defines `dev_resteasy_grpc_arrays___ArrayHolder`, and +2. `dev.resteasy.grpc.arrays.ArrayUtility` in grpc-bridge-runtime. + +arrays.proto looks like this: + +``` + message dev_resteasy_grpc_arrays___BooleanArray { + repeated bool bool_field = 1; + } + + message dev_resteasy_grpc_arrays___ByteArray { + bytes bytes_field = 1; + } + + ... + + message dev_resteasy_grpc_arrays___AnyArray { + repeated google.protobuf.Any any_field = 1; + } + + message dev_resteasy_grpc_arrays___ArrayHolderArray { + repeated dev_resteasy_grpc_arrays___ArrayHolder arrayHolder_field = 1; + } + + message dev_resteasy_grpc_arrays___ArrayHolder { + string componentClass = 1; + oneof messageType { + dev_resteasy_grpc_arrays___BooleanArray booleanArray_field = 3; + dev_resteasy_grpc_arrays___ByteArray byteArray_field = 4; + ... + dev_resteasy_grpc_arrays___AnyArray anyArray_field = 12; + dev_resteasy_grpc_arrays___ArrayHolderArray arrayHolderArray_field = 13; + } + } + +``` +It starts with a definition of array message types for + +1. all primitive types, +2. `google.protobuf.Any`, and +3. `dev_resteasy_grpc_arrays___ArrayHolder` itself. + +Then, `dev_resteasy_grpc_arrays___ArrayHolder` is defined with a oneof field that can +hold any of these array message types. The self-referential field + +``` + dev_resteasy_grpc_arrays___ArrayHolderArray arrayHolderArray_field = 13; +``` +is what allows a `dev_resteasy_grpc_arrays___ArrayHolder` to represent arrays with any number of +dimension. + +Compiling arrays.proto generates `dev.resteasy.grpc.arrays.Array_proto`, which gives us a +gateway into the javabuf[^javabuf] world. Suppose we want to generate a representation of +`int[] {3, 5}`. That would look like + +``` + dev_resteasy_grpc_arrays___IntArray.Builder iab = dev_resteasy_grpc_arrays___IntArray.newBuilder(); + iab.addIntField(3); + iab.addIntField(5); + dev_resteasy_grpc_arrays___IntArray ia = iab.build(); + dev_resteasy_grpc_arrays___ArrayHolder.Builder ahb = dev_resteasy_grpc_arrays___ArrayHolder.newBuilder(); + ahb.setIntArrayField(ia); + ahb.setComponentClass(int.class.getName()); + dev_resteasy_grpc_arrays___ArrayHolder ah = ahb.build(); + System.out.println(ah); +``` + +The output would be + +``` + componentClass: "int" + intArray_field { + int_field: 1 + int_field: 2 + } +``` +A similar, but rather longer, sequence would be required to build a javabuf representation of `int[][] {{3, 5}, {7, 11, 13}}`. +To avoid the mess, grpc-bridge-runtime includes the class `dev.resteasy.grpc.arrays.ArrayUtility`. With `ArrayUtility`, +building the javabuf representation of `int[][] {{3, 5}, {7, 11, 13}}` is as easy as + + dev_resteasy_grpc_arrays___ArrayHolder holder = ArrayUtility.getHolder(new int[][] {{3, 5}, {7, 11, 13}}); + +Moreover, `ArrayUtility` can turn the `dev_resteasy_grpc_arrays___ArrayHolder` back to the original array: + + Object array = ArrayUtility.getArray(holder); + Assert.assertArrayEquals(new int[][] {{3, 5}, {7, 11, 13}}, (int[][]) array); + +These two calls to `ArrayUtility` depend on the fact that the target array is built from a primitive Java type. If the +array uses an application specific type, then there are two alternative calls that can be used: + + public static dev_resteasy_grpc_arrays___ArrayHolder getHolder(JavabufTranslator translator, Object o); + +and + + public static Object getArray(JavabufTranslator translator, Array_proto.dev_resteasy_grpc_arrays___ArrayHolder ah) throws Exception; + +Also, if an application uses arrays, the generated `JavabufTranslator` incorporates `ArrayUtility`, so that it can be +used instead: + + dev_resteasy_grpc_arrays___ArrayHolder ah = (dev_resteasy_grpc_arrays___ArrayHolder) translator.translateToJavabuf(new int[][] {{3, 5}, {7, 11, 13}}); + Object array = translator.translateFromJavabuf(ah); + Assert.assertArrayEquals(new int[][] {{3, 5}, {7, 11, 13}}, (int[][]) array); + +**Note.** The latter point can be usefully expanded, independent of the presence of arrays. Consider the class + + package dev.resteasy.grpc.example; + + public class C { + private int i; + private double d; + private String s; + + public C(int i, double d, String s) { + this.i = i; + this.d = d; + this.s = s; + } + } + +Using the fluent methods created in, say, `C_proto` by the protobuf parser, an instance of +`C_proto.dev_resteasy_grpc_example___C` can be created by + + C_proto.dev_resteasy_grpc_example___C.Builder cb = C_proto.dev_resteasy_grpc_example___C.newBuilder(); + C_proto.dev_resteasy_grpc_example___C c1 = cb.setI(3).setD(5.0).setS("seven").build(); + +Note that each field must be set individually. On the other hand, given the `C(int, double, String)` constructor, +an instance of `C_proto.dev_resteasy_grpc_example___C` can be created more directly: + + C_proto.dev_resteasy_grpc_example___C c2 = (C_proto.dev_resteasy_grpc_example___C) translator.translateToJavabuf(new C(3, 5.0, "seven")); + +They accomplish the same thing, so the choice is a matter of taste. + +## Notes + +[^javabuf]: See the documentation at [https://github.com/resteasy/resteasy-grpc/blob/main/docs/grpc-bridge.md](https://github.com/resteasy/resteasy-grpc/blob/main/docs/grpc-bridge.md) + for a discussion of javabuf classes From 9aefeb42dce153a545f607904b5032130bab649f Mon Sep 17 00:00:00 2001 From: Ron Sigal Date: Fri, 5 Jan 2024 16:01:44 -0500 Subject: [PATCH 2/3] Update 2024-01-05-grpc-jakarta-rs-arrays.md Updating date --- _posts/2024-01-05-grpc-jakarta-rs-arrays.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2024-01-05-grpc-jakarta-rs-arrays.md b/_posts/2024-01-05-grpc-jakarta-rs-arrays.md index 12f05a0..36253fc 100644 --- a/_posts/2024-01-05-grpc-jakarta-rs-arrays.md +++ b/_posts/2024-01-05-grpc-jakarta-rs-arrays.md @@ -2,7 +2,7 @@ layout: post title: "resteasy-grpc: Handling arrays" subtitle: "" -date: 2024-01-02 +date: 2024-01-05 author: Ron Sigal --- From cd7eaf8d4c058facaf4d1a272420715023c0b4b6 Mon Sep 17 00:00:00 2001 From: Ron Sigal Date: Tue, 23 Jan 2024 10:38:37 -0500 Subject: [PATCH 3/3] 2024-01-05-grpc-jakarta-rs-arrays.md->2024-01-23-grpc-jakarta-rs-arrays.md; updated resteasy-grpc version to 1.0.0.Alpha5 --- ...arta-rs-arrays.md => 2024-01-23-grpc-jakarta-rs-arrays.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename _posts/{2024-01-05-grpc-jakarta-rs-arrays.md => 2024-01-23-grpc-jakarta-rs-arrays.md} (98%) diff --git a/_posts/2024-01-05-grpc-jakarta-rs-arrays.md b/_posts/2024-01-23-grpc-jakarta-rs-arrays.md similarity index 98% rename from _posts/2024-01-05-grpc-jakarta-rs-arrays.md rename to _posts/2024-01-23-grpc-jakarta-rs-arrays.md index 36253fc..52cd494 100644 --- a/_posts/2024-01-05-grpc-jakarta-rs-arrays.md +++ b/_posts/2024-01-23-grpc-jakarta-rs-arrays.md @@ -2,11 +2,11 @@ layout: post title: "resteasy-grpc: Handling arrays" subtitle: "" -date: 2024-01-05 +date: 2024-01-23 author: Ron Sigal --- -Release 1.0.0.Alpha3 of resteasy-grpc has a new feature for handling arbitrary arrays. Although protobuf comes +Release 1.0.0.Alpha5 of resteasy-grpc has a new feature for handling arbitrary arrays. Although protobuf comes with a representation of one dimension arrays, e.g. ```