Fork me on GitHub

WoOF integration with JSP Tutorial

This tutorial demonstrates integrating WoOF with existing Java Server Pages (JSP).

Integration occurs by registering and using objects within the HttpServletRequest, HttpSession and ServletContext.

The tutorial will provide a simple page that renders a text property from an object registered in each context respectively. The following shows the resulting pages.

WoOF page

WoOF screen shot.

JSP

JSP screen shot.

Download Tutorial Source

Objects

The following are the objects being registered as attributes for integration. The objects have been deliberately kept simple to focus on integration.

The annotations on the objects will be explained later.

RequestBean

The following bean is registered in the HttpServletRequest.

@HttpRequestStateful("RequestBean")
public class RequestBean implements Serializable {

	private String text;

	public String getText() {
		return this.text;
	}

	public void setText(String text) {
		this.text = text;
	}
}

SessionBean

The following bean is registered in the HttpSession.

@HttpSessionStateful("SessionBean")
public class SessionBean implements Serializable {

	private String text;

	public String getText() {
		return this.text;
	}

	public void setText(String text) {
		this.text = text;
	}
}

ApplicationBean

The following bean is registered in the ServletContext.

@HttpApplicationStateful("ApplicationBean")
public class ApplicationBean {

	private String text;

	public String getText() {
		return this.text;
	}

	public void setText(String text) {
		this.text = text;
	}
}

Templates

The following illustrates the necessary JSP to render the three beans' text property to the page:

<jsp:useBean id="RequestBean" scope="request"
	class="net.officefloor.tutorial.woofservletjspintegration.RequestBean" />
<jsp:useBean id="SessionBean" scope="session"
	class="net.officefloor.tutorial.woofservletjspintegration.SessionBean" />
<jsp:useBean id="ApplicationBean" scope="application"
	class="net.officefloor.tutorial.woofservletjspintegration.ApplicationBean" />
<html>
    <body>
        <jsp:getProperty name="RequestBean" property="text" />
        <jsp:getProperty name="SessionBean" property="text" />
        <jsp:getProperty name="ApplicationBean" property="text" />
        <a href='/template.woof'>WoOF</a>
    </body>
</html>

The equivalent WoOF template is as follows:

<html>
    <body>
        ${text} 
		<!-- {Session} -->${text} 
		<!-- {Application} -->${text} 
		<a href='#{link}'>JSP</a>
    </body>
</html>

WoOF focuses on minimising the impact to the HTML. It enables this light instrumentation of the HTML by having a POJO (plain old java object) provide the dynamic logic for the web page rendering. The other tutorials contain further details.

The following is the template logic class for the above WoOF template.

public class TemplateLogic {

	public RequestBean getTemplate(RequestBean bean) {
		bean.setText("REQUEST");
		return bean;
	}

	public SessionBean getSession(SessionBean bean) {
		bean.setText("SESSION");
		return bean;
	}

	public ApplicationBean getApplication(ApplicationBean bean) {
		// Value set by SetupListener (show upper case for WoOF template)
		bean.setText(bean.getText().toUpperCase());
		return bean;
	}

	@NextTask("JSP")
	public void link(RequestBean requestBean, SessionBean sessionBean,
			ApplicationBean applicationBean) {
		requestBean.setText("REQUEST");
		sessionBean.setText("SESSION");
		applicationBean.setText("application"); // show lower case for JSP
	}
}

The configuration of WoOF occurs graphically and is as follows.

application.woof.

Integration

The above has already integrated WoOF with the JSP.

The integration is by the annotations on the objects. The annotations are flags to WoOF to find the object within the respective context by the specified name. Should the object not be registered it is instantiated and registered within the respective context. The dependency injection of the underlying OfficeFloor framework handles this logic. This results in the following.

Bean Context Access WoOF access JSP access
RequestBean HttpServletRequest.getAttribute("RequestBean") Method parameter annotated with @HttpRequestStateful("RequestBean") Used directly in web page via <jsp:useBean id="RequestBean" scope="request" class="net.officefloor.tutorial.woofservletjspintegration.RequestBean" /> and then <jsp:property name="RequestBean" property="text" />
SessionBean HttpSession.getAttribute("SessionBean") Method parameter annotated with @HttpSessionStateful("SessionBean") Used directly in web page via <jsp:useBean id="SessionBean" scope="session" class="net.officefloor.tutorial.woofservletjspintegration.SessionBean" /> and then <jsp:property name="SessionBean" property="text" />
ApplicationBean ServletContext.getAttribute("ApplicationBean") Method parameter annotated with @HttpApplicationStateful("ApplicationBean") Used directly in web page via <jsp:useBean id="ApplicationBean" scope="application" class="net.officefloor.tutorial.woofservletjspintegration.ApplicationBean" /> and then <jsp:property name="ApplicationBean" property="text" />

The integration works both ways also. The ApplicationBean does not have its value set by the WoOF template logic object. The value is specified by the following ServletContextListener on start-up.

public class SetupListener implements ServletContextListener {

	@Override
	public void contextInitialized(ServletContextEvent event) {
		
		// Create the application bean
		ApplicationBean bean = new ApplicationBean();
		bean.setText("APPLICATION");

		// Bind to ServletContext as attribute
		event.getServletContext().setAttribute("ApplicationBean", bean);
	}

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		// Nothing to clean up
	}
}

As the above ServletContextListener registers the ApplicationBean within the ServletContext, WoOF will obtain this object in rendering the web page and therefore have the text property already specified.

web.xml

For completeness of this tutorial the web.xml is as follows.

<?xml version="1.0" encoding="UTF-8"?>
<web-app>

	<listener>
		<listener-class>net.officefloor.tutorial.woofservletjspintegration.SetupListener</listener-class>
	</listener>

</web-app>

Unit Test

The unit test highlights the servicing of a request by:

  • WoOF template
  • JSP
    public class JspIT extends TestCase {
    
    	public void testTemplate() throws IOException {
    		this.assertRequest(
    				"/template.woof",
    				"<html> <body> REQUEST SESSION APPLICATION <a href='/template-link.woof'>JSP</a> </body> </html>");
    	}
    
    	public void testLinkToJsp() throws IOException {
    		this.assertRequest(
    				"/template-link.woof",
    				"<html> <body> REQUEST SESSION application <a href='/template.woof'>WoOF</a> </body> </html>");
    	}
    
    	private void assertRequest(String uri, String expectedContent)
    			throws IOException {
    
    		try (CloseableHttpClient client = HttpTestUtil.createHttpClient()) {
    
    			// Undertake the request
    			HttpResponse response = client.execute(new HttpGet(
    					"http://localhost:18180" + uri));
    			assertEquals("Request should be successful: " + uri, 200, response
    					.getStatusLine().getStatusCode());
    
    			// Ensure content is as expected (removing additional white spacing)
    			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    			response.getEntity().writeTo(buffer);
    			String html = buffer.toString();
    			html = html.replace('\t', ' ');
    			html = html.replace('\n', ' ');
    			html = html.replace('\r', ' ');
    			while (html.contains("  ")) {
    				html = html.replace("  ", " ");
    			}
    			html = html.trim();
    
    			// Ensure response is as expected
    			assertEquals("Incorrect response entity", expectedContent, html);
    
    		}
    	}
    }
    

Next

The next tutorial looks at making use of JEE Servlet dependencies (e.g. EJBs).