Software As A Service Architecture Guidance

I've recently been thinking a lot and discussing with my colleagues at HubSpot the implications of Saas (Software as a Service). We're looking at this from many angles: operational cost, development cost, support cost, etc. One of the big advantages for SaaS startups is the opportunity to be economically efficient along many dimensions through multi-tenancy. But, just because the opportunity is there doesn't necessarily mean that every startup is exploiting it equally. In my online readings and research, I came across an article about the SaaS Simple Maturity Model. Though I'm not particularly fond of the name, the framework is very useful. Here's my (even simpler) interpretation of the levels of maturity of a SaaSEvery time you add a new customer, you add a new instance of the software. If the customer needs something specific, you change that software instance. Each customer is essentially running on their own "version" of the software.

Level 1 (Managed Chaos): Every customer runs on the same version of the software and any customizations are done viaBut, you still have different instances for each customer (their own website, their own virtual server, their own physical server, etc.). Level 2 (Multi-Tenant, Highrise): You've got all customers running on a single version of the software, and they're all running essentiallyThe good news is that you're getting the benefits of multi-tenant (sharing resources across customers). Even better is that you're not writing custom code for each customer -- everyone essentially runs on theThe big challenge is that as you add more floors to your building (to stretch the analogy a bit), it gets more and more expensive. limits to how high you can build to accomodate a large number of tenants. Level 3 (Multi-Tenant, Build-Out): This is when you've got multi-tenant, single version of the software model. But, you can scale-out (add

This is optimal because instead of letting the architecture decide how many tenants you put into a building, you can let the economics
Fox Red Labs For Sale In KansasAnd yes, there is an optimal number of tenants per instance
Bubble Patio Furniture and this number varies on your situation.
Auto Repair Shop For Rent In Massachusetts Level 4 (Utopia): This is like Level 3, except you've figured out an efficient way to run different versions of the software onYou're doing this not because you're writing custom code for a customer, but because you want to run different code for different customers -- to try things out. The best example is having an "early adopter" instance where customers that want to use your latest and greatest features can

As long as you're efficient[Note: This last one is my own fabrication and wasn't part of the original framework referenced above). HubSpot, my startup, is currently at a Level 2 and shooting for Level 4 this year (with a brief stop at Level 3 as an intermediate point). The good news is that we're adding cusomers quickly so this is more than an academic exercise for us. We can actually rationalize the investment in terms of economics because the benefits that we get from improvement actually makes us money. Are you a superstar startup developer in Boston? Help us figure out how to delight thousands of customers and makeShare in the fun and success. You can email me at dshah [@] . If you have what it takes, we've got some awfully smart and passionate people you'd enjoy working with.This document provides an architectural overview of the Apache CXF services framework. Apache CXF Software Architecture Guide Table of ContentsArchitectural Goals and ConstraintsCXF-API

BusHow service calls are processedFront-endsMessaging & InterceptorsThe Service ModelData BindingsProtocol BindingsTransportsA JAX-WS example The Apache CXF services framework seeks to build the necessary infrastructure components for services. Goals for CXF are many and include: The overall CXF architecture is primarily made up of the following parts: In the upcoming sections, we'll take a look at each layer in turn and examine how they work together. The bus, being CXF's backbone, is a provider of shared resources to the CXF runtime. Examples for such shared resources include WSDL managers and binding factory managers. The bus can easily be extended to include your own custom resources or services, or you can replace default resources like the HTTP destination factory (based on Jetty) with your own (possibly based on another web container such as Apache Tomcat). This extensibility is made possible by dependency injection; the default bus implemenation is based on Spring Framework, which wires the runtime components together for you.

The SpringBusFactory searches for all bean configuration files in the META-INF/cxf directories on your classpath, and builds an application context from them. The bean configuration files included in the application context construction are: See Configuration of the Bus for an example of how to customize the bus by supplying your own bean configuration file and Configuration of Runtime Constructed Objects for more information on the special case of injecting into objects created by the runtime (as opposed to objects created by the IoC container itself). Front-ends provide a programming model to interact with CXF. JAX-WS, JAX-RS, Simple and Javascript front-end APIs are provided by CXF . Each implementation is cleanly separated from the rest of CXF, just like the bindings and the core. Front-ends provide functionality through interceptors that are added to Services and Endpoints. CXF is built on a generic messaging layer comprised of Messages, Interceptors, and InterceptorChains.

