ATTENTION: You are on the develop
branch.
This has been renamed to master
.
The develop
branch will not be maintained anymore.
It is only left here to avoid broken links to existing content.
Please update links to point to the master
branch.
For details look at issue #320.
The service layer is responsible for exposing functionality made available by the logical layer to external consumers over a network via technical protocols.
We distinguish between the following types of services:
-
External Services
are used for communication between different companies, vendors, or partners. -
Internal Services
are used for communication between different applications in the same application landscape of the same vendor.-
Back-end Services
are internal services between Java back-end components typically with different release and deployment cycles (if not Java consider this as an external service). -
JS-Client Services
are internal services provided by the Java back-end for JavaScript clients (GUI). -
Java-Client Services
are internal services provided by the Java back-end for a native Java client (JavaFx, EclipseRcp, etc.).
-
The choices for technology and protocols will depend on the type of service. The following table gives a guideline for aspects according to the service types.
Aspect | External Service | Back-end Service | JS-Client Service | Java-Client Service |
---|---|---|---|---|
required |
required |
not required |
not required |
|
mandatory |
not required |
implicit |
not required |
|
REST+JSON |
For services consumed by other applications we use versioning to prevent incompatibilities between applications when deploying updates. This is done by the following conventions:
-
We define a version number and prefix it with
v
(e.g.v1
). -
If we support previous versions we use that version numbers as part of the Java package defining the service API (e.g.
com.foo.application.component.service.api.v1
) -
We use the version number as part of the service name in the remote URL (e.g.
https://application.foo.com/services/rest/component/v1/resource
) -
Whenever breaking changes are made to the API, create a separate version of the service and increment the version (e.g.
v1
→v2
) . The implementations of the different versions of the service contain compatibility code and delegate to the same unversioned use-case of the logic layer whenever possible. -
For maintenance and simplicity, avoid keeping more than one previous version.
For services that are consumed by clients with different technology, interoperability is required. This is addressed by selecting the right protocol, following protocol-specific best practices and following our considerations especially simplicity.
The term service is quite generic and therefore easily misunderstood. It is a unit exposing coherent functionality via a well-defined interface over a network. For the design of a service, we consider the following aspects:
-
self-contained
The entire API of the service shall be self-contained and have no dependencies on other parts of the application (other services, implementations, etc.). -
idempotence
E.g. creation of the same master-data entity has no effect (no error) -
loosely coupled
Service consumers have minimum knowledge and dependencies on the service provider. -
normalized
Complete, no redundancy, minimal -
coarse-grained
Service provides rather large operations (save entire entity or set of entities rather than individual attributes) -
atomic
Process individual entities (for processing large sets of data, use a batch instead of a service) -
simplicity
Avoid polymorphism, RPC methods with unique name per signature and no overloading, avoid attachments (consider separate download service), etc.
Your services are the major entry point to your application. Hence, security considerations are important here.
See REST Security.