[Opensource] Is anyone actually using workflow with ControllerForm/StateForm

BSC bsci at lycos.com
Mon Feb 17 20:31:57 PST 2003


>> 2) abstract class HubState (or maybe HubController?)
 - has code to manage/verify the allowed "input path(s)" and "output path(s)"
 - "output paths" would be the branches (seperate Controllers?), with a returnToSender() type setting defined in the HubState allowing return to the HubState when the final state of an "output path" is completed.


The existing workflow logic can handle this type of situation.
Here's some code snippets of what you're calling a HubState:


The controller looks something like this:


public class MyDevices extends DBController {
	
	State showState = new ShowMyDevices("show", "Devices");
	addFinalState(showState);

	Transition oneTransition = new Transition();
	oneTransition.setControllerObject("com.xxx.controller.SignIn");
	try {
		oneTransition.enableReturnToSender(null);
	} catch (com.jcorporate.expresso.core.controller.ControllerException ce) {throw new NonHandleableException(ce);}	
	setControllerSecurityTransition(oneTransition);


This controller only has one state (ie no addStatePairing).  The state generates a list of items from the database along with the Transition objects that apply to each item.  The valid transitions could be dependent of the current user's privileges or could be dependent on something specific to the actual data item in the list.  Here is a pseudo-sample:



public class ShowMyDevices extends State {

public void perform(StateForm stateForm, ControllerRequest request, ControllerResponse response)
			throws ControllerException, NonHandleableException {

		while ( "More devices to list" ) {  //Loop on data to display
			
			i++;
			oneBlock = new Block("Line"+i);
			
			oneOutput = new Output("pin", oneDev.getField("PIN"));
			oneBlock.add(oneOutput);

			if (status.equals("UNAUTH")) {
				oneTransition = new Transition();
				oneTransition.setControllerObject("com.xxx.controller.AuthDevice");
				oneTransition.setName("authDevice");
				oneTransition.setLabel("Authenticate");
				oneTransition.enableReturnToSender(response);
				oneTransition.addParam("deviceID", oneDev.getField("DeviceID"));
				oneBlock.add(oneTransition);
			} else {
				if ( status.equals("INACTIVE") || status.equals("ACTIVE") ) {
					oneTransition = new Transition();
					oneTransition.setControllerObject("com.xxx.controller.DelivSettings");
					oneTransition.setName("delivSettings");
					oneTransition.setLabel("Settings");
					oneTransition.enableReturnToSender(response);
					oneTransition.addParam("deviceID", oneDev.getField("DeviceID"));
					oneBlock.add(oneTransition);
				} else {
					throw new ControllerException("Invalid device status: " + status);
				}	
			}
			//Add remove button - The remove controller will provide msg if invalid operation
			oneTransition = new Transition();
			oneTransition.setControllerObject("com.xxx.controller.RemoveDevice");
			oneTransition.setName("removeDevice");
			oneTransition.setLabel("Remove");
			oneTransition.enableReturnToSender(response);
			oneTransition.addParam("deviceID", oneDev.getField("DeviceID"));
			oneBlock.add(oneTransition);
					
			response.add(oneBlock);


The JSP....

  <logic:iterate id="currBlock" property="blocks"> 
  <tr> 

    <td align="left"><bean:write name="currBlock" property="/pin"/></td>

	<logic:present name="currBlock" property="/authDevice">
    <td align="left"> <bean:define id="authDeviceURL" name="currBlock" property="/authDevice.url" type="java.lang.String"/> 
      <html:link page="<%= authDeviceURL %>"><img src="../../images/butauthenticate.gif" width="100" height="20" border="0"></html:link> 
    </td>
	</logic:present> 
	
    <logic:present name="currBlock" property="/delivSettings">
    <td align="left"> <bean:define id="delivSettingsURL" name="currBlock" property="/delivSettings.url" type="java.lang.String"/> 
      <html:link page="<%= delivSettingsURL %>"><img src="../../images/butsettings.gif" width="100" height="20" border="0"></html:link> 
    </td>
	</logic:present> 
	
    <td align="left"> <bean:define id="removeDeviceURL" name="currBlock" property="/removeDevice.url" type="java.lang.String"/> 
      <html:link page="<%= removeDeviceURL %>"><img src="../../images/butdelete.gif" border="0" width="100" height="20"></html:link> 
    </td>
	
  </tr>
  </logic:iterate> 


The JSP will display the list of items along with the valid buttons on each line.  When a user clicks on one of the buttons the appropriate controller is invoked.  Once that controller is completed successfully (this could be multiple screens) then this state (hub) is automatically redisplayed.


>> - However, you could "flow" through multiple hubs, which would get 
    complicated?


The current workflow does not support flowing through multiple hubs.


                
>>   - addStatePairing() still exists, but Handle states can be without
     promptStates when they are the first state in a Controller that
     is an "output path" from a hub.  
     Ex: a hub state has a prompt that lets you select a group of 
     Customers using checkboxes.  There are many branches (output paths) 
     for this hub.  Let's say one is "Email selected customers".  The first
     state in the EmailSelectedCustomersController must verify that those 
     users allow solicitation, if not the error message is displayed on the
     Hub's prompt screen. If so, the first prompt state is displayed.     


The current workflow can also handle this situation.  The sample code listed above is an example of this.  The 'removeDevice' function transitions to a controller/state that will not perform it's 'remove' function unless the device meets certain criteria.  If the criteria isn't met, the hub screen is redisplayed along with the message specified by the removeDevice state.  Here's a piece of the removeDevice state logic:

		if ( "Criteria is not met" ) {
			ErrorCollection errors = new ErrorCollection();
			errors.addError("Cannot remove device because...");
			response.saveErrors(errors);
		}	


In this situation the hub screen would be displayed along with the specified message.


     
>>4) To enhance reusability of external States, allow something like this 
   in the Controller's constructor:
     promptCustomerListState.suppressTransitions("deleteSelectedCustomers");
     promptCustomerListState.suppressNestedTransitions("deleteCustomer");   

   Currently I am handling this type of thing by customizing the different
   view's that use the same State.


I think customizing the views may not be such a bad thing.  The JSP sample listed above is fairly clean and only concerns itself with presentation-type logic.  The State is probably the best place to determine which transitions/functions are valid and the JSPs can decide which of the generated Transitions will be displayed.


---
Aime






_____________________________________________________________
Get 25MB, POP3, Spam Filtering with LYCOS MAIL PLUS for $19.95/year.
http://login.mail.lycos.com/brandPage.shtml?pageId=plus&ref=lmtplus



More information about the Opensource mailing list