What Is a Container? (Container Architecture Series Part 1)

What Is a Container? (Container Architecture Series Part 1)

Over 25 years of experience in application and web development with extensive experience on both Java and .NET platforms. Ed works as the Channels Technical Director at Talend working with technology partners, commercial use customers, and SI partners in the Talend ecosystem. Current focus is on enterprise integration strategies spanning DW, Data Lake, and operational decision support systems using the Talend Unified Platform.

This is the first in a series of posts on container-centric integration architecture. This first post covers common approaches to applying containers for application integration in an enterprise context. It begins with a basic definition and discussion of the Container design patterns. Subsequent posts will explore the role of Containers in the context of Enterprise Integration concerns. This will continue with how SOA and Cloud solutions drive the need for enterprise management delivered via service containerization and the need for OSGI modularity. Finally, we will apply these principles to explore two alternative solution architectures using OSGI service containers.

Containers are referenced everywhere in the Java literature but seldom clearly defined. Traditional Java containers include web containers for JSP pages, Servlet containers such as Tomcat, EJB containers, and lightweight containers such as Spring. Fundamentally, containers are just a framework pattern that provides encapsulation and separation of concerns for the components that use them. Typically the container will provide mechanisms to address cross-cutting concerns like security or transaction management. In contrast to a simple library, a container wraps the component and typically will also address aspects of classloading and thread control.

Spring is the archetype container and arguably the most widely used container today. Originally servlet and EJB containers had a programmatic API. Most containers today follow Spring’s example in supporting Dependency Injection patterns. Dependency Injection provides a declarative API for beans to obtain the resources needed to execute a method. Declarative Dependency Injection is usually implemented using XML configuration or annotations and most frameworks will support both. This provides a cleaner separation of concerns so that the bean code can be completely independent of the container API.

Containers are sometimes characterized as lightweight containers. Spring is an example of a lightweight container in the sense that it can run inside of other containers such as a Servlet or EJB container. “Lightweight” in this context refers to the resources required to run the container. Ideally a container can address specific cross-cutting concerns and be composed with other containers that address different concerns.

Of course, lightweight is relative and how lightweight a particular container instance is depends on the modularity of the container design as well as how many modules are actually instantiated. Even a simple Spring container running in bare JVM can be fairly heavyweight if a full set of transaction management and security modules are installed. But in general a modular container like Spring will allow configuration of just those elements which are needed.

Open Source Containers typically complement Modularity with Extensibility. New modules can be added to address other cross-cutting concerns. If this is done in a consistent manner, an elegant framework is provided for addressing the full spectrum of design concerns facing an application developer. Because containers decouple the client bean code from the extensible container modules, the cross-cutting features become pluggable. In this manner, open source containers provide an open architecture foundation for application development.

Patterns are a popular way of approaching design concerns and they provide an interesting perspective on containers. The Gang of Four Design Patterns book categorized patterns as addressing Creation, Structure, or Behavior. Dependency Injection can be viewed as a mechanism for transforming procedural Creation code into Structure. Containers such as Spring also have elements of Aspect Oriented Code which essentially allow Dependency Injection of Behavior. This allows transformation of Behavioral patterns into Structure as well. This simplifies the enterprise ecosystem because configuration of structure is much more easily managed than procedural code.

Talend provides an open source container using Apache Karaf. Karaf implements the OSGI standard that provides additional modularity and dependency management features that are missing in the Java specification. The Talend ESB also provides a virtual service container based on enterprise integration patterns (EIP) via Apache Camel. Together these provide a framework for flexible and open solution architectures that can respond to the technical challenges of Cloud and SOA ecosystems.