Creation Review

Type
Creation
State
Successful
End Date of the Review Period

Reviews run for a minimum of one week. The outcome of the review is decided on this date. This is the last day to make comments or ask questions about this review.

Project
Proposal

Jakarta RPC

Wednesday, September 22, 2021 - 17:34 by Aleks Seovic
This proposal is in the Project Proposal Phase (as defined in the Eclipse Development Process) and is written to declare its intent and scope. We solicit additional participation and input from the community. Please login and add your feedback in the comments section.
Is this a specification project?
Patent License
Implementation Patent License
Project
Parent Project
Proposal State
Created
Background

Over the last several years, with the rise of microservices architectures, gRPC has become a de facto standard for inter-service communication. It is more efficient than REST, and leverages HTTP2 to provide full-duplex communication between the client and the server.

The official gRPC support for Java platform is provided by grpc-java project, which is a robust, full-featured implementation of gRPC. However, because of the requirement for Android support, it hasn't really moved past Java 7, and it does not always play nicely with the existing Java and Jakarta EE technologies. For example, a number of classes generated by the existing gRPC tooling, such as various client stubs, are declared as final, which makes them unusable with CDI.

Another issue is that while gRPC itself is marshaller-agnostic, the existing tooling only provides support for Protobuf, which may or may not be the right choice for an application, but is pretty much forced upon users, as supporting any other serialization format requires a thorough understanding of gRPC internals and a lot of very low-level work on developers' part, making services significantly more difficult to implement.

Finally, because of Java 7 compatibility baggage, grpc-java still doesn't work well with Java Module System, even though an issue has been open to address that more than 4 years ago.

Scope

Jakarta RPC aims to make gRPC services and clients easier to implement in Java by:

  1. Eliminating the need for IDL/proto files and build-time code generation
  2. Allowing developers to define gRPC services via annotated classes, similar to how JAX-RS allows you to define REST services
  3. Allowing developers to define gRPC service clients via annotated interfaces, similar to how Eclipse MicroProfile REST Client allows you to define REST clients
  4. Allowing developers to configure marshaller for a service via annotations on the service endpoint classes and client interfaces
  5. Allowing anyone to add support for a new marshaller via well-defined SPI
  6. Providing "syntactic sugar" where appropriate to make both the service and the client implementation simpler.

The implementation of the gRPC transport itself is explicitly NOT in scope. It is expected, but not required, that most Jakarta RPC implementations will leverage existing work done by the grpc-java team.

Description

The main goal of Jakarta RPC project is to make gRPC easier to use within Jakarta EE ecosystem, by allowing developers to define gRPC services and clients the same way they are defining REST services and clients today -- via annotated classes (a la JAX-RS) on the server, and annotated interfaces (a la Eclipse MicroProfile REST Client) on the client -- and by making them easier to integrate with existing Jakarta EE technologies, such as CDI and Config.

An additional goal is to eliminate the need for special tooling and build-time code generation that favors one serialization format: Protobuf. gRPC was designed to be agnostic to the serialization format, and allows independent configuration of payload marshaller for request and response at the RPC method level, so we see no reason to prefer one serialization format over another and force Protobuf upon everyone.

Finally, we want to make sure that Jakarta RPC implementations work well with modern Java versions and fully support Java Module System. 

Why Here?

Jakarta RPC aims to do for gRPC service developers what JAX-RS did for REST service developers, so we believe making it an official Jakarta specification makes perfect sense.

The goal is also to ensure that services and clients implemented according to Jakarta RPC work well with other Jakarta EE technologies, such as CDI and Config, which is not currently the case with plain grpc-java.

Future Work

The main goal for the next twelve months is to finalize the specification with a broader community, and get the 1.0 version of the spec included into one of upcoming Jakarta EE releases, and to implement RI and TCK.

As for evangelism, the goal is to both write about and speak on the subject at Java conferences, and any help in that regard is very much appreciated.

Project Scheduling

The plan is to start work on the spec and RI in Q1 2022, and hopefully finish it in time for Jakarta EE 11 release.

Initial Contribution

The bulk of the contribution currently exists within Helidon gRPC project, and Oracle holds the copyright.

When we set out to implement gRPC support in Helidon, we wanted it to be more along the lines of JAX-RS on the server, and MP REST Client on the client.

