Projects‎ > ‎

Pre Post Operation Actions

Overview

Enhance the Operations to support Pre and / or Post processing. The Operations for a given Definition / Context can be configured to "execute" actions either before a given operation is executed and / or after the operation is executed.

  • Pre Actions would be executed:
    • AFTER the Subject sends the Request to the Context
    • BEFORE the Request is sent to the Service/Operations Tier.
  • Post Actions would be executed:
    • AFTER the Response is returned from the Service/Operations
    • BEFORE the Response is sent back to the Subject.

What about Functions

"Actions are to Operations ... as Functions are to Attributes"

Actions are used to invoke business logic either before (preAction) or after (postAction) the Service/Operation is executed, within the Context. Where as Functions are used to invoke business logic, for an individual Attribute, either before or after the operation.

Architecture

Declaring Actions

A new section will be added to the XML file (and the XSD) called OperationActions. This section will declare all Actions that can be used within the Operations of Contexts. Each Action can define Properties that will apply to all "uses" of a given Action. Each "usage" of an Action can either replace or add Properties when it is applied to an Operation.

Applying Actions

The <Operations .../> section of the <Context ...>...</Context> is enhanced to support a new XML Element ... <Actions> ...</Actions>. If there are multiple Actions (for a given Type) they will be execute in the that they are added to the Operation of the Context.


There may be a need to implement flow-control processing between multiple Action. This relates to whether a given Action should be executed based on a "outcome" of a previous Action. The initial implementation will always invoke all Actions in order.

Startup

  1. The openptk.xml is processed
  2. For each Action in the OperationActions section
    1. Check for id
    2. Check for classname
      • Try to instanciate the Class, verify it can be created
    3. Check for Properties
      • Add to Action if they exist
    4. Add the Action to the "template" Map of Actions
  3. For each Operation in each Context
    1. Check for an <Actions ...>...</Actions> section
    2. For each <Action ...> section
      • Validate the the id against the Map of Actions
      • Make a "new" instance (Copy) of the Action that's in the template Map using getClass().newInstance()
      • Set the Properties to be a merge of the template and "local" Properties
      • Run startup() method for the Action
      • Set the context in the new Action
      • Add the Action class to the context hashmap for operations

Runtime

  1. Create and populate an Input object
  2. Obtain the Subject from the Configuration
  3. Run Subject.execute(Operation, Input)
    1. Run the Functions associated with the Attribute if assigned to the Operation
      • Input may be modified by the Function
    2. Create Request based on Input
  4. Run Context.execute(Request)
  5. Run Context.preAction(Request)
    • Obtain all of the Actions for the Operation
    • For each Action call action.preAction(Request) if mode is PRE or BOTH
      • The Action may throw a ActionException
      • The Request may be modified by the Action
  6. Run Service.execute(Request)
    • Execute operation
    • Return Response
  7. Run Context.postAction(Response)
    • Obtain all of the Actions for the Operation
    • For each Action call action.postAction(Response) if mode is POST or BOTH
      • The Action may throw a ActionException
      • The Response may be modified by the Action
  8. Return Response from Context
  9. Create Output from Response
    1. Run the Functions associated with the Attribute if assigned to the Operation
      • Output may be modified by the Function
  10. Return output

Implementation

The following classes / interfaces define the API

Name: org.openptk.exception.ActionException
Type: Class
 
Name: org.openptk.context.actions.ActionIF extends ComponentIF
Type: Interface
Methods: public void preAction(RequestIF request) throws ActionException
public void postAction(ResponseIF response) throws ActionException
public void setContext(ContextIF context)
public ContextIF getContext()
public void startup() throws ActionException
public void shutdown() throws ActionException
 
Name: org.openptk.context.actions.Action extends Component implements ActionIF
Type: Abstract Class
Methods: public void preAction(RequestIF request) throws ActionException
public void postAction(ResponseIF response) throws ActionException
public void setContext(ContextIF context)
public ContextIF getContext()
public void startup() throws ActionException
public void shutdown() throws ActionException

Notify

