Is GraphQL the Resurgence of RPC style API’s?

GraphQL’s development started in 2012 at Facebook to mitigate the issues they faced integrating their mobile application with the verbose API’s the website used before it was released to the public in 2015. Since then, the there has been a public debate if GraphQL should be classified as RPC-style API standard or if it is something entirely different. While there has always been a debate of which API style might be best, the truth is that each style has its advantages and shortcomings and is tailored to solve a specific use case. So let’s try to understand the differences and commonalities between RPC, REST and GraphQL before coming to the conclusion that GraphQL might be the latest resurgence of RPC style API integration.

RPC – Remote Procedure Calls

Remote Procedure Calls were developed in the 1970’s gained adoption throughout the 1980’s where Bruce Jay Nelson is credited to coin the term for the technique of calling a function or subroutine over the network on a different computational node and expecting a response. From an API point of view, the unit of interest is the function that defines the service. With the advent of REST, RPC style communication lost initially some traction but re-gained interest resulting in gRPC or Apache Thrift.

Advantages

  • Simple and easy to understand as each function describes semantically its intention
  • Payloads are lightweight and tailored to the problem the function solces
  • Performance generally higher as protocol layers can be optimized for RPC execution

Disadvantages

  • Tight coupling between a service provider and consumer based on function and related data sets
  • No standardization, implementations vary and services can not be discovered through standardized lookups
  • It is easy to add additional functions which results often in the so called “function explosion”
  • Maintenance of different RPC services grows more and more difficult with the growing number of services and dependencies
  • No standardized abstraction at an API layer that is decoupled from the underlying system

REST – Representational State Transfer

REST defines a set of constraints to expose resources via URLs. The term was introduced in 2000 by Roy Fielding and described the principles that were discussed during the 1990s as “HTTP object model” resulting in the Uniform Resource Identifiers standard. With its focus on resources and the adoption of the HTTP protocol, that defines the operations that can be applied on resources, REST achieves the opposite of tight coupling. The latest development defining the REST API interaction model further resulted in the JSON Hypertext Application Language (HAL), JSON-API as a specification for building APIs in JSON and the Ion Hypermedia Type as intuitive, JSON-based hypermedia type.

Advantages

  • Client and server are semantically decoupled and only focused on operations around resource access
  • API can evolve over time as long as basic constraints for backward compatibility are respected
  • Use of the HTTP protocol helps to decrease resource consumption and reduces the network bandwidth resulting in APIs performance
  • No limitations regarding the data format used between client and server

Disadvantages

  • Not a single specification that defines the way the interaction between service provider and consumer should be structured
  • Potential for large payloads that reduce the overall application performance for both, server and client

GraphQL – Query language for your API

GraphQL is a query language for your API, was developed since 2012 by Facebook as a response to their transition to mobile and released in 2015 to the open-source community. Since 2018 the project was moved to the newly found GraphQL Foundation and hosted by the Linux Foundation. GraphQL offers clients the ability to define the structure of they expect. To achieve that, the central unit of the work is structured around is a query. The latest development includes a schema definition as a description of all queries that can be executed against a service. The queries provide the client with flexibility to defined what they expect.

Advantages

  • Due to the nature that queries specify exactly what a service consumer needs, the network overhead is low
  • The schema definition is typed and both service provider and consumer can use the definition as contract
  • Larger object graphs are best suited to be exposed via a GraphQL service since clients want to consume portions of the entirety

Disadvantages

  • Exposing queries instead of the simple HTTP protocol operations increase complexity of adopting the framework
  • Caching architectures that fit the HTTP resource model become obsolete since not all data is exposed in a default way consistently
  • Versioning of queries and attributes is not clearly defined by any set of best practices

Conclusion

When looking at the core concepts of each API style, it becomes obvious that there is a clear distinction between the resource-centric view of REST and the functional- and query-based perspective of RPC and GraphQL API styles. Trying to distinguish between functions and queries becomes much harder and I agree with Phil Sturgeon’s statement:

“GraphQL is essentially RPC, with a lot of good ideas from the REST/HTTP community tacked in”

The biggest advantage that I see over REST is, that the specification has lead to a clear schema enabling the navigation of your object tree whereas REST-full services have often the notion of an RPC-style interaction based on HTTP operations without considering the navigation across resources. I think it is fair to say that there are commonalities between GraphQL and RPC, but SQL like queries provide still more flexibility than exposing a function that accomplishes something. As a consequence, I would not consider GraphQL to be the resurgence of the RPC API-style and rather a valuable addition to the existing set of

Each of these API-styles has its own use case and there is not a single API-style that can be considered to be superior to another. The advantages of each API-style feature and I recommend considering the adoption of more than one when building out APIs to offer integration points to your applications. There are cases, where a query-based integration style might be superior, i.e. when trying to integrate flexibly with a data or a mobile API, but there are other API scenarios like a management or command API that has entirely different requirements on how to interact with the data and the functions it exposes.

References

  1. GraphQL – A query language for your API
  2. Phil Sturgeon – Understanding RPC, REST and GraphQL
  3. Tom Smith – APIs: RPC versus REST versus GraphQL
  4. Renato Athaydes – The return of RPC
  5. gRPC – A high performance, open-source universal RPC framework
  6. Apache Foundation – Apache Thrift
  7. M. Kelly – JSON Hypertext Application Language
  8. JSON-API – A specification for building APIs in JSON
  9. Ion Working Group – The Ion Hypermedia Type

Esper Component Configuration and Config File Support in Camel-Extra

