Is moving away from RPC a good idea?

390 views
Skip to first unread message

Christian Hebert

unread,
Jan 10, 2024, 11:26:04 AMJan 10
to GWT Users
Hi guys, I've seen the changes in the new release regarding jakarta servlets, which is great, it's a step toward jakarta but to this day,  GWT is still based on the Servlet API 3.1.

Prior of seeing that change, I tried to move away from RPC calls and use http requests instead. I found a nice library called RestyGWT (https://resty-gwt.github.io/) who can really simplify the process of handling json data from/to a Rest API.

So I converted my GWT remote servlets to a Rest API, made a few minor changes in my client code and voilà, I was able to deploy it on a Jakarta Application server since there is no GWT involved on the server side anymore.

The last version of RestyGWT has been release in 2020 so I'm not sure how active this project is but from what I've seen it's enough for me.

So, I would like to get your thoughts on that.  Would you go on that road? stick to RPC calls and wait for a version of GWT based on Jakarta? build your "own" GWT with the changes introduced in the vew version?

Michael Conrad

unread,
Jan 10, 2024, 2:45:31 PMJan 10
to google-we...@googlegroups.com
You should investigate the DominoKit project. They have a much more up-to-date JSON/Jackson-ish implementation.

Ref: https://github.com/DominoKit/domino-rest
--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit/8fa7dc19-2a15-442d-93b2-adebb947046cn%40googlegroups.com.

Colin Alworth

unread,
Jan 10, 2024, 9:00:52 PMJan 10
to GWT Users
With 2.11 released, GWT-RPC (and RequestFactory) work on jakarta.servlet. There are no specific improvements that I'm aware of that require updating beyond the Servlet API 5.0, which is what gwt-servlet-jakarta uses.

I _believe_ that RestyGWT relies on Generators, so might make an eventual move to J2CL difficult, if that happens to be on your radar.

My personal experience is that GWT-RPC is imperfect in a lot of ways, but for the kinds of things that GWT excels at, I still often find it to be better than the other options. It is explicitly for GWT clients, and it uses the shared DTO types as the source of truth for how to de/serialize, so it ensures a certain consistency that way.

JSON-over-HTTP (whether actual REST or not) has me missing real object graphs, numerical precision (somehow JSON's spec allows for infinite precision for ints/floats, but forgot to add infinity/nan? and yet the JS runtime cuts off that precision to what fits in an IEEE754 64bit float...), no date/time support, and not terribly efficient for large payloads. It does a pretty great job of being okay in any language/runtime though, but it isnt hard to get subtle serialization differences, and end up needing not just a schema to share (openapi/swagger/etc can help with this), but also deciding what those conventions will be. JSON can also work well over other transports, such as websockets - same basic limitations as with HTTP, but depending on your use case could well be worth examining.

I've had a lot of close-up experiences with gRPC lately (protobufs, flatbufs, and Apache Arrow's Flight protocol in GWT), and I nearly like it, aside from the abysmal support for browser clients. gRPC offers some tools that at least REST doesn't - streaming data being the main one, and overt RPC calls rather than relying on consistent definitions of REST verbs (which is wonderful when done right, but most teams using "REST" are usually just "JSON-over-HTTP RPC"). This could be (and may yet be someday) a whole article by itself someday, but gRPC is outright incompatible with browsers without first translating to gRPC-web usually requiring a proxy between server and JS client), the default JS client can't do stream server data with binary formatting (only text formatting allowed), and the browser itself can't handle bidirection streaming at all. But you define your services and types outside of any language, each language gets bindings generated for it which will be consistent with all other languages, and, if used properly, clients/servers are forwards and backwards compatible with each other. Some niceties like subclasses, nullable collections and strings aren't available or at least hard to reproduce in a recognizable way. There is also no good code generation for GWT at this time, so we've been operating using generated jsinterop from the grpc and proto libraries and generated code, with decent success. If you are interested in pursuing gRPC, we have worked on a servlet (jakarta and javax) implementation of gRPC, and a servlet filter implementation that in-process handles the grpc-web translation. We also worked up a websocket implementation that behaves like an http2 transport, with multiple concurrent streams running on it, even over http/1.1.

One final note: we forked gwt-rpc a few years ago to provide a binary wire format and built-in websocket support. The focus of our use case was on "struct-like" types, avoiding most collections and polymorphism, but the implementation can still handle most situations that regular GWT-RPC can deal with, but without writing to utf-8 strings (offering a significant performance improvement for large payloads), and allowing interop with non-GWT clients (JVM and android clients are provided, TeaVM works in our experiments, but hasn't been published, and there are closed source c++ and c# clients as well). I haven't updated this to use jakarta.servlet yet, but I imagine it would take less than a day to start and finish it.

Vassilis Virvilis

unread,
Jan 11, 2024, 3:35:05 AMJan 11
to google-we...@googlegroups.com
First of all thanks for doing this work. It is hugely appreciated and required in order to avoid GWT and GWT projects look like zombies in a dead landscape.

I am using RestyGWT and yes I also believe it uses Generators (GWT.create() ?). I am facing a problem there since RestyGWT is deadish itself.

One of the reasons I abandoned GWT-RPC was Jsinterop. With Jsinterop you can include and link to js libraries in the client. Some of them require data from the backend e.g. datatables.net, d3 etc. GWT-RPC is not compatible with them so I would need to use RequestFactory, which I never liked or another framework. So why have two of them? Use one. Go to JSON. RestyGWT was the only viable choice at the time.

With Resty-GWT I can have my POjOs without annotations, and I can share them between backend, frontend and other clients (non web). RestyGWT has 2 backends:
- an older private jackson like (forked) implementation. That's the one I use.
- a newer gwt-jackson based one. This one never worked for me.

Furthermore I have invested in RestGWT and I have some custom patches so RestyGWT can transmit my generics.

At this point domino-jackson and domino-rest looks like the way forward but from a quick look require annotations in the POJO and this is something that I would like to avoid.

Just my 2 bits. Sorry if incoherent...






--
Vassilis Virvilis

Frank Hossfeld

unread,
Jan 11, 2024, 8:40:11 AMJan 11
to GWT Users
Using domino-rest, the POJO have usually only one annotation: @JSONMapper.

Vegegoku

unread,
Jan 11, 2024, 10:10:06 AMJan 11
to GWT Users
Domino-rest is up-to-date well documented and in our next release -Currently available in the HEAD-SNAPSHOT- we are moving to jakarta namespace.

Full documentation can be found in our website here https://dominokit.com/solutions/domino-rest/v1/docs/getting-started

Vegegoku

unread,
Jan 11, 2024, 10:13:24 AMJan 11
to GWT Users
The annotation on the POJO is not required at all, Domino-rest will auto generate the json-mapping classes if the jax-rs/jakarata resource consumes/produces a json even if the annotation is missing, so you can keep the POJO clean or only have Jackson compatible annotations. ;-)

Vassilis Virvilis

unread,
Jan 11, 2024, 10:20:32 AMJan 11
to google-we...@googlegroups.com
Hi Vegegoku,

Thanks for clearing that up.

At some point I will definitely try the domino-rest/jackson.

For now I dread the time I will eventually be forced to port my current setup.




--
Vassilis Virvilis

Leon Pennings

unread,
Jan 12, 2024, 8:59:00 AMJan 12
to GWT Users
I think moving away from gwt-rpc is a bad idea. 
A big advantage of GWT is that I can code everything in java and do not have to serialize anything to and from text.
That to me is one of the usp's of GWT.
Going from java -> json -> java (or gwt java), is like trying to have a complex conversation between 2 Dutch guys, but with a German translator in between. 




Op donderdag 11 januari 2024 om 16:20:32 UTC+1 schreef Vassilis Virvilis:

Ralph Fiergolla

unread,
Jan 12, 2024, 9:17:00 AMJan 12
to google-we...@googlegroups.com
Fully agree - and very much like the example!

Jens

unread,
Jan 12, 2024, 11:33:33 AMJan 12
to GWT Users
If you do not have special needs I think GWT-RPC is still fine especially with a jakarta version now available. But while it is easy to use it also has some annoying downsides you have to live with.

However there are quite some options:
- JsInterop based DTOs + JSON.parse/stringify. However you loose inheritance or have to write some helper code to workaround it as needed
- Use a json based library that solves the polymorphism problem for you
- Use gRPC for the web (grpc-web) which requires a proxy in front of your server gRPC endpoint to transparently convert binary to json
- Use websocket in either plain text mode or binary mode. If in binary mode you could use protobuf or similar to build the payload

Personally I always wanted to explore using nats.io, which is a message broker that also supports a request-reply pattern out of the box. That means a message channel/topic acts like a service. Nats has a nats-websocket library which connects browsers to the message broker and you can use protobuf or similar to define/generate your binary messages. Because you now have a message broker between clients and servers it should be relatively easy to scale and you get things like broadcast a message to all clients (push) with little effort. Nats also has a distributed KV store integrated if needed.

-- J.

Ed

unread,
Jan 12, 2024, 5:49:43 PMJan 12
to google-we...@googlegroups.com

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Alex Karg

unread,
Jan 13, 2024, 8:08:33 AMJan 13
to GWT Users
gwt-rpc is one of the parts I like the most about GWT and why we chose GWT to start with. Same DTOs on client and server and you don't have to care (too much) about de/serialization. Why do I care about JSON, or binary or whatever serialized format, as long as it is secure, performant and serialization is able to handle my object relation structures?

Some mention "some annoying downsides" or "is imperfect in a lot of ways" regarding gwt-rpc. What are does? The only argument I understood so far, is that it may require you to have gwt-rpc and REST/RequestFactory client-server channels in parallel. We had that since the very beginning, because of OAuth, captcha, file download links etc.. I never saw any practical issues with that set up. For example with spring-security we can easily map both channels to the same user/roles/rights concept.

Paul Robinson

unread,
Jan 13, 2024, 5:46:42 PMJan 13
to google-we...@googlegroups.com
One thing I really like about using JSON for my message formats is that they are human readable (YMMV).

If you're wondering whether a problem is client side or server side, or when you just want to know exactly what information the client was given, being able to read the content of messages can be very useful. 

Paul

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Jens

unread,
Jan 15, 2024, 11:26:30 AMJan 15
to GWT Users
Some mention "some annoying downsides" or "is imperfect in a lot of ways" regarding gwt-rpc. What are does?

1. Client and server always need to be in sync because of serialization policy. So a user must reload the web app if you redeploy your application and have modified shared classes. 
2. If you want to use J2CL in the future you should not use it.
3. You can only use it with GWT clients unless you reimplement the wire format in other languages / applications. Only unofficial information about the wire format exists. 
4. No async servlet support
5. Command pattern doesn't work well with GWT-RPC because you cannot code split the client side serialization data. So your initial or leftover fragment contains everything that goes over the wire. Code splitting only works well if you have one GWT-RPC service per code split condition.

Cricri

unread,
Jan 15, 2024, 4:33:23 PMJan 15
to google-we...@googlegroups.com
Finally I've decided to stick to RPC and use gwt-servlet-jakarta. We will have a lot of applications (50+) to migrate to jakarta at some point, this will be the fastest way.

Thanks all for your comments.

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-tool...@googlegroups.com.

Alex Karg

unread,
Feb 9, 2024, 10:36:37 AMFeb 9
to google-we...@googlegroups.com
Thanks for that answer Jens. Makes perfect sense.

Regarding point 1, I am thinking about a more seamless upgrade process that minimizes client interruption. Such that old clients can remain working on "old" server versions for a while, while new clients work on new servers in parallel, until all old clients are migrated in a controlled process. Once no old clients are connected any more, the old servers are shut down and the upgrade process is completed.

Is there any suggested standard approach (e.g. Load Balancer Setups, Client-Server Interface Versioning) to achieve this? Anyone doing this successfully?

Freundliche Grüsse,
Alexander Karg



--

Leon

unread,
Feb 9, 2024, 11:00:03 AMFeb 9
to google-we...@googlegroups.com
If you define a non-existent html cache and/or update your server early in the morning or late in the evening you will not have a problem. All browser clients will reload the latest version.
Fallback is to show a warning in the GWT client that the browser needs a cache clearing when you get a serialization error.
The serialization error is a handy tool for making sure no outdated client connects to a newer backend. Unless you made no GWT changes with the new backend, then no-one will notice anyway.

I would not be one to choose for a dual version in production. It'll turn into a bit of a mess when you have DB changes or domain logic changes.





You received this message because you are subscribed to a topic in the Google Groups "GWT Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/ggDdh0rb6eM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit/CAHcNM3K8e4KTDhB04yDDKPpP%3Dmp1C7776dPJSdR4%2B5wemXdUww%40mail.gmail.com.

Colin Alworth

unread,
Feb 9, 2024, 11:05:13 AMFeb 9
to GWT Users
Point 1 is a potentially a serious concern for basically any tooling that decouples through interprocess communication, including grpc+protobuf (with ostensibly "perfect backwards/forwards compatibility") - in tooling that doesn't explicitly force compatibility as GWT-RPC does, you have to implicitly handle the edge cases, like versioning each method/type in some way, or established rules like "reject messages that have new fields or old fields" (which includes never fully deleting fields), and never change the meaning of fields "oh, as of 3.1.2 we trim whitespace, sorry that was significant for you"). GWT-RPC is a lot grumpier about it - change fields of any one type used by any one method in your service, and the entire service is invalid. Poof, you know instantly that something is invalid, and should update to continue.

A disciplined approach like what gRPC forces, where fields added must always be safe to skip and fields removed must never change the meaning of the message ends up requiring design-time work to enforce, and those notions can apply to other tools as well. Only add service calls, version the service when any DTO/message type changes, and keep backwards compatiblity for old versions for a release or two. As long as you upgrade your servers past these breaking points slightly less often than the intervals over which clients get updates, this can't go wrong (and applies cleanly for gwt-rpc as well). Among other projects, the envoy proxy's XDS service is very aggressive about this - it works, and ensures you can aggressively evolve the services, but it sure is a pain for XDS clients to keep up with.

 In the middle somewhere is to do what most teams do, and take a "eh, this probably isn't _that_ important to miss" approach, and a few calls/cases may fail from time to time.

Going back to envoy briefly, XDS makes it possible for the proxy to change endpoints it supports on the fly based on service calls to update the cluster configuration. For long-running streams it can make sense to simply say "Add new cluster member Y, and when you are done with all active connections to instance X, don't allow future connections to it". GWT-RPC isn't streaming out of the box (our GWT-RPC fork is, and is intended to be j2cl/jvm/android/etc compatible), so you need to introduce "sessions" somehow into the vocabulary, or add metadata to responses ("X-FooSoft-Version: 4" means if you speak version 3, time to upgrade, or "X-Deprecated: true" means you're out of date and should update soon, etc) that the client should always check, and assume that rotation can happen over some range of hours or days.
Reply all
Reply to author
Forward
0 new messages