Classname: org.openptk.context.actions.Notify
Description: Provides a means to notify a user (via email).
Mode: POST
Plugins: SendEmail
Template
Properties: sendemail.subject
sendemail.fromaddress
sendemail.toaddress.attribute
template.document
Declaration:
<Action id="notify" classname="org.openptk.context.actions.Notify">
   <Properties>
      <Property name="plugin.template" value="template"/>
      <Property name="plugin.email"    value="sendemail"/>
   </Properties>
</Action>
Usage:
<Context id="Person" definition="..." ...>
   ...
   <Operations>
      <Operation id="create" attrgroup="person-create" >
         <Actions>
            <Action id="notify" mode="post">
               <Properties>
                  <Property name="sendemail.subject"             value="Your Employee (MySQL) account has been created"/>
                  <Property name="sendemail.fromaddress"         value="%{email.fromaddress}" />
                  <Property name="sendemail.toaddress.attribute" value="email" />
                  <Property name="template.document"             value="EmailTemplate-AccountCreated" />
               </Properties>
            </Action>
         </Actions>
      </Operation>
      ...
   </Operations>
</Context>

IfExistsThenUpdate

Classname: org.openptk.context.actions.IfExistsThenUpdate
Description: Will automatically change a CREATE operation to UPDATE if the entry already exists.
Mode: PRE
Plugins: (none)
Properties: (none)
Declarations:
<Action id="ifexists" classname="org.openptk.context.actions.IfExistsThenUpdate">
</Action>
Usage:
<Context id="Media-MySQL-JDBC" enabled="true" definition="Media" connection="MySQL" association="JDBC-MEDIA">
   ...
   <Operations>
      <Operation id="create" attrgroup="media-create">
         <Actions>
            <Action id="ifexists" mode="pre" />
         </Actions>
      </Operation>
      ...
   </Operations>
   ...
</Context>

CheckMimeType

Classname: org.openptk.context.actions.CheckMimeType
Description: Checks the mime type of the file to ensure it matches the allowed types.
Mode: PRE
Plugins: (none)
Properties: mimetype.allow
Declarations:
<Action id="checkmimetype" classname="org.openptk.context.actions.CheckMimeType">
   <Properties>
      <Property name="mimetype.allow" value="image/png, image/jpg, image/jpeg, image/gif"/>
   </Properties>
</Action>
Usage:
<Context id="Media-MySQL-JDBC" enabled="true" definition="Media" connection="MySQL" association="JDBC-MEDIA">
   ...
   <Operations>
      <Operation id="create" attrgroup="media-create">
         <Actions>
            <Action id="checkmimetype" mode="pre" >
               <Properties>
                  <Property name="attribute.type" value="type"/>
               </Properties>
            </Action>
         </Actions>
      </Operation>
      ...
   </Operations>
   ...
</Context>

ScaleCropImage

Classname: org.openptk.context.actions.ScaleCropImage
Description: Scale and/or Crop and image file.
Mode: PRE
Plugins: (none)
Properties: size.width
size.height
uniqueid
attribute.data
attribute.type
attribute.length
attribute.modified
attribute.digest
attribute.context
attribute.subject
attribute.relationship
Declarations:
<Action id="thumbnail" classname="org.openptk.context.actions.ScaleCropImage">
   <Properties>
      <Property name="size.width"             value="50" />
      <Property name="size.height"            value="60" />
      <Property name="uniqueid"               value="${contextid}-${subjectid}-cardphoto"/>
      <Property name="attribute.data"         value="data"/>
      <Property name="attribute.type"         value="type"/>
      <Property name="attribute.length"       value="length"/>
      <Property name="attribute.modified"     value="modified"/>
      <Property name="attribute.digest"       value="digest" />
      <Property name="attribute.context"      value="contextid"/>
      <Property name="attribute.subject"      value="subjectid" />
      <Property name="attribute.relationship" value="relationshipid" />
   </Properties>
</Action>
Usage:
<Context id="Media-MySQL-JDBC" enabled="true" definition="Media" connection="MySQL" association="JDBC-MEDIA">
   ...
   <Operations>
      <Operation id="create" attrgroup="media-create">
         <Actions>
            <Action id="thumbnail" mode="post" />
         </Actions>
      </Operation>
      ...
   </Operations>
   ...
</Context>