ignore

Spring Integration

A must-have feature for modern Java web frameworks is a simple mechanism for integrating with the business tier. Top of the list here is integration with the Spring Framework.

Strecks allows for clean and elegant integration with Spring in three ways.

Spring Bean Injection

To enable Spring bean injection, two things need to be in place. You need one or more Spring application context XML files, which contains your Spring bean definitions, and you need an entry in WEB-INF/web.xml. The context XML files will be present in any Spring application; you can consult the Spring documentation for more details. The web.xml requires an entry similar to the following. Note that entries similar to these are required in any Spring web application, and not just ones involving Strecks.

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-context.xml</param-value>
</context-param>

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

The contextConfigLocation parameter simply denotes where the Spring configuration files are located. The ContextLoaderListener is used to load the Spring application context from this location.

Any bean referenced in the Spring configuration file can be injected into the action bean using the @InjectSpringBean annotation. For example, if spring-context.xml contains a bean named serviceBean, this bean can be injected into the action bean using code such as the following.

private Service serviceBean;

@InjectSpringBean(name = "serviceBean")
public void setServiceBean(Service serviceBean)
{
   this.serviceBean = serviceBean;
}

public void execute()
{
      //call serviceBean methods and do presentation logic
}

Action Beans as Spring Beans

Strecks includes a very simple mechanism to allow an action bean to be defined as a Spring bean. This could be particularly useful, for example, if you wish to add Spring's Aspect Oriented Programming capabilities to your action beans. It also allows you to resolve any Spring bean dependencies in your action bean class using Spring's Inversion of Control (IOC) container.

Assuming you already have an action bean named myActionBean configured as a Spring bean in your spring XML configuration file, all that is required to expose this as a Strecks action bean is a @SpringBean annotation to your action bean class declaration. The example below shows how this could be done.

@Controller(name = BasicController.class)
@SpringBean(name = "springActionBean")
public class SpringControlledAction implements BasicAction
{
    private String message;

    private SpringService springService;

    public String execute()
    {
        int count = springService.getCount();
        message = "Executed Spring controlled action, 
            count result obtained: " + count;
        return "success";
    }

    public String getMessage()
    {
        return message;
    }

    //note no @InjectSpringBean annotation required
    public void setSpringService(SpringService service)
    {
        this.springService = service;
    }
}

Note that the class SpringControlledAction will still need to be registered in struts-config.xml in the same way as any other Struts action or Strecks action bean.

Spring View Layer Integration

One of the most powerful features of Spring MVC is its support for alternative view technologies. Streck's pluggable view rendering allows you to seamlessly tap into this power. Use of Spring view rendering can be useful in a number of situations:

Enabling Spring view rendering is achieved through the use of the @SpringView annotation. To show how the @SpringView annotation can be used, we'll begin with a Struts-based view rendering example, then modify this to achieve the same result using Spring MVC view rendering in a few different ways.

Struts-based Example

In the navigation section, we described the use of the @NavigateForward annotation. In the example below, the @NavigateForward denotes the method whose return type is used to look up the ActionForward corresponding to the target JSP.

@Controller(name = NavigableController.class)
public class ExampleNavigableAction implements NavigableAction
{
    public void execute()
    {
         //implementation omitted
    }

    @NavigateForward
    public String getResult()
    {
        return "success";
    }
}

Using an entry in struts-config.xml, the result success is mapped to the JSP message.jsp, so that when action execution is complete, control will be forwarded to message.jsp.

Spring MVC Programmatic View

The first example shows the use of @SpringView with the view supplied programmatically.

@Controller(name = NavigableController.class)
public class SpringViewAction implements NavigableAction
{

    private String message;

    public void execute()
    {
     //implementation omitted
    }

    @SpringView()
    public ModelAndView getResult()
    {
        JstlView view = new JstlView();
        view.setUrl("/message.jsp");
        return new ModelAndView(view);
    }
}

Note that this example, no views or view resolver entries are required in the Spring XML configuration file. In fact, we don't even need a Spring configuration file. We are simply using the Spring API to enable forwarding to message.jsp.

While the example above clearly offers little additional benefit, we'd get much more out of this mechanism if our purpose was to enable view rendering using one of the alternative views, such as an AbstractPdfView or AbstractExcelView subclass.

Another thing to note: the method annotated with @SpringView must always return ModelAndView.

