Monday, 3 September 2012

Spring MVC-Service-DAO-Persistence Architecture Example

It is considered good practice to use modularity across Spring web applications. It keeps them maintainable and testable. This can be achieved by using controllers, services and data access objects (DAO). Typically, a user request is handled by a controller, which calls a service, which calls a data access object, which calls the persistence layer implementation.

Using services means that application functionalities can be tested without a test framework simulating user calls to controllers. Separating services from the persistence layer implementation via DAO, allows using an in-memory database (for example) by substituting production DAO implementations, by test DAO implementation pointing to an in-memory database.

The code example used in this post is available from Github in the Spring-MVC-Service-DAO-Persistence-Architecture directory. It is a variation of the Spring Web JPA Hibernate In-Memory example.

MVC Controller Calls The Service Implementation

The following controller is injected with an implementation of MyService. It handles /roundtrip user calls by calling its create() and Retrieve(id) methods, which creates and retrieves an instance of a MilliTimeItem object. It contains a unique ID and a timestamp in milliseconds.
@Controller
public class MyController {

    @Autowired
    private MyService myService;

    @RequestMapping(value = "/")
    public String home(Model model) {
        return "index";
    }

    @RequestMapping(value = "/roundtrip")
    public String persistenceStatus(Model model) {

        long id = myService.create();
        MilliTimeItem retr = myService.retrieve(id);
 
        model.addAttribute("RoundTrip", retr);
 
        return "roundtrip";

    }

}

Service Implementation calls Data Access Objects (DAO)

The DAO is injected in the MyService implementation. The createAndRetrieve() calls the DAO createMilliTimeItem() and getMilliTimeItem() methods. It returns the created and retrieved item.
public class MyServiceImpl implements MyService {

    @Autowired
    private MyPersistenceDAO myDAO;

    @Transactional
    long create();
 
    @Transactional
    MilliTimeItem retrieve(long id);

}

Data Access Object Implementation Calls The Persistence Layer

The DAO implementation is injected with the JPA EntityManager:
@Repository
public class MyPersistenceDAOImpl implements MyPersistenceDAO {

    @PersistenceContext
    private EntityManager em;

    @Override
    public long createMilliTimeItem() {
 
        MilliTimeItem mti = new MilliTimeItem();
        mti.setMilliTime(System.currentTimeMillis());

        em.persist(mti);
        long result = mti.getID();
        em.detach(mti);
 
        return result;
 
    }

    @Override
    public MilliTimeItem getMilliTimeItem(long id) {
        return em.find(MilliTimeItem.class, id);
    }

}

Running the Example

After compiling this example with Maven, it can be run with mvn tomcat:run. Then, browse http://localhost:8585/spring-mvc-service-dao-persistence-architecture/.

The generated output is:
Created MilliTimeItem's ID: 1
Created MilliTimeItem's value: 1346691836108

More Spring related posts here.

4 comments:

  1. I think making your DAO's transactional (using @Transactional annotation on DAO) is bad practise. Your services should be transactional and not DAO's. Your DAO's should not have knowledge of transactionality. For unit testing DAO's individually, one can use a framework like Spring testing framework to automatically start a transaction before DAO call. This is usually done by marking the test class as Transactional

    ReplyDelete
  2. Shouldn't there be @Service annotation before the
    public class MyServiceImpl implements MyService ?

    ReplyDelete