JEAF Architecture Model

The diagram above shows the generic meta model that describes the building blocks of enterprise applications. The core parts of it are components, services, use cases and activities. As we will see service- and component-oriented approaches do not contradict but will even complement one another.

In the context of JEAF the following building blocks are defined:

Component

Components are self-contained, reusable pieces of software. In combination with services, use cases and activities they form the central parts of JEAF’s Architecture Model.

Usually even enterprise applications only consist of a rather small amount of components. Components may also consist of sub-components. Sub-components are used to improve the internal structure of a component and are thus not accessible from outside of the surrounding component.

A component has a static and a dynamic aspect. Its static aspect is represented by so called business objects. They form the internal data structure of the component and as we live in an object-oriented world business objects also offer operations to do things with them

Services on the other hand define the dynamic aspects of a component from an outside view. They structure all the things that are offered by a component into logical units. Internally a component might uses activities to provide its services.

When building up components (not sub-components) then it’s very important that they have a granularity that is so big that they are also candidates to become an own deployment unit. This in consequence means that every component will / should have its independent life cycle, which of course may differ from the one of the overall application.

Service

A components offers its functionality bundled in logical blocks as so called services. Services are always stateless and do not define the overall transaction context. However, every component still has to define its transnational behavior for its services.

Services can make use of other services in order to provide their functionality.

Service Object

Service objects are used as a representation of the domain model of a component to the outside world. Often they are a simplified view of the internal structures. Together with all the service operations service objects define the public interface of a component. Service objects do not contain business logic as they are mostly treated as a data container. Nevertheless they may provide convenience methods to simplify the usage of an service interface (in case that the interface is exposed as Java classes).

Subsystem

A subsystem consists of one or more components and forms its own deployment unit. A subsystem itself is just a bracket about a set of components that are deployed together. Thus it does not have its own source code except for build scripts that are used to build, test and deploy the subsystem.

Business Object

Business objects are used to build up the domain model of a component. There are several kinds of business objects like persistent objects, domain object etc. The concrete variant highly depends on the concrete component. But what they all have in common is that represent the internal structure of a component.

According to the concepts of information hiding and decoupling this also means that business objects are always private and must not be referenced / used from outside of the component. This also means that references between business objects from different components are “illegal”. In order to have a proper decoupling between the internal structures of a component and its interface it’s also not allowed to use business objects in services interfaces. Instead so called service objects should be used. They are intended to be used to define the public view on data / business objects of a component.

Business objects not only represent data but they also contain all the business logic than can be clearly assigned to the business object itself.

 

As mentioned before there are different flavors of business objects:

  • Persistent Objects
    Persistent Objects are used to describe the domain model of a component in case that data is stored in a relation database. Persistent Objects this case provide an object-oriented view on the relational data.

    In addition to the general remarks concerning decoupling it is very important that in case of persistent data decoupling is also ensured on database level.

  • Domain Objects
    Domain objects are also used to describe the domain model of a component. However in this case the data is not stored in a database but may be accessed using some other external system like an external REST-Service or a legacy host application.

Use Case

Any interaction with a system is a use case no matter if the actor is human or just another system. Use cases represent the dynamic part of an application and might even have a state (at least from a business perspective).

A use case itself consists of 1 or more activities. The starting point for a use case is provided as a service operation. The executed activities and their order depend on the micro workflow that is implemented by the service that is used to implement an use case.

Activity

Components use activities to implement non-trivial functionality of the services they offer. Activities are used to structure the internal dynamic aspects of a component and help to achieve a better testability. Activities can also call other services as part of the internal logic. Like services, activities are stateless and so are only allowed to operate on input parameters and data loaded by the activity itself (e.g. from database or external services).

An activity always belongs to exactly one component and it can only operate on business objects of this component.

Service Provider

In addition to services and components JEAF also offers an additional mechanism to support technical services, so called Service Providers. Service Providers are also stateless like services but they are used to encapsulate technical services as a reusable unit.

Service providers have, in opposite to business services, the following restrictions:

  • Service providers do not have their own transaction context. Instead they inherit it from the current component that calls the service provider.

  • Service providers do not support to be called from remote sources directly. Instead calls to service providers are always within the same virtual machine. Consequence out of this is also that objects passed to or returned from a service provider do not need to be serializable.

  • When calling methods of a service provider there will not be any authorization checks.

 

All the restrictions from above lead to the fact that service providers are very lightweight compared to real services, but the usage is also more restricted. A good example for a service provider is JEAF’s support for persistence. This is implemented a service provider (JEAF Persistence).

Interceptor

Interceptors are special objects that will be called before and after a call to a service. Based on interceptors it’s for example possible to ensure that service methods are only called if the current user has a matching authorization.