Named Spring View

We can get a similar result to our Struts-based example by the @SpringView annotation to enable obtaining a named Spring view. The action bean code in this case will look as follows.

public class SpringNamedViewAction implements NavigableAction
{
    private String message;

    public void execute()
    {
      //omitted
    }

    /**
     * Uses looks for view named "messageView" in application context
     */
    @SpringView()
    public ModelAndView getResult()
    {
        return new ModelAndView("messageView");
    }
}

The only difference with the previous example is that instead of returning a ModelAndView with a programmatically created View instance, we reference a named view. Of course, this view needs to be defined somewhere, and that place is in the Spring configuration file which is used to build your application's ApplicationContext. An entry such as the following would be suitable.

<bean id = "messageView" class = 
    "org.springframework.web.servlet.view.JstlView">
    <property name = "url" value = "/message.jsp"/>
</bean>

Conceptually, the usage here similar to the use of the success String to obtain an ActionForward, as in our first example. The scheme offers some flexibility while remaining simple. The problem is that we need a bean entry for each named Spring view, which for a large application could result in a lot of XML configuration. Also, in this example at least, we are no better off than using the Struts-based ActionMapping view resolution mechanism.

Resolved Spring View

We can add an additional level of indirection and flexibility by using a Spring ViewResolver. The purpose of a ViewResolver is to dynamically find views based on some contextual information. To enable finding views via a ViewResolver, our example would change to the following.

public class SpringViewResolverAction implements NavigableAction
{
    public void execute()
    {
        //implementation omitted
    }

    /**
     * Uses looks for view named "message" using 
     * resolver "viewResolver" obtained from application context
     */
    @SpringView(resolver = "viewResolver")
    public ModelAndView getResult()
    {
        return new ModelAndView("message");
    }
}

In this case, there is still a named view. Instead of looking it up directly by name in from the Spring ApplicationContext, we use a ViewResolver to find the view. Each ViewResolver implementation will use a different strategy for finding or creating a view based on the view name and other contextual information. One commonly used ViewResolver is the InternalResourceViewResolver, which supports localized views. A suitable Spring configuration bean entry to go with our SpringViewResolverAction action is shown below.

<bean id = "viewResolver" class = 
    "org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name = "viewClass" value = 
        "org.springframework.web.servlet.view.JstlView"/>
    <property name = "prefix" value = "/"/>
    <property name = "suffix" value = ".jsp"/>
</bean>

The InternalResourceViewResolver maps the view name to a localized version of a resource with the same name, allowing a prefix and suffix to be specified for extra flexibility.

Alternative View Technologies

The real power in integrating Strecks with Spring MVC view rendering becomes evident when we want to use alternative view technologies. In the next example, we show how Excel-based view generation can be enabled in a Strecks action bean. The example uses a subclass of AbstractExcelView, which relies on the Apache Jakarta POI library.

@Controller(name = NavigableController.class)
public class SpringExcelViewAction implements NavigableAction
{
    public void execute()
    {
        //implementation omitted
    }

    @SpringView()
    public ModelAndView getResult()
    {
        View view = new AbstractExcelView()
        {

            protected void buildExcelDocument(Map model, 
                HSSFWorkbook workbook, 
                HttpServletRequest request,
                HttpServletResponse response) throws Exception
            {
                HSSFSheet sheet = workbook.createSheet("Spring Excel View");
                sheet.setDefaultColumnWidth((short) 12);

                // Write a text at A1.
                HSSFCell cell = getCell(sheet, 0, 0);
                setText(cell, "Spring Excel View Via Strecks");

                // Write the current date at A2.
                HSSFCellStyle dateStyle = workbook.createCellStyle();
                dateStyle.setDataFormat(
                    HSSFDataFormat.getBuiltinFormat("m/d/yy"));
                cell = getCell(sheet, 1, 0);
                cell.setCellValue(new Date());
                cell.setCellStyle(dateStyle);
            }
        };
        return new ModelAndView(view);
    }
}

In this example, we are programmatically creating a our View object. Improvements to this example would involve registering our implementation as a named view or obtaining it via a ViewResolver, as we did in previous examples. However, it does demonstrate the basic practicalities involved in using Spring MVC view generation. Applying the same techniques for other view types would be no more difficult.

SourceForge.net logo java.net Member logo Copyright © 2005-2007 Realsolve Solutions