Over a million developers have joined DZone.

Wiring-in-the-Large: The Missing Technology for Java Cloud Applications

DZone's Guide to

Wiring-in-the-Large: The Missing Technology for Java Cloud Applications

· Cloud Zone ·
Free Resource

Learn how to migrate and modernize stateless applications and run them in a Kubernetes cluster.

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 30 TB 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 computer 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 communication virtualization. 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:

<composite name="LoanComposite" ...>
  <component name="Client">
    <implementation.java class="org.fabric3.sample.client.ClientImpl"/>
    <reference name="service" target="Service"/> 
  <component name="Service">
    <implementation.java class="org.fabric3.sample.service.ServiceImpl"/>

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

public class ClientImpl implements Client {
  protected Service service;
  public void doSomething() {
    Message message = ...

The Fabric3 run-time (a conformant SCA implementation) provides transparent dynamic endpoint propagation in the way we discussed above.

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:

Fabric fabric = Bootstrap.initialize();
Domain domain = fabric.getDomain();
Service service = domain.getService(Service.class);
Message message = ... 

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

Join us in exploring application and infrastructure changes required for running scalable, observable, and portable apps on Kubernetes.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}