On the server you simply implement a CDI bean with some annotated methods, and provide additional metadata, such as service name and the marshaller to use, via class-level annotations. Here are a few examples of Helidon gRPC services:

https://github.com/helidon-sockshop/payment/blob/master/payment-core/src/main/java/io/helidon/examples/sockshop/payment/PaymentGrpc.java (pure gRPC service, which uses JSONB as a marshaller)

https://github.com/helidon-sockshop/shipping/blob/master/shipping-core/src/main/java/io/helidon/examples/sockshop/shipping/ShippingResource.java (single class supports both JAX-RS and gRPC endpoint -- not something I'd recommend, but we wanted to show that it can be done for simple use cases)

https://github.com/coherence-community/todo-list-example/blob/master/java/helidon-server/src/main/java/com/oracle/coherence/examples/todo/server/grpc/ToDoListGrpcApi.java (slightly more complex service implementation, which uses POF for marshaling, and defines message types as nested classes) 

On the client, you simply define an annotated interface and let the framework create and inject proxy for you:

https://github.com/helidon-sockshop/orders/blob/master/orders-core/src/main/java/io/helidon/examples/sockshop/orders/PaymentClient.java

https://github.com/helidon-sockshop/orders/blob/master/orders-core/src/main/java/io/helidon/examples/sockshop/orders/ShippingClient.java

which can then be injected into another CDI bean and used like this:

https://github.com/helidon-sockshop/orders/blob/master/orders-core/src/main/java/io/helidon/examples/sockshop/orders/DefaultOrderProcessor.java#L60

The plan is to move relevant interfaces, classes, and annotations from io.helidon namespace into jakarta namespace, and iterate on the specification with a broader community until we reach concensus.

The spec itself shouldn't have any third party dependencies, but the implementations of the spec will likely depend on  grpc-java, which is licensed under Apache 2.0 license.

Source Repository Type

I believe Red Hat will need more time to fully respond to this project proposal. Some of our initial concerns is that this seems to surface existing implementation details such focus on ease of use and minimization of protobuf, blocking in nature, and no security considerations.

The Red Hat gRPC from Quarkus has come up with the following annotated pros/cons lists:

Pros

  • Marshaller; Clearly a great point and very interesting. The usage of JSON (as in their example) is somewhat weird (remember, gRPC is intended to be “fast”
  • REST Client-Like Clients; That’s a very neat idea. Allows reducing the service surface and implement ambassadors (integration with MP Fault Tolerance) It may not be practical in the sense that the method name must exactly match (which is not the case for the rest client as only the VERB + Path) must match.
  • Simplified Development model; It has always been a hurdle for gRPC (Java). It may require the user to write lots of message classes which could be automatically generated using protoc or similar tooling. Typically, the demo is using Lombok… That does not sound right (maybe records can help).

Cons

  • Blocking first; gRPC is non-blocking by default. Making the experience blocking first is wrong. Typically, bi-directional streaming is not possible. How is the gRPC back-pressure implemented with such an approach?
  • No tooling; We can see that it looks attractive, but the IDL and tooling around gRPC is also the reason it’s working: clear contract definition, handle schema evolution. Sending unstructured text messages feels wrong. Most of the time, it’s just because the tooling is not correctly integrated into the framework. In Quarkus, you drop the IDL, and you're done. No tooling.
  • Generic dispatching; The proposed approach will need dynamic dispatching at runtime. It will introduce a performance cost.
  • No implementation check; Nothing verifies that the implementation / client matches the IDL. It may introduce complex debugging, as name must exactly match (and proto method name <-> Java is NOT simple)
  • No gRPC metadata; The proposed development model does not allow custom gRPC fields or headers, which are often useful to pass metadata.

In summary, the approach is very interesting. It explores gRPC beyond the classical usage. At the moment, it feels that it still needs a lot of work to provide something relevant. In our opinion, this does not feel like gRPC, and not like JAX-RS, something in-between and it would benefit the project to have a multi-vendor implementation prototype(s) to validate the direction the specification should take.

 

Great news to see our embrace with the modern RPC model. If we name it Jakarta RPC, what's the relationship with the existence spec, such as JAX-RS. IMO, it's a low-level spec below it, right? Another, I was curious how do we eliminate the concrete implementation of the gRPC transport, although we have shown it explicitly NOT in scope. if we just leverage existing work done by the grpc-java team, how do we finish the project scope?