Interceptors are the fundamental unit of functionality. By dividing up how messages are processed and sent, this gives CXF a very flexible architecture. It can be reconfigured at any point in the processing. This also gives CXF the ability to pause & resume interceptor chains. Interceptors have a method, handleMessage, which allows them to act on the Message.These Interceptors can then be built up into chains of interceptors, straightforwardly called InterceptorChains. Interceptors are uni-directional and are inherently unaware of whether they are dealing with a request, response, or fault. CXF provides an InterceptorChain implementation called the PhaseInterceptorChain. When Interceptors are added to the chain, they are grouped into ordered phases. A PhaseInterceptor may provide guidance as to how it is to be ordered within the phase. Let us take a hypothetical simplified example (NOTE: these phases and interceptors don't necessarily exist in CXF). Let us say we are parsing a SOAP message.

We may want to have two phases. First, a dispatch phase which parses the soap headers and determines which service to route the Message to. Second, an unmarshal phase which binds the SOAP body to JAXB objects. In the first dispatch phase we could implement this via two interceptors, first a ReadHeadersInterceptor which parses the headers and second a WS-AddressingInInterceptor which determines which service we're invoking from the WS-Addressing header. In the second unmarshal phase, we have just a single JAXBUnmarshallerIntercptor. Both the ReadHeadersInterceptor and AddressingInInterceptor would tell the PhaseInterceptorChain they are in the "dispatch" phase by returning "dispatch" when getPhase() is called. Additionally, the ReadHeadersInterceptor could specify that it wants to run before the AddressingInInterceptor by returning the interceptor id when Interceptor.getBefore() is called. Before it was mentioned how chains were very dynamic and flexible. In our above example, we could add interceptors specific to that service once it is resolved.

Or we could pause the chain once while we wait for some external chain, like an asynchronous service response. At any point during processing, an interceptor may throw a Fault, or a derivative of a Fault like the SoapFault. This will cause the chain to stop invoking and unwind it. Unwinding consists of calling handleFault on each interceptor that was invoked in reverse order. InterceptorChains have the concept of a fault observer. Once the chain is unwound, the fault interceptor is invoked with the message that caused the fault. The fault observer may trigger a new chain which then invokes a specified set of interceptors meant to handle faults. In addition to the concept of a Message, there is the concept of the Exchange. The exchange class holds a references to the in, out and fault messages for the current message exchange. It also holds properties specific to the exchange, and not just the message. For instance the Exchange holds the Service that is current being invoked in it.

An interesting feature of the PhaseInterceptorChain is that it is reentrant. This can be powerful and slightly dangerous. This feature is only used in CXF during the sending of an outgoing message, The SoapOutInterceptor is the best example: The Service model is the representation of a service within CXF. It is made up of two parts. First there is the ServiceInfo which contains a WSDL-like model of the service and its operations, bindings, endpoints and schema. Second, there is the Service itself, which contains the ServiceInfo, data-binding information, service interceptors, service properties and more. A service can be constructed from many different sources including classes and WSDLs (1.1 or 2.0). Typically front-ends are responsible for creating a service via service factories. Factory components such as ServerFactoryBean and ClientProxyFactoryBean can used with the front-end to create, publish and consume web services. The factory classes build up the service model and configure the service interceptors, data bindings and more.

The Service model itself is contained in the ServiceInfo class. The following image depicts a subset of the Service Model's packaged API: Data bindings implement the mapping between XML elements and Java objects. Data bindings convert data to and from XML, produce XML schema, and provide support for wsdl2java code generation. Not all data bindings support all of this functionality. At very least, a data binding must provide the data conversion. See Data Binding Architecture for details. Currently supported data bindings include JAXB 2.x (default), Aegis, Apache XMLBeans, Service Data Objects (SDO) and JiBX (under development). Bindings provide ways to map concrete formats and protocols on top of transports. A binding contains two main parts, a BindingFactory and a Binding. A BindingFactory builds a Binding from the service model's BindingInfo. The binding contains interceptors specific to the binding and also implements the createMessage() method, which creates a Message implementation specific for that binding.

CXF currently supported the following bindings protocols: SOAP 1.1, SOAP 1.2, REST/HTTP, pure XML and CORBA. The prototypical binding is SOAP. It has its own Message class called the SoapMessage. It adds the ability to hold the current SoapVersion and the headers for the message. The Soap binding also adds a special type of interceptor called the SoapInterceptor. The SoapInterceptor adds two methods to the Interceptor class: These inform the SOAP interceptors as to what headers and roles the particular SOAP interceptor understands. It has many interceptors designed to handle SOAP messages: Other bindings include REST/HTTP binding, pure XML binding, and the CORBA binding. CXF includes its own transport abstraction layer to hide transport specific details from the binding and front end layers. Currently supported transports include: HTTP, HTTPs, HTTP-Jetty, HTTP-OSGI, Servlet, local, JMS, In-VM and many others via the Camel transport for CXF such as SMTP/POP3, TCP and Jabber.