Fork me on GitHub

Dynamic Navigation Tutorial

This tutorial demonstrates controlling navigation back and forth between the following two pages:

NavigateHttpServer one screen shot.NavigateHttpServer two screen shot.

Download Tutorial Source

application.woof

The following shows the configuration of the two web page templates and the navigation between the templates.

application.woof configuration.

The links are the navigation paths between the templates. Each template provides outputs that by the above configuration navigates the user to the other page.

@NextTask

The first template provides a link to navigate to the other template.

<html>
    <head>
        <title>One</title>
        <link rel="stylesheet" type="text/css" href="./css/one.css" />
    </head>
	<body>
		<h1>Page One</h1>
		<a href="#{navigate}">link</a>
	</body>
</html>

The link is handled by the following method. The annotation indicates the next task within the flow.

public class TemplateOne {

	@NextTask("external")
	public void navigate() {
	}

}

As the next task name is not a name of another method (and not a template section name, see later tutorials) it becomes an output from the template. From the configuration above the output is configured to navigate to the other template.

This is useful should some action be required to be taken when the user clicks to navigate to the next page.

@FlowInterface

The second template uses a submit to navigate to the first template.

<html>
    <head>
        <title>Two</title>
        <link rel="stylesheet" type="text/css" href="./css/two.css" />
    </head>
	<body>
		<h1>Page Two</h1>
		<form action="#{process}">
			<input type="submit" />
		</form>
	</body>
</html>

Much like the first template the logic class also navigates to an external flow. In this case it uses an interface for programmatic control of navigation.

public class TemplateTwo {

	@FlowInterface
	public interface Flows {
		void next();
	}

	public void process(Flows flows) {
		flows.next();
	}

}

As the interface is dependency injected, WoOF sees the @FlowInterface annotation and will provide an implementation of the interface. Each method on the interface will be linked by name to one of the following:

  • a method on the template logic class
  • a section of the template (see later tutorials)
  • an external flow from the template. This is then linked by the application.woof configuration (as is the case above)

This allows programmatically determining which is the next task. It is possible to add further methods to the interface to provide alternate navigation paths. Navigation only occurs if the method is invoked. Please also be aware that navigation to the page happens after the method has completed.

Both @NextTask and @FlowInterface may also be used in combination. @NextTask will provide the default next task unless overridden by a method of a @FlowInterface being invoked.

The above configuration has the external flow linked back to the first template.

Unit Test

The unit test navigates between the templates.

	private final CloseableHttpClient client = HttpTestUtil.createHttpClient();

	public void testNavigate() throws Exception {

		// Start server
		WoofOfficeFloorSource.start();

		// Request template one
		this.doRequest("http://localhost:7878/one.woof");

		// Click on link on template one
		this.doRequest("http://localhost:7878/one-navigate.woof");

		// Submit on template two
		this.doRequest("http://localhost:7878/two-process.woof");
	}

	private void doRequest(String url) throws Exception {
		HttpResponse response = this.client.execute(new HttpGet(url));
		assertEquals("Request should be successful", 200, response
				.getStatusLine().getStatusCode());
		response.getEntity().writeTo(System.out);
	}

Next

The next tutorial looks at storing state between requests within a HTTP session.