View Flow

Home
View
Created by david on 2009-06-09 09:30:14.0

A view flow is a group of views which belong together. A flow has a single entry point. When the flow is not active the user can only access the entry point view. When the user accesses one of the defined exit points, the flow will be "committed", when a view which does not belong to the flow is accessed the flow is "aborted". You can use view flows to create wizards or editors.

Our view flow is a wizard with 4 pages: 2 where the user can enter data, one page where he has to confirm the data and one page which reports the user that the operation was successful. There is also a start page (index.xhtml) which is not part of the view flow:

index.xhtml


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsxp="http://www.jsxp.org/spec/1.0">
	<head>
		<title>View Flow Test</title>
	</head>
	<body>
		(ViewFlowScope)<br/>
		<a href="start-flow.xhtml">Start of view flow</a><br/>
		<a href="flow-page-2.xhtml">Middle of view flow</a><br/>
	</body>
</html>

start-flow.xhtml


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsxp="http://www.jsxp.org/spec/1.0">
	<head>
		<title>Flow: Start the flow</title>
	</head>
	<body>
		(ViewFlowScope)<br/>
		<form action="flow-page-2.xhtml" method="post">
			Name: <input id="name" name="name" type="text"/><br/>
			<a href="index.xhtml">Abort</a> <input type="submit" value="Next &gt;"/>
		</form>
	</body>
</html>

flow-page-2.xhtml


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsxp="http://www.jsxp.org/spec/1.0">
	<head>
		<title>Flow: Page 2</title>
	</head>
	<body>
		(ViewFlowScope)<br/>
		<form action="confirm_page.xhtml" method="post">
			Foo: <input id="foo" name="foo" type="text"/><br/>
			<a href="index.xhtml">Abort</a> <a href="start-flow.xhtml">&lt; Back</a> <input type="submit" value="Next &gt;"/>
		</form>
	</body>
</html>

confirm-page.xhtml


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsxp="http://www.jsxp.org/spec/1.0">
	<head>
		<title>Flow: Confirm your input</title>
	</head>
	<body>
		(ViewFlowScope)<br/>
		<form action="finish-flow.xhtml" method="post">
			<p>Please Confirm:</p>
			Name: (Name)<br/>
			Foo: (Foo)<br/>
			<a href="index.xhtml">Abort</a> <a href="flow-page-2.xhtml">&lt; Back</a> <input type="submit" value="Confirm"/>
		</form>
	</body>
</html>

finish-flow.xhtml


<html xmlns="http://www.w3.org/1999/xhtml" xmlns:jsxp="http://www.jsxp.org/spec/1.0">
	<head>
		<title>Flow finished</title>
	</head>
	<body>
		(ViewFlowScope)<br/>
		
		<p>
			Thank you for executing this flow:<br/>
			Name: (Name)<br/>
			Foo: (Foo)
		</p>
		
		<a href="index.xhtml">Home</a>
	</body>
</html>

Now we need an Application class which defines our view flow (the application class has to be registered in the web.xml too - refer to the documentation for details about this):

ViewFlowApplication


package org.jsxp.test.viewflow;

import java.util.LinkedList;
import java.util.List;

import org.jsxp.framework.Context;
import org.jsxp.framework.ViewController;
import org.jsxp.framework.ViewFlow;
import org.jsxp.framework.ViewFlowListener;
import org.jsxp.framework.web.WebApplication;
import org.jsxp.test.viewflow.web.ConfirmPageXhtmlController;
import org.jsxp.test.viewflow.web.FinishFlowXhtmlController;
import org.jsxp.test.viewflow.web.FlowPage2XhtmlController;
import org.jsxp.test.viewflow.web.StartFlowXhtmlController;


public class ViewFlowApplication extends WebApplication implements ViewFlowListener {

	private static final long serialVersionUID = -7856533268296291041L;
	List<ViewFlow> flows = new LinkedList<ViewFlow>();
	
	public ViewFlowApplication() {
		ViewFlow flow = new ViewFlow(StartFlowXhtmlController.class, 
			ViewFlow.createViewList(StartFlowXhtmlController.class, FlowPage2XhtmlController.class, 
				ConfirmPageXhtmlController.class, FinishFlowXhtmlController.class), 
			ViewFlow.createViewList(FinishFlowXhtmlController.class), null);
		
		flow.addViewFlowListener(this);
		flows.add(flow);
	}
	
	@Override
	public List<ViewFlow> getViewFlows() {
		return flows;
	}

