Blog

Why you don't need REST endpoint classes with Hilla

By  
Leif Åstrand
Leif Åstrand
·
On Oct 5, 2023 12:00:00 AM
·
In Product

We are introducing some new terminology with Hilla 2.2. We have renamed the server-side logic that you call from the browser to "browser-callable services" instead of "endpoints." We have realized that the endpoint terminology leads us to think about the network communication layer in an overly complex way.

The new name emphasizes the simplicity of calling methods exposed by any bean from the browser, and it helps avoid associating with concepts such as URL structures and HTTP verbs that are inherent to REST endpoints.

Background: Why you need endpoint classes without Hilla

Explicitly defined endpoints let you control what is sent over the network and how it is sent. Focus on the how is especially important when you've got multiple different clients using the same endpoints, and those clients are not necessarily updated with the same cadence as the endpoints. With such requirements, you want to explicitly control the data representation format to make sure it can be evolved in the future. When introducing changes, you want to ensure those changes are either backwards compatible or introduced as a new version alongside the original endpoints.

REST patterns attach additional semantics to things like the structure of the path of the request URL, the HTTP verb (e.g., GET and POST), various headers, and sometimes, even references to additional actions inside the request payload (HATEOAS). These conventions make it easier for developers of 3rd party clients to know what to expect and thus make it easier for them to start using the API.

The requirements are simpler for a single web client

Hilla is a different beast. Hilla takes care of the communication protocol for a single web UI. We have found that referring to Hilla's communication layer as "endpoints" creates associations with concerns that are specific to REST endpoints. By talking about browser-callable services, we focus on the role of the communication layer: the easiest possible way of accessing business logic from application code running in the browser.

The frontend logic in a Hilla application uses generated TypeScript wrappers for sending messages to the server and receiving responses. There is no need for explicit versioning of the interchange format since every client runs on the latest version immediately when the page is loaded in the browser. We acknowledge that we should make it easier to detect when the page needs to be reloaded, but we don't think it's necessary to go further than that.

If you need to support 3rd party REST clients, then we recommend that you define those endpoints separately (using e.g., @RestController) from the communication layer for the Hilla frontend. This concept is generally referred to as the Backend for Frontend architecture pattern.

Hilla is MVC in the browser

The separate endpoint classes in a typical REST application (e.g., @RestController classes) exist to give explicit control over how data is sent over the network. All business logic and access control should be implemented in the service layer, whereas the endpoint layer is only a translator between the service layer and the communication format based on JSON (or XML) over HTTP. There shouldn't be any reason to be concerned about such details with Hilla.

Comparing REST, MVC, and Hilla
Comparing REST, MVC, and Hilla

Rather than comparing Hilla with a REST endpoint architecture, it's more helpful to compare with a MVC architecture where a controller populates a model, which is in turn used to render the view through a server-side HTML template. In that architecture, the controller interacts directly with the service layer. In the case of Hilla, the "controller" is instead TypeScript logic that updates state values based on which React or Lit updates the rendered DOM. This, in turn, means that it should be natural for this "controller" implemented in TypeScript to directly interact with the service layer – through a browser-callable service abstraction. It is still important to define what data is sent Traditional endpoint classes are not only about how data is sent but also about what is being sent. Because that data is passed over the network, you want to be extra careful to avoid accidentally sending sensitive data. You could also tune performance by aggregating everything needed by a view into a single response and by omitting properties that are not used in the UI.

This aspect of what is sent can be handled in many different ways depending on application requirements and personal preferences. Some typical ways are to define explicit DTO types for sending over the network or to use features of the JSON serialization library (e.g., @JsonView) to control what is being sent based on the business objects returned by the service layer. Because of these matters, you might still have a thin conversion layer between the service layer and the network. We still encourage you to think of this layer as a DTO conversion service rather than as endpoints because it is only concerned with the what but not the how of the network communication. That's why we prefer to call services instead of endpoints We like the word "endpoint" on its own for describing Hilla's communication. Still, we have come to realize that many developers that we talk to make an automatic association with "REST endpoint," and that leads them to misunderstand the main point. This is why we introduce the concept of a "browser-callable service" to shift the focus towards the ease of accessing Spring services from the browser.

Discover what else is new in Hilla 2.2 →

Leif Åstrand
Leif Åstrand
Leif Åstrand keeps an eye on the overall architecture of the Vaadin platform. He knows a thing or two about how Vaadin, Web Components, and the internet works.
Other posts by Leif Åstrand