Skip to content

16. MVC Web Application in a 3-Tier Architecture – Example 2

16.1. Introduction

We wrote the [people-01] application with the following structure:

The [dao] layer implemented the list of people managed using an [ArrayList] object. This allowed us to avoid overcomplicating the [dao] and [service] layers so we could focus on the [web] layer. We want to evolve the application toward a more realistic environment where the list of people would be stored in a database table. This will require us to change the [dao] layer. This will impact the other two layers. To take advantage of the layer independence provided by Spring IoC, we will take the [people-01] application and configure it with Spring IoC:

The new application will be called [people-02]. Once it has been written, we know that we will be able to change the [DAO] and [service] layers without modifying the code in the [web] layer. That is exactly what we are aiming for.

We create a new Eclipse project [people-02] by copying and pasting the [people-01] project, as explained in section 6.2:

In [1], we see the configuration file appear, in which we will define the beans for the [dao] and [service] layers. Its content is as follows:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- the dao class -->
    <bean id="dao" class="istia.st.mvc.personnes.dao.DaoImpl" init-method="init"/>
    <!-- the service class -->
    <bean id="service" class="istia.st.mvc.personnes.service.ServiceImpl">
        <property name="dao">
            <ref local="dao" />
        </property>
    </bean>
</beans>
  • Line 5: Defines the bean named [dao] as an instance of the [DaoImpl] class. After instantiation, the instance's [init] method is executed.
  • lines 7–10: define the bean named [service] as an instance of the [ServiceImpl] class.
  • lines 8–10: the [dao] property of the [DaoImpl] instance is initialized with the reference to the [dao] layer created on line 5. Recall that the [ServiceImpl] class does indeed have the [dao] property and the corresponding setter:
public class ServiceImpl implements IService {

    // the [dao] layer
    private IDao dao;

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }
...

Of course, this file alone does nothing. The [Application] controller will use it in its [init] method to instantiate the [service] layer. Let’s recall the previous version of the controller’s [init] method:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
...
    // service
    ServiceImpl service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
        // instantiation of the [DAO] layer
        DaoImpl dao = new DaoImpl();
        dao.init();
        // instantiate the [service] layer
        service = new ServiceImpl();
        service.setDao(dao);
    }

In line 5, we had to explicitly name the implementation class of the [service] layer, and in line 12, that of the [dao] layer. With Spring IoC, the [init] method becomes the following:

@SuppressWarnings("serial")
public class Application extends HttpServlet {
    // instance parameters
    ...

    // service
    private IService service = null;

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
    ...
        // instantiation of the [service] layer
        service = (IService) new XmlBeanFactory(new ClassPathResource("spring-config.xml")).getBean("service");
    }
  • line 7: the private field [service] is no longer of type [ServiceImpl] but of type [IService], i.e., of the type of the [service] layer interface. The [web] layer is therefore no longer tied to a specific implementation of this interface.
  • line 14: initialization of the [service] field from the configuration file [spring-config.xml].

These are the only changes to be made. Let’s integrate this new application into Tomcat, start it, and then request the URL [http://localhost:8080/personnes-02]:

Image

16.2. Archiving the web application

We have developed an Eclipse/Tomcat project for a 3-tier application:

In a future version, the group of people will be stored in a database table.

  • This will require a rewrite of the [DAO] layer. This is easy to understand.
  • The [service] layer will also be modified. Currently, its sole role is to ensure synchronized access to the data managed by the [dao] layer. To this end, we have synchronized all methods in the [service] layer. We have explained why this synchronization was placed in this layer rather than in the [DAO] layer. In the new version, the [service] layer will still have the sole role of synchronizing access, but this will be handled by database transactions rather than by synchronizing Java methods.
  • The [web] layer will remain unchanged.

To facilitate the transition from one version to the next, we are creating a new Eclipse project [mvc-personnes-02B], a copy of the previous project [mvc-personnes-02] but where the [web, service, dao, entities] layers have been placed in .jar archives:

The [src] folder now contains only the Spring configuration file [spring-config.xml]. It previously also contained the source code for the Java classes. These elements have been removed and replaced by their compiled versions placed in the [personnes-*.jar] archives shown in [1]:

The [mvc-personnes-02B] project has been configured to include the [personnes-*.jar] archives in its ClassPath.

We deploy the web project [mvc-personnes-02B] within Tomcat:

To test the project, we start Tomcat and then request the URL [http://localhost:8080/personnes02B]:

Image

The reader is invited to perform additional tests.

In the database version, we will change the [service] and [dao] layers. We want to show that it will then suffice to replace the [personnes-dao.jar] and [personnes-service.jar] archives in the previous project with the new archives so that our application now works with a database. We will not need to touch the archives of the [web] layer and the [entities] layer.