Search

Stack Architecture

One of the key CAP design principles is to be an opinionated but yet open framework. Giving a clear guidance for cutting-edge technologies on the one hand and still keep the door wide open for custom choice on the other hand, demands a highly flexible CAP Java SDK. The modular architecture reflects this requirement, allowing fine-grained stack configuration and custom extensions.

Content

Modular Architecture

Architecture Overview

The architecture of CAP Java applications is driven by the fully modularized stack of the CAP Java SDK. This introduces some nice benefits applications gain out of the box.

The basic design principle is to keep the implementation of orthogonal functionality separated in independent components. The obvious advantage of the decoupling is that it makes concrete components exchangeable independently. Hence, it reduces the risk of expensive adaptions in custom code, which can be necessary due to new requirements with regards to the platform environment or used version of platform services. Hence, the application is platform and service agnostic.

For instance, custom code doesn’t need to be written against the chosen type of persistence service, but can use the generic persistence service based on CDS QL. Likewise, the application isn’t aware of the concrete (cloud) platform environment in which it gets embedded. Consequently, preparing an application to be deployable in different platform contexts is rather a matter of configuration than of code adaption.

Consequently, CAP Java SDK doesn’t determine the technology the application is build on. But it comes with a chosen set of industry-proven frameworks that can be consumed easily. Nevertheless, you can override the defaults separately depending on the demands in your scenario.

Moreover, the fine-grained modularization allows you to assemble a minimum set of components, which is necessary to fulfill the application-specific requirements. This reduces resource consumption at runtime as well as maintenance costs significantly.

Another helpful result of the described architecture is that it simplifies local testing massively. Firstly, as components are coupled weakly, you can define the actual test scope precisely and concentrate on the parts that need a high test coverage. Components outside of the test scope are replaceable with mocks, which ideally simulate all the possible corner cases. Alternatively, you can even configure test on integration level to be executed locally if you replace all dependencies to remote services by local service providers. A common example for this is to run the application locally on SQLite instead of SAP HANA.

The following diagram illustrates the modular stack architecture and highlights the generic components:

You can recognize five different areas of the stack, which comprise components according to different tasks:

Application Framework

Before starting the development of a new CAP-based application, an appropriate application framework to build on needs to be chosen. The architecture of the chosen framework not only has a strong impact on the structure of your project, but it also affects efforts for maintenance as well as support capabilities. The framework provides the basis of your web application in terms of a runtime container in which your business code can be embedded and executed. This helps to separate your business logic from common tasks like processing HTTP/REST endpoints including basic web request handling. Typically, a framework also provides you with a rich set of generic tools for recurring tasks like configuration, localization, or logging. In addition, some frameworks come with higher-level concepts like dependency injection or sophisticated testing infrastructure.

CAP Java SDK positions Spring or more precisely Spring Boot as the first choice application framework, which is seamlessly integrated. Spring comes as a rich set of industry-proven frameworks, libraries, and tools that greatly simplify custom development. Spring Boot also allows the creation of self-contained applications that are easy to configure and run.

As all other components in the different layers of the CAP Java SDK are decoupled from the concrete application framework, thus you are not obligated to build on Spring. In some scenarios, it might be even preferable to run the (web) service with minimal resource consumption or with smallest possible usage of Open Source dependencies. In this case, a solution based on plain Java Servlets could be favorable. Lastly, in case you want to run your application on a 3rd party application framework, you’re free to bundle it with CAP modules and provide the glue code, which is be necessary for integration.

Protocol Adapters

The CAP runtime is based on an event driven approach. Generally, Service providers are the consumers of events, that mean, they do the actual processing of events in handlers. During execution, services can send events to other service providers and consume the results. The native query language in the CAP is CQN, which is accepted by all services that deal with data query and manipulation. Inbound requests therefore need to be mapped to corresponding CQN events, which are sent to an accepting CDS service (see concept details) afterwards. Mapping the ingress protocol to CQN essentially summarizes the task of protocol adapters depicted in the diagram. Most prominent example is the OData V4 protocol adapter, which is fully supported by the CAP Java SDK. Further HTTP-based protocols can be added in future, but often applications require specific protocols, most notably RESTful ones. The modular architecture allows to add custom protocol adapters in a convenient manner, which can be plugged into the stack at runtime. Note that different endpoints can be serves by different protocol adapters at the same time.

Service Providers

Services have different purposes. For instance, CDS model services provide an interface to work with persisted data of your domain model. Other services are rather technical, for example, hiding the consumption API of external services behind a generic interface. As described in CAPs core concepts, services share the same generic provider interface and are implemented by event handlers. The service provider layer contains all generic services, which are auto-exposed by the CAP Java runtime according to the appropriate CDS model. In addition, technical services are offered such as the Persistence Service or Authorization Service, which can be consumed in custom service handlers.

