Continuing with our Servlet to Spring series, we will explore how to incorporate Spring framework in our application, if you have not been following please read the earlier parts of the series. For this, it would be better if you have read the dependency injection discussion.

Spring has been the most revolutionary architecture in java in recent times, completely changing the way we develop java web application. Before Spring came along the standard way of developing java web application was to follow Sun Microsystem blue print application using EJB and Servlets. With IOC containers the Spring containers could offer transaction capabilities without heavy weight EJB container provided by Application Servers like JBoss, Websphere e.t.c.

Spring Context

Spring context library provides dependency injection capabilities. If you look at the current Spring documentation it gets too much of magic just by including Spring in classpath without writing single line of code. Since this blog is all about learning it the hard way, we would build our spring application using XML and without magic, that way you can understand how dependency injection works and then we would add the syntactical sugar on it.

We would be using the codebase from last post, so if you have not been following the series, please checkout last post on jdbc or you can directly checkout the source from github at shopping-cart-jdbc

Lets add the core maven dependency by adding following dependency in dependency section of pom.xml.

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>5.2.2.RELEASE</version>
</dependency>

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>5.2.2.RELEASE</version>
</dependency>

      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.2.RELEASE</version>
      </dependency>

We will also be creating a few more classes and interfaces, as we had explored in our last post dependency injection, it is a good idea to break the dependency classes into interface and implementation pairs. So we would create an interface WineDao and move the implementation into WineDaoImpl class.

public interface WineDao {
    public List<WineDetail> getListOfWines();
}

public class WineDaoImpl implements WineDao {

public List<WineDetail> getListOfWines() {
   ArrayList<WineDetail> listOfWine = new ArrayList<>();
   try {
      DriverManager.registerDriver(new Driver());
      try (Connection connection = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
            Statement stmt = connection.createStatement();
            ResultSet resultSet = stmt.executeQuery("SELECT WINE_ID,WINE_NAME,PRICE FROM WINE_DETAIL")) {

         while (resultSet.next()) {
            WineDetail detail = new WineDetail();
            detail.setId(resultSet.getInt("WINE_ID"));
            detail.setName(resultSet.getString("WINE_NAME"));
            detail.setPrice(resultSet.getDouble("PRICE"));
            listOfWine.add(detail);
         }
      }
   } catch (SQLException e) {
      e.printStackTrace();
   }
   return listOfWine;
}
}

We will also create a WineService and WineServiceImpl which will serve as middle tier between our dao and servlet.

public interface WineService {
    public List<WineDetail> getListOfWines();
}

public class WineServiceImpl implements WineService{

    private WineDao dao;

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

    @Override
    public List<WineDetail> getListOfWines() {
        return dao.getListOfWines();
    }
}

Now lets add a xml which would contain our class and dependency definition, just like we did our rudimentary container in our last post, we need to give spring an account of what classes do we have and what dependency do we have, lets call this file application.xml and we would place this file in src/main/resources.

Dependency Definition

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    
    
    <bean id="wineService" class="com.learnithardway.web.WineServiceImpl">
        <property name="dao" ref="wineDao"/>
    </bean>

    <bean id="wineDao" class="com.learnithardway.web.WineDaoImpl">

    </bean>


</beans>

Notice that we have explicitly defined each and every class as bean, which is springs way of saying that its a spring managed class, and each of the dependency are represented as property which are cross referenced to other beans or they could be simple values as well. Now that we have the dependency definition in place, lets look at servlet on how to initialise the spring container.

public class IndexServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private ApplicationContext applicationContext;

	@Override
	public void init() throws ServletException {
		applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		WineService wineService = applicationContext.getBean(WineService.class);
		List wines = new ArrayList<>();
		List listOfWines = wineService.getListOfWines();
		request.setAttribute("wines", listOfWines);
		request.getRequestDispatcher("wines.jsp").forward(request, response);
	}

}

The entire spring context is contained in applicationContext, there are multiple types of application context available, like ClassPathXmlApplicationContext and WebApplicationContext depending on how its being initialised. Once initialised we can look up the necessary dependency using getBean method, in this case the servlet in not managed by Spring hence spring acts like a service registry instead of IOC container, which for spring managed class like WineService it acts as IOC container and inject the dependency into WineService.

Syntax Sugar

In any non trivial application the bean definition like this would quickly become cumbersome to maintain, for this spring came up with syntax sugar in form of namespaced xml tags, lets look at some of them.

    <context:annotation-config/>

This tells spring that we are going to manage our beans and dependencies using annotation, so we do not need to explicitly define the dependencies in xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean id="wineService" class="com.learnithardway.web.WineServiceImpl">
    </bean>

    <bean id="wineDao" class="com.learnithardway.web.WineDaoImpl">
    </bean>


</beans>

Now lets add annotation on the classes to mark the dependency, this can be done using either @Resource annotation or @Autowired.

public class WineServiceImpl implements WineService{

    @Resource
    private WineDao dao;

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

    @Override
    public List getListOfWines() {
        return dao.getListOfWines();
    }
}

That didn’t change much of xml for us right? Lets see if we can remove the bean definition, we have already told spring that we would manage our bean definition using annotation, now if we just let spring know where to look for our beans, we would not need to explicitly define the beans as well.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
    
    <context:component-scan base-package="com.learnithardway.web"/>


</beans>

Now we need to decorate our bean classes with @Component, @Service, or @Repository annotation which will tell Spring that these are our beans which should be managed by spring.

@Service
public class WineServiceImpl implements WineService{

    @Resource
    private WineDao dao;

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

    @Override
    public List getListOfWines() {
        return dao.getListOfWines();
    }
}

@Repository
public class WineDaoImpl implements WineDao {

public List getListOfWines() {
	ArrayList listOfWine = new ArrayList<>();
	try {
		DriverManager.registerDriver(new Driver());
		try (Connection connection = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
				Statement stmt = connection.createStatement();
				ResultSet resultSet = stmt.executeQuery("SELECT WINE_ID,WINE_NAME,PRICE FROM WINE_DETAIL")) {

			while (resultSet.next()) {
				WineDetail detail = new WineDetail();
				detail.setId(resultSet.getInt("WINE_ID"));
				detail.setName(resultSet.getString("WINE_NAME"));
				detail.setPrice(resultSet.getDouble("PRICE"));
				listOfWine.add(detail);
			}
		}
	} catch (SQLException e) {
		e.printStackTrace();
	}
	return listOfWine;
}
}

In the next part we would add Spring MVC to this example so that we can have our front end code also managed by Spring, please feel free to look at the code on github.


Author

Nitiz

There are currently no comments.

Bitnami