While I was going through the list of enhancement requests for Camel-Extra, which is a community project related to Apache Camel, I came across an old request asking to support the default Esper configuration in order to ease the development of event patterns and queries. Camel-Extra is a sister project of ASF Camel that hosts components, which are not compliant to the Apache license. Within that space Esper is a LGPL licensed library that supports complex event processing (CEP) and analytics on event series. The the Camel component has been generously contributed to Camel-Extra by James Strachan in November 2007. Although Esper possesses only a small number of configuration parameters, it is sometimes quite useful to simplify event patterns and event processing language (EPL) statements by providing a small amount of configuration parameters. Additionally, it might be useful to provide some tuning parameters meeting specific requirements. However, I am not tempted to offer a detailed description on how to configure the Esper engine in order to meet your specific requirements, since you will find a comprehensive guide in the Esper documentation. I will rather write on how to use the current camel-esper component.

Using Camel-Esper to Query Event Streams

Before diving into the configuration example, I would like to provide an overview, on how the camel-esper component can be configured in your route configuration in order to execute queries upon event streams without neglecting the fact, that you will always find the most recent documentation within the component description of Apache Camel. The component adheres to the overall Camel concept that defines a processing chain via an integration DSL calling subsystems via endpoint URI configurations. Esper can be considered within this context as one of those subsystems, which leads us to the fact that you need to configure an endpoint for being able to interact with the Esper library and framework.

Conceptual Overview: Calling Esper from Camel

Since Esper is embedded within Camel as component concept, addressing the component works like addressing any other subsystem of Camel. Fig. 1 provides an overview a route configuration which is being used as example. Route 1 has a direct endpoint, which serves as interface where any event producer can send messages in a synchronous invocation style. All messages being consumed from this endpoint will be passed towards an configured Esper endpoint, identified via a name as representing the internal ID within the Camel context that serves as addressable endpoint. The second part of the Esper configuration is a query or pattern piece, which does query the event streams coming through the specific Esper communication channel. Finally, after having executed the evaluation, the message will be passed within route 2 towards a consuming, direct endpoint.
Fig.1: Conceptual route configuration

Fig.1: Conceptual route configuration

This simple example shows already, that the logic to evaluate the event streams is encoded within the Esper endpoint. Esper offers basically two different options to write evaluation statements for event streams, a pattern language and an event query language. Both options have been integrated to the Esper component provided by camel-extra and will be introduced in the next two sections.

Esper Event Query Language Configuration

The first configuration example demonstrates, how it is possible to configure the camel-extra Esper component endpoint to query an event stream via the event processing language. The query language is a SQL like language, specifically designed to query event streams in contrast to database tables. The concept of stream therefore replaces the commonly known concept of tables. Nevertheless, since events are nothing else than data, the existing SQL concepts of joins, filtering and aggregation via grouping can be effectively applied upon streams as well. In order to run your event queries based upon the event processing language, it is necessary to specify the eql option followed by the actual expression. In our case, we are looking for all events of type StockTick having the symbol AAPL which results in the select statement of the above endpoint configuration.

Esper Event Pattern Language Configuration

The second example shows a configuration option for using the event pattern language. The pattern language is based upon University research, originally conducted within the “Rapid” project at Stanford University. The Esper implementation is based upon dynamic state trees and can be considered as so called delta networks, where only changes to data is being communicated across object boundaries. Additionally, changes are only propagated, if the information is needed somewhere else. To optimise performance, Esper operates upon indices for data retrieval operations. The entire grammar of the pattern language is build on top of ANTLR, based on the Extended Backus-Naur Form (EBNF). To enable the Esper pattern language, it is required to define the pattern option in your endpoint configuration followed by the pattern expression you want to execute. In the example, we are looking for every Stock tick that contains the symbol ‘AAPL’, since we want to retrieve all information related to Apple. One may have noticed, that addressing an event object requires the full package name, in order to acquaint Esper with the respective event type. Since typing the entire package name including the name of the actual Java object can be cumbersome, the following section introduces a different way, to induce the addressing of event types.

Enabling the File-based Configuration for Esper

Esper contains an option to provide configuration via an external XML-based file. The purpose of the configuration file is on the one hand to simplify queries, written in EPL and pattern language and on the other hand, to tune the engine behaviour to meet your individual requirements. Camel-extra’s Esper component supports the configuration via the default configuration file. To enable the configuration via XML in camel-esper, it is required to set the configured option to true, a flag set per default to false. The specification of this parameter ensures, that camel-esper conducts a lookup for the esper.cfg.xml file in the root of your class path (e.g. <project_home>/src/main/resources/esper.cfg.xml). Having enabled the XML-based configuration, it is now possible to add a name for an event type and it’s corresponding class with fully qualified name (i.e. including the package name). This way, Esper knows, that the name refers to a specific address so that the name can be used within the EPL or pattern language. This example shows only a very limited set of configuration options provided by Esper. For a full reference, please refer to the configuration section of the Esper documentation.

Summary

This article briefly introduces camel-esper, a component hosted within the camel-extra project. It outlines the integration and use of Esper within a camel route configuration at a conceptual level and demonstrates, how to adopt the EPL and pattern language, in order to select events from an event stream. Finally, one of the recently added features, of using the default Esper configuration via an XML file concludes the article and gives some insights in how to optimise your Camel application, when using Esper. Since the article introduces only the general usage concept, some further reading can be recommended.
  1. Apache Camel Component Concept
  2. Camel-Extra Esper Component
  3. Camel-Extra Project
  4. Esper Event Processing Language
  5. Esper Pattern Language
  6. Esper Configuration