Posts Tagged ‘EventDriven’
[DevoxxUK2024] Processing XML with Kafka Connect by Dale Lane
Dale Lane, a seasoned developer at IBM with a deep focus on event-driven architectures, delivered a compelling session at DevoxxUK2024, unveiling a powerful Kafka Connect plugin designed to streamline XML data processing. With extensive experience in Apache Kafka and Flink, Dale addressed the challenges of integrating XML data into Kafka pipelines, a task often fraught with complexity due to the format’s incompatibility with Kafka’s native data structures like Avro or JSON. His presentation offers practical solutions for developers seeking to bridge external systems with Kafka, transforming XML into more manageable formats or generating XML outputs for legacy systems. Through clear examples, Dale illustrates how this open-source plugin enhances flexibility and efficiency in Kafka Connect pipelines, empowering developers to handle diverse data integration scenarios with ease.
Understanding Kafka Connect Pipelines
Dale begins by demystifying Kafka Connect, a robust framework for moving data between Kafka and external systems. He outlines two primary pipeline types: source pipelines, which import data from external systems into Kafka, and sink pipelines, which export Kafka data to external destinations. A source pipeline typically involves a connector to fetch data, optional transformations to modify or filter it, and a converter to serialize the data into formats like Avro or JSON for Kafka topics. Conversely, a sink pipeline starts with a converter to deserialize Kafka data, followed by transformations and a connector to deliver it to an external system. This foundational explanation sets the stage for understanding where and how XML processing fits into these workflows, ensuring developers grasp the pipeline’s modular structure before diving into specific use cases.
Converting XML for Kafka Integration
A common challenge Dale addresses is integrating XML data from external systems, such as IBM MQ or XML-based web services, into Kafka’s ecosystem, which favors structured formats. He introduces the Kafka Connect plugin, available on GitHub under an Apache license, as a solution to parse XML into structured records early in the pipeline. For instance, using an IBM MQ source connector, the plugin can transform XML documents from a message queue into a generic structured format, allowing subsequent transformations and serialization into JSON or Avro. Dale demonstrates this with a weather API that returns XML strings, showing how the plugin converts these into structured objects for further processing, making them compatible with Kafka tools that struggle with raw XML. This approach significantly enhances the usability of external data within Kafka’s ecosystem.
Generating XML Outputs from Kafka
For scenarios where external systems require XML, Dale showcases the plugin’s ability to convert Kafka’s JSON or Avro messages into XML strings within a sink pipeline. He provides an example using a Kafka topic with JSON messages destined for an IBM MQ system, where the plugin, integrated as part of the sink connector, transforms structured data into XML before delivery. Another case involves an HTTP sink connector posting to an XML-based web service, such as an XML-RPC API. Here, the pipeline deserializes JSON, applies transformations to align with the API’s payload requirements, and uses the plugin to produce an XML string. This flexibility ensures seamless communication with legacy systems, bridging modern Kafka workflows with traditional XML-based infrastructure.
Enhancing Pipelines with Schema Support
Dale emphasizes the plugin’s schema handling capabilities, which add robustness to XML processing. In source pipelines, the plugin can reference an external XSD schema to validate and structure XML data, which is then paired with an Avro converter to submit schemas to a registry, ensuring compatibility with Kafka’s schema-driven ecosystem. In sink pipelines, enabling schema inclusion generates an XSD alongside the XML output, providing a clear description of the data’s structure. Dale illustrates this with a stock price connector, where enabling schema support produces XML events with accompanying XSDs, enhancing interoperability. This feature is particularly valuable for maintaining data integrity across systems, making the plugin a versatile tool for complex integration tasks.
Links:
[DevoxxPL2019] Reactive for the Impatient: A Gentle Introduction to Reactive Programming and Systems
Lecturer
Mary Grygleski serves as a developer advocate at IBM, based in Chicago. She organizes the Chicago Java Users Group (CJUG) and leads IBM-sponsored meetups on topics like reactive systems and cloud technologies. Her background includes promoting community engagement and advancing Java-based reactive frameworks.
Abstract
This article provides an in-depth exploration of reactive programming and systems, emphasizing their emergence to address modern computing demands for responsiveness and scalability. It delineates core principles from the Reactive Manifesto, differentiates reactive paradigms, and surveys key Java libraries: RxJava, Spring Reactor, Akka, and Vert.x. Analytical insights into patterns, methodologies, and real-world applications underscore the significance of asynchronicity, elasticity, and fault tolerance in building impatient-user-friendly systems.
Emergence and Principles of Reactive Systems
The surge in reactive methodologies arises from hardware advancements, such as multi-core CPUs and cloud virtualization, coupled with escalating user expectations for instantaneous responses. Mary traces reactive roots to the 1980s actor model in Erlang for real-time telecommunications, now adapted to handle proliferating devices and concurrent requests. Human impatience drives this evolution, mirroring family dynamics where multiple demands require asynchronous handling.
The Reactive Manifesto, led by Lightbend (creators of Akka), outlines four pillars: responsiveness, elasticity, resiliency, and message-driven architecture. Responsiveness ensures timely replies, even in failures, forming the usability foundation. Elasticity scales resources dynamically under varying loads, maintaining throughput. Resiliency employs replication and isolation for fault containment, preventing systemic collapses. Message-driven mechanics enable the others, facilitating asynchronous, non-blocking communication akin to event-driven systems but with addressed destinations.
Mary clarifies distinctions: reactive programming propagates changes via event streams, functional reactive programming advances via execution threads, and reactive systems orchestrate isolated components cohesively. Event-driven emits unaddressed events for observers, while message-driven specifies recipients, enhancing coordination.
Patterns and Terminologies in Reactive Programming
Reactive programming revolves around responding to external stimuli through event propagation. Streams represent sequential data elements, fundamental to reactivity. Observables emit event streams, observed by subscribers, drawing from design patterns like observer, composite, and iterator.
Using marble diagrams, Mary illustrates streams: empty timelines await events, marbles denote data, vertical lines signal completion. Backpressure management prevents overwhelming consumers. Reactive extensions (Rx) standardize these, with RxJava implementing them in Java.
A noodle shop analogy piques interest: ordering mimics reactive flows, where requests (events) trigger preparations (responses) asynchronously, handling multiple patrons without blocking.
Survey of Java Reactive Libraries: RxJava and Spring Reactor
RxJava, Netflix’s 2013 port of Microsoft’s Reactive Extensions, supports Java 6+ with backpressure in version 2 (2016). It enables declarative, functional-style programming for asynchronous data streams.
Code sample for a simple observable:
import io.reactivex.Flowable;
public class HelloWorld {
public static void main(String[] args) {
Flowable.fromArray(args).subscribe(System.out::println);
}
}
This pipelines arguments into a flowable, subscribing for output.
Spring Reactor, from Pivotal, leverages Java 8 streams for cleaner APIs, fully supporting reactive streams. It integrates with Kafka, Netty, and others.
Comparative example:
// Traditional Spring MVC (blocking)
@GetMapping("/products")
public List<Product> getProducts() {
System.out.println("Traditional way started");
List<Product> products = productService.getProducts();
System.out.println("Traditional way completed");
return products;
}
// Reactive WebFlux (non-blocking)
@GetMapping(value = "/product-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Product> getProductStream() {
System.out.println("Reactive way using Flux started");
Flux<Product> productFlux = productService.getProductStream();
System.out.println("Reactive way using Flux completed");
return productFlux;
}
The reactive version returns a Flux (ticket) immediately, processing asynchronously.
RxJava partially supports reactive streams; Reactor fully, with Reactor favoring Java 8+ for elegance.
Advanced Frameworks: Akka and Vert.x
Akka, from Lightbend, embodies the actor model for event-driven, location-transparent systems. Actors handle functions isolately, with supervisors managing failures for resiliency.
Java Akka hello world:
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
public class HelloWorld extends AbstractActor {
@Override
public void preStart() {
final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class), "greeter");
greeter.tell(Greeter.Msg.GREET, getSelf());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.matchEquals(Greeter.Msg.DONE, msg -> getContext().stop(getSelf()))
.build();
}
}
Scala variant condenses this, leveraging functional conciseness.
Vert.x, from Eclipse, is polyglot, supporting mixed languages. Verticles (actor-like) execute on events, with an event bus for communication.
Vert.x HTTP server:
import io.vertx.core.Vertx;
public class HelloWorldServer {
public static void main(String[] args) {
Vertx.vertx().createHttpServer()
.requestHandler(req -> req.response().end("Hello World"))
.listen(8080);
}
}
Vert.x’s lightweight, non-container-bound nature suits diverse integrations.
Implications for Modern Software Development
Reactive approaches mitigate blocking I/O pitfalls, though database engines lag in full reactivity (e.g., R2DBC offers non-blocking connectivity, but underlying engines remain blocking). Mary advocates community participation, like her reactive meetup group, to foster learning.
In conclusion, reactive paradigms empower scalable, responsive systems, aligning software with hardware and user demands. Frameworks like RxJava, Reactor, Akka, and Vert.x provide tools for implementation, promising flexible, fault-tolerant architectures.
Links:
[DevoxxFR2012] Node.js and JavaScript Everywhere – A Comprehensive Exploration of Full-Stack JavaScript in the Modern Web Ecosystem
Matthew Eernisse is a seasoned web developer whose career spans over fifteen years of building interactive, high-performance applications using JavaScript, Ruby, and Python. As a core engineer at Yammer, Microsoft’s enterprise social networking platform, he has been at the forefront of adopting Node.js for mission-critical services, contributing to a polyglot architecture that leverages the best tools for each job. Author of the influential SitePoint book Build Your Own Ajax Web Applications, Matthew has long championed JavaScript as a first-class language beyond the browser. A drummer, fluent Japanese speaker, and father of three living in San Francisco, he brings a unique blend of technical depth, practical experience, and cultural perspective to his work. His personal blog at fleegix.org remains a valuable archive of JavaScript patterns and web development insights.
This article presents an exhaustively elaborated, deeply extended, and comprehensively restructured expansion of Matthew Eernisse’s 2012 DevoxxFR presentation, Node.js and JavaScript Everywhere, transformed into a definitive treatise on the rise of full-stack JavaScript and its implications for modern software architecture. Delivered at a pivotal moment, just three years after Node.js’s initial release, the talk challenged prevailing myths about server-side JavaScript while offering a grounded, experience-driven assessment of its real-world benefits. Far from being a utopian vision of “write once, run anywhere,” Matthew argued that Node.js’s true power lay in its event-driven, non-blocking I/O model, ecosystem velocity, and developer productivity, advantages that were already reshaping Yammer’s backend services.
This expanded analysis delves into the technical foundations of Node.js, including the V8 engine, libuv, and the event loop, the architectural patterns that emerged at Yammer such as microservices, real-time messaging, and API gateways, and the cultural shifts required to adopt JavaScript on the server. It includes detailed code examples, performance benchmarks, deployment strategies, and lessons learned from production systems handling millions of users.
EDIT
In 2025 landscape, this piece integrates Node.js 20+, Deno, Bun, TypeScript, Server Components, Edge Functions, and WebAssembly, while preserving the original’s pragmatic, hype-free tone. Through rich narratives, system diagrams, and forward-looking speculation, this work serves as both a historical archive and a practical guide for any team evaluating JavaScript as a backend language.
Debunking the Myths of “JavaScript Everywhere”
The phrase JavaScript Everywhere became a marketing slogan that obscured the technology’s true value. Matthew opened his talk by debunking three common myths. First, the idea that developers write the same code on client and server is misleading. In reality, client and server have different concerns, security, latency, state management. Shared logic such as validation or formatting is possible, but full code reuse is rare and often anti-patterned. Second, the notion that Node.js is only for real-time apps is incorrect. While excellent for WebSockets and chat, Node.js excels in I/O-heavy microservices, API gateways, and data transformation pipelines, not just real-time. Third, the belief that Node.js replaces Java, Rails, or Python is false. At Yammer, Node.js was one tool among many. Java powered core services. Ruby on Rails drove the web frontend. Node.js handled high-concurrency, low-latency endpoints. The real win was developer velocity, ecosystem momentum, and operational simplicity.
The Node.js Architecture: Event Loop and Non-Blocking I/O
Node.js is built on a single-threaded, event-driven architecture. Unlike traditional threaded servers like Apache or Tomcat, Node.js uses an event loop to handle thousands of concurrent connections. A simple HTTP server demonstrates this:
const http = require('http');
http.createServer((req, res) => {
setTimeout(() => {
res.end('Hello after 2 seconds');
}, 2000);
}).listen(3000);
While one request waits, the event loop processes others. This is powered by libuv, which abstracts OS-level async I/O such as epoll, kqueue, and IOCP. Google’s V8 engine compiles JavaScript to native machine code using JIT compilation. In 2012, V8 was already outperforming Ruby and Python in raw execution speed. Recently, V8 TurboFan and Ignition have pushed performance into Java and C# territory.
Yammer’s Real-World Node.js Adoption
In 2011, Yammer began experimenting with Node.js for real-time features, activity streams, notifications, and mobile push. By 2012, they had over fifty Node.js microservices in production, a real-time messaging backbone using Socket.IO, an API proxy layer routing traffic to Java and Rails backends, and a mobile backend serving iOS and Android apps. A real-time activity stream example illustrates this:
io.on('connection', (socket) => {
socket.on('join', (room) => {
socket.join(room);
redis.subscribe(`activity:${room}`);
});
});
redis.on('message', (channel, message) => {
const room = channel.split(':')[1];
io.to(room).emit('activity', JSON.parse(message));
});
This architecture scaled to millions of concurrent users with sub-100ms latency.
The npm Ecosystem and Developer Productivity
Node.js’s greatest strength is npm, the largest package registry in the world. In 2012, it had approximately twenty thousand packages. Now, It exceeds two and a half million. At Yammer, developers used Express.js for routing, Socket.IO for WebSockets, Redis for pub/sub, Mocha and Chai for testing, and Grunt, now Webpack or Vite, for builds. Developers could prototype a service in hours, not days.
Deployment, Operations, and Observability
Yammer ran Node.js on Ubuntu LTS with Upstart, now systemd. Services were containerized early using Docker in 2013. Monitoring used StatsD and Graphite, logging via Winston to ELK. A docker-compose example shows this:
version: '3'
services:
api:
image: yammer/activity-stream
ports: ["3000:3000"]
environment:
- REDIS_URL=redis://redis:6379
The 2025 JavaScript Backend Landscape
EDIT:
The 2025 landscape includes Node.js 20 with ESM and Workers, Fastify and Hono instead of Express, native WebSocket API and Server-Sent Events instead of Socket.IO, Vite, esbuild, and SWC instead of Grunt, and async/await and Promises instead of callbacks. New runtimes include Deno, secure by default and TypeScript-native, and Bun, Zig-based with ten times faster startup. Edge platforms include Cloudflare Workers, Vercel Edge Functions, and AWS Lambda@Edge.
Matthew closed with a clear message: ignore the hype. Node.js is not a silver bullet. But for I/O-bound, high-concurrency, real-time, or rapid-prototype services, it is unmatched. In 2025, as full-stack TypeScript, server components, and edge computing dominate, his 2012 insights remain profoundly relevant.
Links
Relevant links include Matthew Eernisse’s blog at fleegix.org, the Yammer Engineering Blog at engineering.yammer.com, the Node.js Official Site at nodejs.org, and the npm Registry at npmjs.com. The original video is available at YouTube: Node.js and JavaScript Everywhere.