Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions content/posts/2024-01-23-grpc-jakarta-rs-arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ author: Ron Sigal
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.

```
```protobuf
message ints {
repeated int64 is = 1;
}
Expand All @@ -25,7 +25,7 @@ The mechanism has two parts:

arrays.proto looks like this:

```
```protobuf
message dev_resteasy_grpc_arrays___BooleanArray {
repeated bool bool_field = 1;
}
Expand Down Expand Up @@ -66,7 +66,7 @@ It starts with a definition of array message types for
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

```
```protobuf
dev_resteasy_grpc_arrays___ArrayHolderArray arrayHolderArray_field = 13;
```

Expand All @@ -77,7 +77,7 @@ Compiling arrays.proto generates `dev.resteasy.grpc.arrays.Array_proto`, which g
gateway into the javabuf[^javabuf] world. Suppose we want to generate a representation of
`int[] {3, 5}`. That would look like

```
```java
dev_resteasy_grpc_arrays___IntArray.Builder iab = dev_resteasy_grpc_arrays___IntArray.newBuilder();
iab.addIntField(3);
iab.addIntField(5);
Expand Down Expand Up @@ -105,34 +105,34 @@ 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

```
```java
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:

```
```java
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:

```
```java
public static dev_resteasy_grpc_arrays___ArrayHolder getHolder(JavabufTranslator translator, Object o);
```

and

```
```java
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:

```
```java
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);
Expand All @@ -141,7 +141,7 @@ used instead:

**Note.** The latter point can be usefully expanded, independent of the presence of arrays. Consider the class

```
```java
package dev.resteasy.grpc.example;