If the generic handler implementation of a specific service doesn’t match the requirements, you can extend or replace it with custom handler logic that fits your business needs. Find details in implementing event handlers.

CQN Execution Engine

The CQN execution engine is responsible for processing the passed CQN events and translating them to native statements that get executed in a target persistence service like SAP HANA or SQLite. CQN statements can be build conveniently in a fluent API. In future, additional targets can be added to the list of supported outbound sources.

Application Features

The overall architecture of the CAP Java SDK allows additional components to be plugged in at runtime. This plug-in mechanism makes the architecture open for future extensions and allows context-based configuration. It also enables you to override standard behavior with custom-defined logic in all different layers. Customer components or extension modules that should be loaded by the runtime need to satisfy so-called feature interfaces, which represent the abstraction of some functionality needed by the server at runtime. An example for this is calling the authentication procedure for which two feature implementations are provided by default: local authentication with mock users and production-grade XSUAA authentication. Other authentication strategies could be added and configured by customers. Similarly, there’s an environment feature for the CloudFoundry platform, which needs to be chosen if you want to run your application on SAP Cloud Platform Cloud Foundry. Nevertheless, the same application should also be runnable in a different environment provided an appropriate feature is provided.

Moreover, optional service extensions such as enterprise messaging are also modeled as features. Audit logging will be provided based on the same technique soon.

Stack Configuration

As outlined in Modular Architecture, the CAP Java SDK is highly flexible. You can’t only choose among modules prepared for different environments. You can also include optional or custom extensions. Which set of modules is active at runtime is a matter of compile time and runtime configuration.

At compile time, you can assemble modules from the different layers:

Module Configuration

All CAP Java SDK modules are built as Maven artifacts and are available on Apache Maven Central Repository. They have group id com.sap.cds. Beside the Java libraries (Jars) reflecting the modularized functionality, the group also contains a “bill of materials” (BOM) pom named cds-services-bom, which is recommended especially for multiproject builds. It basically helps to control the dependency versions of the artifacts and should be declared in dependency management of the parent pom:

<properties>
	<cds.sdk.version>1.1.0</cds.sdk.version>
</properties>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>com.sap.cds</groupId>
			<artifactId>cds-services-bom</artifactId>
			<version>${cds.sdk.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

The actual Maven dependencies specified in your pom need to cover all libraries that are necessary to run the web application: An application framework, a protocol adapter, and the CAP Java runtime. The dependencies of a Spring Boot application with OData V4 endpoints could look like in the following example:

<dependencies>
	<!-- Application framework -->
	<dependency>
		<groupId>com.sap.cds</groupId>
		<artifactId>cds-framework-spring-boot</artifactId>
		<scope>runtime</scope>
	</dependency>

	<!-- Protocol adapter -->
	<dependency>
		<groupId>com.sap.cds</groupId>
		<artifactId>cds-adapter-odata-v4</artifactId>
		<scope>runtime</scope>
	</dependency>

	<!-- CAP Java runtime -->
	<dependency>
		<groupId>com.sap.cds</groupId>
		<artifactId>cds-services-api</artifactId>
	</dependency>
	<dependency>
		<groupId>com.sap.cds</groupId>
		<artifactId>cds-services-impl</artifactId>
		<scope>runtime</scope>
	</dependency>
</dependencies>

You are not obliged to choose one of the prepared application frameworks, which have artifact id prefix cds-framework. It’s also possible to make use of the CAP Java runtime in a different context. The same holds for the protocol adapters. You’re free to add additional adapters or to bring your own adapter.

Unlike all the other dependencies, cds-services-api is defined not as a runtime dependency as you might need to build your custom handler or adapter code on basis of this API.

Additional application features you want to make use of are added as additional dependencies. For instance:

<dependencies>
	<!-- Features -->
	<dependency>
		<groupId>com.sap.cds</groupId>
		<artifactId>cds-feature-cloudfoundry</artifactId>
		<scope>runtime</scope>
	</dependency>
</dependencies>

Makes your application ready for running in SAP Cloud Platform Cloud Foundry environment.

Choosing a feature by adding the Maven dependency at compile-time essentially enables the application to make use of the feature at runtime. If a chosen feature misses the required environment at runtime, the feature won’t be activated. Together with the fact that all features have a built-in default implementation ready for local usage, you can run the application locally with the same set of dependencies as for productive mode. For instance, the authentication feature cds-feature-hana requires a valid hana-binding in the environment. Hence, during local development without this binding, this feature gets deactivated and the stack falls back to default feature adapted for SQLite.

Available Modules

Following application frameworks are available:

Protocol adapters:

Runtime (mandatory):

Application features:

Starter Bundles

To simplify the configuration on basis of Maven dependencies, the CAP Java SDK comes with starter bundles that help to set up your configuration for most common use cases quickly:

Both starter bundles can be combined.