Java Functions for Spring Cloud Stream Applications

What Has Changed?

Java Functions

Continual advances in the Java and Spring ecosystem have driven us to rethink our approach. The most significant change is that we have implemented a layered architecture in which the core functionality, previously provided by the app starters, are now provided as Java functions, implementing the standard interfaces found in the java.util.function package.

The functional components in this release can be exposed as standard Spring beans and then used for your data integration needs by directly embedding them in an application. By injecting these functions in a custom application, you immediately benefit from the features provided by underlying libraries. For example, Spring Integration adapters are used in many of these functions. You can invoke the function directly, use Spring Cloud Function to invoke it through a REST endpoint, or use it in a serverless environment. Unlike the app starters, the functional components have no dependency on Spring Cloud Stream. They are now, however, the core components of the stream applications. The following image shows the relationship between the components and the applications:


Stream Applications

By using Spring Cloud Stream, we can exploit the logical equivalence of the java.util.function types (Supplier, Function, Consumer) to the Spring Cloud Stream concepts (source, processor, and sink, respectively). As before, we use a new and improved Maven plugin to generate the Spring Boot main class, application.properties file, and binder-specific Maven poms with built-in monitoring and security support. With few exceptions, we can build the Spring Cloud Stream applications with no additional code.

The new approach offers several advantages:

Spring Cloud Stream v3.x introduced a powerful Functional programming model based on Spring Cloud Function. This approach is favored over the legacy annotation-based model (@EnableBinding, @StreamListener). Spring Cloud Stream can bind directly to the input(s) and output(s) of a Function @Bean. With this model, neither the legacy Spring Cloud Stream annotations nor the Source, Processor, and Sink interfaces are needed.

The figure below illustrates this concept by using simple functions packaged as Spring Cloud Stream applications. The binder implementation and external configuration properties enable the applications to communicate through a message broker, but the application code is not concerned with any of this. Spring Cloud Stream invokes the helloTime Function in the ProcessorApplication whenever a message arrives on the time topic and directs its output to the hello topic. Likewise, the printTime Consumer in the SinkApplication is triggered by a message arriving on the hello topic. But what triggers the SourceApplication? As you may have guessed, Spring Cloud Stream auto-configures a poller, which invokes the currentTime Supplier every second (by default). Of course, this is configurable.

The functional components are available to be packaged and deployed in a wide range of uses other than Spring Cloud Stream, particularly in FaaS environments.

The functional components are built with Project Reactor, where appropriate, to enable non-blocking reactive streaming.

The stream applications (or any Spring Boot application built with the functional components) can take advantage of Spring Cloud Function’s declarative function composition features. This means that the pre-packaged stream applications can be configured to perform common transformation and filtering operations with no customization required.

The new stream-applications Git repository is a monorepo. Unlike stream-cloud-app-starters, where each app has its own repository, the new stream-applications repository contains everything (functions, applications, and common components) in a single repository. This simplifies dependency management and allows for atomic commits. The hope is that this change, along with other ongoing efforts, will make it easier for developers and help encourage community contributions.

What Does this Release Contain?
The following is a partial list of the various functions and applications available in this release:

Suppliers and sources: File, FTP, SFTP, AWS S3, HTTP, Geode, TCP, TIme, Twitter, Websocket, JDBC, JMS, RabbitMQ, MQTT.

Consumers and sinks: Analytics, Cassandra, File, FTP, Geode, JDBC, Log, Mongodb, MQTT, Rabbit, Redis, AWS S3, SFTP, TCP, Twitter, Wavefront, Websocket.

Functions and processors: Filter, Header Enricher, HTTP Request, Tensorflow (image recognition, object detection and semantic segmentation), SpEL, Splitter, Task Launch Request, Task Launcher, Twitter.

See the Stream Applications README for a complete list.

What does this mean for current users?
In many cases, the new applications provide the equivalent functionality as the previous releases. In some cases (such as Twitter), we have significantly enhanced the functionality. We also have merged and renamed some of the applications. In short, there are some breaking changes. Notably, many of the configuration property names have changed, where appropriate, to reflect an association with the functional components (for example, s3.supplier.remoteDir). Also, these applications may not work with stream applications that are built with older releases of Spring Cloud Stream. For example, a source built with an older version of Spring Cloud Stream is not guaranteed to work with a sink from this release. If you are already using pre-packaged applications from a previous release, there is no need to upgrade immediately, unless you are compelled to take advantage of some of the new features. The Einstein release train will go into maintenance mode, so it will include only bug fixes going forward. All new development will be applied to future releases.

How do I contribute a new function or application?
If you cannot find what you are looking for in the existing catalog of functions and applications, please consider contributing. This way, the entire open source community will benefit. In a subsequent post, we will walk through a real-world example of developing a function and stream application.

We encourage the community to get involved with this project. We have several open issues labelled ideal for contribution. In addition to code contributions, we really appreciate documentation improvements, creating issues, and starring the repository.

Comments

Popular posts from this blog

Today Walkin 14th-Sept

Spring Elasticsearch Operations

Hibernate Search - Elasticsearch with JSON manipulation