Thursday, September 26, 2013

Have you ever wondered why dependency injection in most Java
frameworks is only for local, in-process services as opposed to distributed
services?

I recently came across Paul Maritz’s keynote (skip to minute 32) at the 2013 EMC
World conference, which made me think about this question in the context of
cloud platforms. The keynote is an excellent and well thought-out statement of
how Pivtol is positioning itself in the emerging cloud platform market. One of
his most interesting points is that with the proliferation of mobile and
interconnected devices (often referred to as the Internet of Things), we are
seeing a new class of applications emerge that intake, process, and distribute
large amounts of data.

Maritz highlights his talk with some useful anecdotal
evidence: a single transatlantic flight produces nearly 30TB of data that needs
to be recorded, processed, and analyzed by a new breed of applications.

Cloud Fabrics

These types of applications cannot effectively be built on
traditional Java EE application server architectures. Instead, they will run on
cloud fabrics: dynamic,
interconnected infrastructure that is highly adaptable.

The dynamic nature of cloud fabrics place new requirements
on existing Java frameworks and containers. For example, VM instances may be
created or migrated to meet increased demand. In this setting, machine (and
hence service endpoint) addresses may change. This makes static architectures
often associated with Java EE application server clusters and message brokers
difficult to manage and scale

Cloud fabrics are built on hardware virtualization where
physical compute resources are abstracted via software. Virtualization needs to
be extended up the stack to Java programming models so that applications can be
run more efficiently.

Spring: The Service Virtualization Pioneer

Spring was an early pioneer in this respect. It virtualized
many parts of the Java EE app server by replacing container APIs for obtaining
local service references (JNDI) with dependency injection. This made it possible to run Spring application
code outside a Java EE container, for example, in unit tests.

As cloud fabrics gain adoption, we’ll see a need to extend
Spring’s wiring capabilities to distributed services – wiring–in-the-large. Just
as applications should not need container APIs to obtain references to local
services, they should not need APIs to call remote services or send messages to
endpoints. If remote services are instead wired to application code, the fabric
infrastructure can transparently propagate endpoint address changes as VMs are
migrated or created in response to varying workload:

An additional benefit of wiring-in-the-large is communicationvirtualization. Application code no longer relies on
transport-specific APIs to send messages or invoke remote services. The cloud
fabric is instead responsible for injecting code with proxies that manage
communication:

This will allow the cloud fabric to adopt and adjust the
most appropriate messaging technology without requiring code-level changes. In
addition to greatly simplifying code, communication virtualization also makes
it possible to produce more portable cloud applications.

Wiring-in-the-Large in Practice

So what does wiring-in-the-large look like in practice? The
good thing is that many of its concepts predate the emergence of modern cloud
computing. The OASIS SCA standards give us a simple and familiar way to wire
remote services that fit well with cloud fabrics:

The above services can be connected via JMS, ZeroMQ, AMQP,
MQTT or some other communications technology – it’s either up to the SCA
runtime or deployment configuration to choose one. Application code will look
the same:

What’s Next?

Fabric3 support for wiring-in-the-large currently requires applications be deployed to a Fabric3 container. The Fabric3 community is working on removing this
restriction so that cloud services can be accessed in an ubiquitous manner –
literally from any JVM or Java runtime. Here’s an example:

This API can be integrated into frameworks such as Spring
and Guice to provide transparent injection of remote services. Basically,
application code will no longer need to deal with specific transport APIs, or
in the case of Spring, templates.

****

Returning to Maritz’s picture of next-generation applications that consume, process and distribute data at a
massive scale, wiring-in-the-large will hopefully play the same modernizing
role that local dependency injection did for Java EE in the
corporate datacenter. If you want more detail on the art of the possible,
check out Fabric3.