5.4. Service Layer

On top of the domain and persistence layer sits the service layer of the application. Its role is to coordinate the domain objects and repositories in order to perform higher level operations. This is also the layer which provides transaction demarcation. One consideration for which transaction demarcation should be done at service level is to ensure that the changes made by service operations are atomic. Otherwise, concurrent operations may leave the application data in an inconsistent state. Demarcating transactions at the repository/DAO level should be done carefully, taking into consideration that multiple repository/DAO invocations that are not surrounded by a wrapping transactions will execute in separate transactional contexts.
In the Sportsclub application, there are two variants of implementing the service layer:
  • using Spring (Reservations, parts of Invoicing)
  • using EJB (Subscriptions, Invoicing)

Note

It is possible to define transactions at the repository level, avoiding another indirection to the persistence layer for simple persistence operations (finding an object, persisting an object).

5.4.1. The Spring-based service layer

The Spring-based service layer exposes a number of service beans that can be consumed by the UI, which are injected with the beans defined in the persistence layer. This is the level where transaction demarcation is provided by the use of the appropriate Spring annotations.

5.4.2. The EJB service layer

A common scenario in Spring/EJB integration is the wrapping of Spring Beans in EJBs. This is often done in order to get advantage of the services provided by the EJB container (security, declarative transaction management), while keeping some of the objects they collaborate with as simple POJOs. In this scenario, the EJBs form the outermost layer of the business logic, the one that is exposed to the rest of the application (UI). In this scenario, the EJB services are injected with the Spring-based repositories.
JBoss has its own native support for Spring/EJB integration, in the form of the Spring Deployer and special annotations for injection of Spring beans into EJBs.

5.4.2.1. The Spring Deployer

The Spring Deployer is a JBoss-specific deployer that can be used to bootstrap a Spring ApplicationContext and register it into JNDI. The configuration files for bootstrapping the application context are defined at the EAR level, and the Spring ApplicationContext is shared to all the components. The definition file is simple, and just imports the contexts defined in the JPA jars.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <description>BeanFactory=(SpringDao)</description>

    <import resource="classpath*:dao-context.xml"/>
    <import resource="classpath*:infrastructure.xml"/>


</beans>

5.4.2.2. Injection into EJBs

Once the ApplicationContext is created, the beans defined there can be injected into EJBs. So, in this case, the Spring repositories will be injected into EJBs as follows:
@Stateless
@Interceptors(SpringLifecycleInterceptor.class)
public class BillingServiceImpl implements BillingService
{
   @Spring(bean = "invoiceRepository", jndiName = "SpringDao")
   private InvoiceRepository invoiceRepository;

   /* rest of the class definition ommitted */
}
The injection task is undertaken by the SpringLifecycleInterceptor. Once it encounters a field or setter annotated with @Spring, it will look for the JNDI-bound application context and inject the corresponding Spring bean.