Accessing Spring Beans

The application we built in the last section works fine, but the IndexAction has no access to any Spring beans. Let's create a ProductManager interface and the StaticListProductManager implementation class and define a productManager bean. The ProductManager interface contains only one method: List<Product> findAll(). This method returns all available products and StaticListProductManager implements this method by returning a hard-coded list of products. The productManager bean is defined in the applicationContext.xml file, as shown in Listing 19-4.

Listing 19-4: productManager Definition in the applicationContext.xml

image from book
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"      "http://www.springframework.org/dtd/spring-beans.dtd">      <beans>     <bean            /> </beans>
image from book

The ProductManager interface implemented by StaticListProductManager is quite simple: it has only one method that returns all the products. Listing 19-5 shows the ProductManager interface.

Listing 19-5: ProductManager Interface

image from book
package com.apress.prospring.ch19.business;      import java.util.List;      import com.apress.prospring.ch19.domain.Product;      public interface ProductManager {     public List<Product> findAll(); }
image from book

This interface is implemented by StaticListProductManager, which returns only a hard- coded list of products, as shown in Listing 19-6.

Listing 19-6: StaticListProductManager Implementation

image from book
package com.apress.prospring.ch19.business;      import java.util.ArrayList; import java.util.List;      import com.apress.prospring.ch19.domain.Product;      public class StaticListProductManager implements ProductManager {          private List<Product> products;          private Product createProduct(int productId, String name, String description) {         Product product = new Product();         product.setProductId(productId);         product.setName(name);         product.setDescription(description);                  return product;     }          public StaticListProductManager() {         products = new ArrayList<Product>();         products.add(createProduct(1, "Pro Spring",              "The best book ever"));         products.add(createProduct(2, "Pro Jakarta Struts",              "That's a good one, too"));     }          public List<Product> findAll() {         return products;     }      }
image from book

This is a pretty standard way of implementing the Business Tier of a Spring application. Unfortunately, we do not define the Struts Action subclasses as Spring beans, which means we cannot use the Spring DI.

We need to take another approach. Because our application is running in a container that provides the ServletContext implementation and because it is a Spring application, the context's attribute WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE is set to an instance of Spring WebApplicationContext. We can use WebApplicationContextUtils. getRequiredWebApplicationContext(servletContext) to get WebApplicatonContext and then call its getBean() method to get an instance of a Spring bean.

Listing 19-7 shows how to use the technique described in the preceding paragraph to get an instance of the productManager bean.

Listing 19-7: Getting a Spring Bean in a Struts Action Subclass

image from book
public class IndexAction extends Action {          private ProductManager productManager;          public void setServlet(ActionServlet actionServlet) {         super.setServlet(actionServlet);         ServletContext servletContext = actionServlet.getServletContext();         WebApplicationContext wac =              WebApplicationContextUtils.                 getRequiredWebApplicationContext(servletContext);         productManager = (ProductManager)wac.getBean("productManager");     }          public ActionForward execute(ActionMapping mapping, ActionForm form,          HttpServletRequest request, HttpServletResponse response)          throws Exception {         request.setAttribute("products", productManager.findAll());                  return mapping.findForward("success");     } }
image from book

In Listing 19-7, you can see that the declaration of the ProductManager property looks just like the same declaration in a Spring controller. To get an instance of the ProductManager implementation declared in the productManager bean, we need to get the ServletContext from the ActionServlet instance by calling the getServletContext() method. Next, we use the WebApplicatonContextUtils utility class to get a WebApplicationContext instance associated with the ServletContext. Finally, we manually get the instance of the productManager bean by calling the getBean() method and passing in the bean name. Because getBean() returns Object, we must cast the returned instance to ProductManager. The execute() method can use the ProductManager instance in the usual way.

This is a very clumsy way to access the Spring beans. To simplify the access to the Spring- managed beans, Spring offers the ActionSupport class. It is a convenience superclass that extends Action and offers a number of methods that allow the subclasses to access the Spring API. Let's take a closer look at the methods offered by the ActionSupport class in Table 19-1.

Table 19-1: Methods Offered by ActionSupport

Method

Description

setServlet()

Gets the WebApplicationContext and MessageSourceAccessor instances from the Spring context. Calls onInit() when the servlet is being initialized and onDestroy() when it is being destroyed.

initWebApplicationContext()

Called from setServlet(), performs the WebApplicationServlet instance lookup. The default implementation is to find the root WebApplicationContext.

final getWebApplicationConext()

Returns an instance of WebApplicationContext.

final getMessageSourceAccessor()

Returns an instance of MessageSourceAccessor.

final getServletContext()

Returns an instance of ServletContext.

final getTempDir()

Returns the temporary directory for the web application.

onInit()

Subclasses can override this method to perform their own initialization. It is the last method called in the setServlet() method when the servlet is being loaded.

onDestroy()

Subclasses can override this method to perform their own deinitialization. It is the first method called in the setServlet() method when the servlet is being unloaded.

We can now refactor our IndexAction class to extend the ActionSupport class. To do so, we remove the setServlet() method and replace it by overriding the onInit() method. All these changes are shown in Listing 19-8.

Listing 19-8: Refactored IndexAction

image from book
package com.apress.prospring.ch19.web.actions;      import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;      import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.springframework.web.struts.ActionSupport;      import com.apress.prospring.ch19.business.ProductManager;      public class IndexAction extends ActionSupport {          private ProductManager productManager;          protected void onInit() {         productManager = (ProductManager)getWebApplicationContext().             getBean("productManager");     }          public ActionForward execute(ActionMapping mapping, ActionForm form,          HttpServletRequest request, HttpServletResponse response)          throws Exception {         request.setAttribute("products", productManager.findAll());              return mapping.findForward("success");     } }
image from book

As you can see, the code is much cleaner and still allows you to access the Spring beans.



Pro Spring
Pro Spring
ISBN: 1590594614
EAN: 2147483647
Year: 2006
Pages: 189

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net