	@Override
	public String[] getViewControlBasePackages() {
		return new String[] {"org.jsxp.test.viewflow.web"};
	}

	public void viewFlowAborted(ViewFlow viewFlow) {
		Context.getContext().getFlashMessages().addInformationMessage("Page Flow Aborted!");
	}

	public void viewFlowFinished(ViewFlow viewFlow) {
		Context.getContext().getFlashMessages().addInformationMessage("Page Flow Finished!");
	}

	public void viewFlowStarted(ViewFlow viewFlow) {
		Context.getContext().getFlashMessages().addInformationMessage("Page Flow Started!");
	}

}

For all the input data we define a data bean class:

DataBean.java


package org.jsxp.test.viewflow.web;

import java.io.Serializable;

public class DataBean implements Serializable {
	private static final long serialVersionUID = 1L;
	private String name;
	private String foo;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getFoo() {
		return foo;
	}
	public void setFoo(String foo) {
		this.foo = foo;
	}
}

What's left now is the controllers for our views. Let's first start with the controllers for the views in the wizard.

StartFlowXhtmlController.java


package org.jsxp.test.viewflow.web;

import org.jsxp.framework.Context;
import org.jsxp.test.viewflow.web.generated.StartFlowXhtmlControllerGenerated;

public class StartFlowXhtmlController extends StartFlowXhtmlControllerGenerated<Object> {
	@Override
	public void execute() throws Exception {
		setVariableViewFlowScope(String.valueOf(Context.getContext().getScopes().getViewFlowScope()));
	}
}

Note that in the next 2 controllers, we use a data bean object as our input parameter. This exact data bean object we store in the view flow scope. This means that the user input is available to all views of the wizard as long as the flow is active.

FlowPage2XhtmlController.java


package org.jsxp.test.viewflow.web;

import org.jsxp.framework.Context;
import org.jsxp.framework.annotations.ViewFlowScope;
import org.jsxp.test.viewflow.web.generated.FlowPage2XhtmlControllerGenerated;

public class FlowPage2XhtmlController extends FlowPage2XhtmlControllerGenerated<DataBean> {
	private DataBean dataBean;
	
	@Override
	public void execute() throws Exception {
		setVariableViewFlowScope(String.valueOf(Context.getContext().getScopes().getViewFlowScope()));
	}

	@Override
	public DataBean getInputParameter() {
		return getDataBean();
	}
	
	@ViewFlowScope
	public DataBean getDataBean() {
		return dataBean;
	}
	public void setDataBean(DataBean dataBean) {
		this.dataBean = dataBean;
	}
}

ConfirmPageXhtmlController.java


package org.jsxp.test.viewflow.web;

import org.jsxp.framework.Context;
import org.jsxp.framework.annotations.ViewFlowScope;
import org.jsxp.test.viewflow.web.generated.ConfirmPageXhtmlControllerGenerated;

public class ConfirmPageXhtmlController extends ConfirmPageXhtmlControllerGenerated<DataBean> {
	private DataBean dataBean;

	@Override
	public void execute() throws Exception {
		setVariableViewFlowScope(String.valueOf(Context.getContext().getScopes().getViewFlowScope()));

		setVariableFoo(dataBean.getFoo());
		setVariableName(dataBean.getName());
	}

	@Override
	public DataBean getInputParameter() {
		return getDataBean();
	}
	
	@ViewFlowScope
	public DataBean getDataBean() {
		return dataBean;
	}
	public void setDataBean(DataBean dataBean) {
		this.dataBean = dataBean;
	}
}

FinishFlowXhtmlController.java


package org.jsxp.test.viewflow.web;

import org.jsxp.framework.Context;
import org.jsxp.framework.annotations.ViewFlowScope;
import org.jsxp.test.viewflow.web.generated.FinishFlowXhtmlControllerGenerated;

public class FinishFlowXhtmlController extends FinishFlowXhtmlControllerGenerated<Object> {
	private DataBean dataBean;

	@Override
	public void execute() throws Exception {
		setVariableViewFlowScope(String.valueOf(Context.getContext().getScopes().getViewFlowScope()));
		
		setVariableName(dataBean.getName());
		setVariableFoo(dataBean.getFoo());
	}

	@ViewFlowScope
	public DataBean getDataBean() {
		return dataBean;
	}
	public void setDataBean(DataBean dataBean) {
		this.dataBean = dataBean;
	}
}