<%@ page import="java.io.*, java.net.*, java.util.*" %><@% page import="org.apache.xerces.parsers.*, org.xml.sax.*" %><%! /** This page provides a skeleton that explores some approaches to implementing an actor for the REST workflow controller. I've included a lot of comments in this page as guidence to some possible implementation strategies and alternatives. Copyright (c) 2002-2003 by Bryan Thompson, All rights reserved. */ %><% try { // Is this a POST? if( ! request.getMethod().equals( "POST" ) ) { /* 405: The agent only accepts the "POST" verb. */ response.sendError( response.SC_METHOD_NOT_ALLOWED ); } // Is there an XML entity? if( ! request.getContentType().startsWith("text/xml") && ! request.getContentType().startsWith("application/xml") ) { /* 415: Unsupported media type. */ response.sendError( response.SC_UNSUPPORTED_MEDIA_TYPE ); } /* Parse the XML entity, typically with DOM since its very small. */ if( request.getContentLength() != -1 ) { DOMParser parser = new DOMParser(); parser.setFeature( "validate", false ); parser.parse( new InputSource( request.getReader() )); Document body = parser.getDocument(); // extract event type and named event parameters. } else { throw new Exception( "required entity body not found in request.") } if( isActEvent ) { String activityURI; // from the ACT event. /* There is a set of response codes (30x) that may support use cases when the agent chooses to delegate the behavior to a different agent, when an agent has moved, when a proxy must be used, etc. See the HTTP/1.1 specification for details. The agent (this page) could also forward the request to another agent. @problem: If the request is redirected by any of these means, will the workflow controller be able to reach the final agent if it chooses to send a "HALT" event? It seems like the only way to support this is by keeping track of which page instance is actually processing that . Could that be managed easily using Session or a static Map? */ /* If an agent can perform its behavior with very low latency (comparable to network latency for a GET/POST/POST cycle) or with no possibility of error (a side effect that always succeeds), then it may send a 200 (Ok) to indicate that it performed the ACT and that the workflow controller may TERMINATE the activity on its behalf. Otherwise, the agent MUST use an asynchronous approach to communicating with the workflow controller. */ if( asynchronous ) { /* Indicate to the workflow controller that the agent has accepted the ACT event and will execute the delegated behavior for the specified activity instance. POST 202 (Accepted) */ /* Get a representation of the state of the activity instance whose implementation has been delegated to this agent. This step is required iff the agent needs access to that activity state in order to implement the correct behavior. The agent can get the workflow specification for the activity instance, access resources in named queues, retrieve the representation of the parent activity instance, etc., by following hyperlinks from the . GET */ /* Make changes in the state of the delegated activity. For example, the agent may POST an event, POST a resource, with its flow state, into a named resource queue, or use PUT to update local variables on the activity or to update the local variables associated with a resource in a resource queue for that activity. The agent may also DELETE resources from queues. POST to send an event or place a resource in queue. - and / or - PUT ... to update something that already exists. */ /* Send a "TERMINATE" event to the activity instance that was delegated to this agent. This event indicates the normal completion of the delegated behavior for that activity by the agent. POST "TERMINATE" */ } else { // do low-latency, synchronous behavior // POST 200 (Ok) return; // end of agent. } } } catch( Throwable t ) { /* POST an "EXCEPTION" event back to activity. */ } finally { /* Relinquish any resources that you may be holding. */ } %>