public class C {
Expand All @@ -160,15 +160,15 @@ used instead:
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

```
```java
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:

```
```java
C_proto.dev_resteasy_grpc_example___C c2 = (C_proto.dev_resteasy_grpc_example___C) translator.translateToJavabuf(new C(3, 5.0, "seven"));
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The [WildFly](https://github.com/wildfly/wildfly) and [Quarkus](https://github.c

- [Using MicroProfile OpenAPI With RESTEasy](https://resteasy.dev/2023/02/20/resteasy-microprofile-openapi/)

For Quarkus, here is a blog post that shows the usage of the built-in MicroProfile OpenAPI in Quarkus:
For Quarkus, here is a blog post that shows the usage of the built-in MicroProfile OpenAPI in Quarkus:

- [MicroProfile OpenAPI for everyone](https://quarkus.io/blog/openapi-for-everyone/)

Expand Down
38 changes: 19 additions & 19 deletions content/posts/2025-02-14-resteasy-grpc-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ and `java.util.Set`. In order to handle arbitrary implementations, idiosyncratic
implementating classes are ignored and all implementations are assigned the least common nature of lists and sets. That is,
an implementation of `java.util.List` is considered to be an ordered sequence and is translated to a protobuf
message type of the form
```
```protobuf
message java_util___ArrayList16 {
string classname = 1;
repeated int32 data = 2;
}
```
and an implementation of `java.util.Set` is considered to be an unordered collection and is translated to a
protobuf message type of the form
```
```protobuf
message java_util___HashSet3 {
string classname = 1;
repeated string data = 2;
Expand All @@ -40,7 +40,7 @@ a workaround. The important thing is to define a protobuf message whose repeated
`java_util___ArrayList16`. That would be a reasonable representation of `ArrayList<Integer>`. Similarly, `java_util___HashSet3`
would be a reasonable representation of `HashSet<String>`. The `JavaToProtobufGenerator` class in the
[grpc-bridge](https://github.com/resteasy/resteasy-grpc) module generates the protobuf messages and decorates them as follows:
```
```java
// List: java.util.ArrayList<java.lang.Integer>
message java_util___ArrayList16 {
string classname = 1;
Expand All @@ -56,7 +56,7 @@ would be a reasonable representation of `HashSet<String>`. The `JavaToProtobufGe
}
```
These are two simple examples. Consider something a little more complicated: `java.util.ArrayList<java.util.HashSet<java.lang.String>>`:
```
```java
// List: java.util.ArrayList<java.util.HashSet<java.lang.String>>
message java_util___ArrayList14 {
string classname = 1;
Expand All @@ -70,7 +70,7 @@ field in `java_util___ArrayList14` is of type `java_util___HashSet3`.
A complication arises in the form of type variables and wildcards. The solution adopted in resteasy-grpc is to map unassigned
type variables and wildcards to `java.lang.Object`, which makes sense, since they can take any types at runtime. The protobuf
analog to `java.lang.Object` is `google.protobuf.Any`, which is defined
```
```protobuf
message Any {
string type_url = 1;
bytes value = 2;
Expand All @@ -81,7 +81,7 @@ package declared in the .proto file. The value field has built-in type bytes, w
of bytes no longer than 2^32", according to https://developers.google.com/protocol-buffers/docs/proto3.

Suppose we have the Jakarta REST resource methods
```
```java
package x.y;

@GET
Expand Down Expand Up @@ -110,13 +110,13 @@ Suppose we have the Jakarta REST resource methods
}
```
where x.y.Grimble is
```
```java
public class Grimble<T> {
T t;
}
```
`JavaToProtobufGenerator` would create the rpc and message definitions
```
```protobuf
// p/grimble/raw x_y___Grimble google.protobuf.Empty GET sync
rpc gr_raw (GeneralEntityMessage) returns (GeneralReturnMessage);

Expand Down Expand Up @@ -155,7 +155,7 @@ where x.y.Grimble is
```
The details about the rpc comments are described elsewhere ([gRPC Bridge Project: User Guide](https://resteasy.dev/docs/grpc/)),
but here it's enough to know that the rpc definition
```
```protobuf
// p/grimble/variable x_y___Grimble18 google.protobuf.Empty GET sync
rpc gr_variable (GeneralEntityMessage) returns (GeneralReturnMessage);
```
Expand All @@ -175,15 +175,15 @@ type `google.protobuf.Any`, which, as discussed above, represents an arbitrary t
`of java.lang.Object`.

The discussion about generic types and type variables applies to lists and sets. For example,
```
```java
@Path("arraylist/hashset/wildcard")
@POST
public ArrayList<HashSet<?>> arraylistHashsetTest2(ArrayList<HashSet<?>> l) {
return l;
}
```
gives rise to
```
```java
// List: java.util.ArrayList<java.util.HashSet<java.lang.Object>>
message java_util___ArrayList13 {
string classname = 1;
Expand All @@ -202,7 +202,7 @@ gives rise to
Here we'll discuss a gRPC client intending to communicate with a Jakarta REST server. The subject is covered in detail in
[gRPC Bridge Project: User Guide](https://resteasy.dev/docs/grpc/), but here we will look at sending and receiving
`Collection`s. For example, consider the resource method
```
```java
@GET
@Path("arraylist/integer")
public ArrayList<?> listArray0(ArrayList<Integer> list) {
Expand All @@ -212,15 +212,15 @@ Here we'll discuss a gRPC client intending to communicate with a Jakarta REST se
We've seen that `java.util.ArrayList<java.lang.Integer>` translates to javabuf class `java_util___ArrayList16`. So the client
has to create an instance of `java_util___ArrayList16` to send to the server. There are two possible strategies. One is to
work in the javabuf world:
```
```java
java_util___ArrayList16.Builder juaBuilder = java_util___ArrayList16.newBuilder();
juaBuilder.setClassname("java.util.ArrayList");
juaBuilder.addData(3);
juaBuilder.addData(7);
java_util___ArrayList16 jua = juaBuilder.build();
```
Alternatively, one could create an `ArrayList` and translate it to an `java_util___ArrayList16`:
```
```java
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(3);
list.add(7);
Expand All @@ -229,18 +229,18 @@ Alternatively, one could create an `ArrayList` and translate it to an `java_util
```
where `translator` is an instance of `dev.resteasy.grpc.bridge.runtime.protobuf.JavabufTranslator`.
The next step is to build a `GeneralEntityMessage`:
```
```java
GeneralEntityMessage.Builder gemBuilder = GeneralEntityMessage.newBuilder();
gemBuilder.setJavaUtilArrayList16Field(gemBuilder.build());
```
Then the remote method can be invoked:
```
```java
GeneralReturnMessage response = stub.listArray0(gem);
```
where `stub` is the client side representative of the server methods.
Finally, the result can be extracted from the `GeneralReturnMessage`. Note that `listArray0` returns
an instance of `ArrayList<?>`, which translates to javabuf class
```
```java
// List: java.util.ArrayList<java.lang.Object>
message java_util___ArrayList17 {
string classname = 1;
Expand All @@ -249,11 +249,11 @@ an instance of `ArrayList<?>`, which translates to javabuf class
}
```
This complicates things a bit since we have to extract the returned list from an `Any`.
```
```java
java_util___ArrayList17 result = response.getJavaUtilArrayList17Field();
Any any = response.getAnyField();
Message result = any.unpack((Class) Utility.extractClassFromAny(any, translator));
list = (ArrayList<Object>) translator.translateFromJavabuf(result);
```
### Maps
Stay tuned for the next release, which which implementations of `java.util.Map` will be treated in a similar way.
Stay tuned for the next release, in which implementations of `java.util.Map` will be treated similarly.
20 changes: 13 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.roq</groupId>
<artifactId>quarkus-roq</artifactId>
Expand All @@ -58,11 +62,12 @@
<artifactId>quarkus-roq-plugin-tagging</artifactId>
<version>${version.quarkus-roq}</version>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<groupId>io.quarkiverse.roq</groupId>
<artifactId>quarkus-roq-plugin-sitemap</artifactId>
<version>${version.quarkus-roq}</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
Expand All @@ -71,12 +76,13 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

<dependency>
<groupId>io.quarkiverse.roq</groupId>
<artifactId>quarkus-roq-plugin-sitemap</artifactId>
<version>${version.quarkus-roq}</version>
<groupId>org.mvnpm</groupId>
<artifactId>highlight.js</artifactId>
<version>11.11.1</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand Down
8 changes: 8 additions & 0 deletions public/css/org_common.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ These are the common css styles for the JBoss.org site.

/* = Common tags and elements */

pre:has(code) {
margin: 0px;
max-height: max-content;
width: auto;
padding: 0px;
border: none;
}

Comment thread
jamezp marked this conversation as resolved.
pre {
margin: 0px;
padding: 10px;
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
site.escaped-pages=posts/*.md,docs/**.adoc

quarkus.log.category."io.quarkiverse.roq.frontmatter.deployment".level=DEBUG

quarkus.web-bundler.dependencies.auto-import=all
quarkus.asciidoc.attributes.icons=font
quarkus.asciidoc.attributes.source-highlighter=highlight.js
Loading