Oracle Openworld Directory Index
================================================= =================================================
Special Thanks
Dave Stoney
Oracle France
Technip
Joyce Peng
Vijayanth Devadhar
Agenda
Why the requirement
How did we do it
Structure of the IFS Document Class
Status
How will IFS communicate with Workflow
Start and Stop the workflow
How will Workflow communicate with IFS
Process Calls
Update IFS Workflow Status
How will Workflow send Notifications for IFS Documents
Why
Internet File System is a great tool for storing documents into a database structure
Allows multiple ways to manage and maintain documents
Explorer, Browser, FTP
IFS can be used as a document management system
Check In, Check Out, Versioning
However, there is no Document Lifecycle
Draft, review, completed, processing, approval, rejected
Solution
Get Workflow and IFS to talk to each other
IFS to Workflow
Start workflow
Stop Workflow
Workflow to IFS
Issue IFS commands like lock document, check out
Update Document Status
From Draft to Approved
Problem
Workflow and IFS does not work together
IFS uses a Java API
Workflow uses a PL/SQL API
Only true in WF 2.5
WF 2.6 introduced a WF Java API
How many PL/SQL programmers know Java?
Solution
From the User’s Point of View
Upload a Document
Upload Document
Maintain The Document
Submit the Document
Submit A Document
Start the Workflow
The WF Process
The WF Process
Notification
During the Process
Final Result
Solution
From The Programmer’s Point
The Design
The Design
WF Document Class
Value Default
Name:
WFDefaultStatus
Datatype:
String
Value:
Draft
Subclass
Name: WFDocument
Superclass: Document
Add Attribute
Name: WFStatus
Datatype: String
Length: 25
Is Settable: Yes
Read Only: Yes
Value Default:
WFDefaultStatus
WF Doc Agent
Purpose
To reassign all uploaded documents to the new WF Document sub-class
Design
Use the Event Based IFS Agent Template
Capture “Create Instance” IFS Event
WF Doc Agent Code
public void processEvent(IfsEvent event) throws IfsException
{
LibrarySession session = getSession();
try {
Long id = event.getId();
PublicObject po = session.getPublicObject(id);
log("Event type: " + event.getEventType());
log("Object: " + po.getClassname());
if (event.getEventType() == IfsEvent.EVENTTYPE_CREATEINSTANCE) {
if (po != null) {
if (po instanceof Document) newInstanceOfDocumentEvent((Document)po);
}
}
}
public void newInstanceOfDocumentEvent(Document document) {
try {
log("
if(document.getClassname().equalsIgnoreCase("DOCUMENT")){
//create a temp document using new class name
String tempName = document.getName().concat("_temp");
Document tempDoc = copyDocumentShareContent(document,tempName);
//Add it to same folder
String directoryPath = document.getAnyFolderPath().substring(0,(document.getAnyFolderPath().indexOf(document.getLabel())-1));
LibrarySession session = getSession();
FolderPathResolver folderpathresolver =
new FolderPathResolver(session);
PublicObject publicobject =
folderpathresolver.findPublicObjectByPath(directoryPath);
Folder newFolder = null;
if ( publicobject instanceof Folder)
newFolder = (Folder) publicobject;
newFolder.addItem(tempDoc);
//remove old document
String docName = document.getName();
removeItemFromFolder(document,newFolder);
//rename temp doc to old document
tempDoc.setName(docName);
Submit to Workflow
Modified showdocprops.jsp
// Change 016 KJB WF Process
else if (attributes[i].getLabel().equalsIgnoreCase("WFSTATUS")) {
<%=attVal%>
<%if (attVal.equalsIgnoreCase("DRAFT")) %>
onClick="submitWF();">
<%else if (! attVal.equalsIgnoreCase("APPROVED"))%>
<%
}
Submit Workflow
When the Submit Button is pressed, it will call submitWF.jsp
function submitWF() {
document.docPropertiesForm.wfbutton.value="Working...";
location="startWF.jsp?actn=start" +
"&id=" + document.docPropertiesForm.wfDocId.value +
"&path=" + document.docPropertiesForm.wfPath.value;
}
Submit WF JSP
<%@ page contentType = "text/html; charset=UTF-8" %>
<%@ page import = "java.sql.*;" %>
Calling Workflow...
<%
String action = request.getParameter("actn");
String path = request.getParameter("path");
String docId = request.getParameter("id");
%>
Action = <%= action %>
Id = <%= docId %>
Path = <%= path %>
<%
Connection conn = null;
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
if ((System.getProperty ("oracle.jserver.version")) == null) {
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521:stats",
"wfuser",
"wfuser");
}
Workflow Calling IFS
When a workflow function wants to talk to IFS, that function must do the following calls
Call a PL/SQL procedure in the WF API format
Top Function
The middle procedure will call a WF/IFS procedure to translate WF attributes and IFS attributes
Result
The low level procedure will manage communications with Advance Queue.
AQ Request Message
Used to send a message to IFS
This is the message that WFListnerAgent receives
CREATE OR REPLACE TYPE IFS_WF_REQUEST AS OBJECT
( IFS_WF_REQUEST_ID INTEGER,
IFS_WF_REQUEST_TYPE VARCHAR2(10),
IFS_WF_SOURCE_PATH VARCHAR2(80),
IFS_WF_CHECKIN_COMMENTS VARCHAR2(80),
IFS_WF_COPY_TARGET_FOLDER VARCHAR2(80),
IFS_WF_COPY_SOURCE_FOLDER VARCHAR2(80),
IFS_WF_NEW_FOLDER_NAME VARCHAR2(20),
IFS_WF_OVERWRITE_FLAG VARCHAR2(1),
IFS_WF_CREATE_PARENTS_FLAG VARCHAR2(1))
AQ Reply Message
This is the message that the lower PLSQL procedure is waiting for
This message is sent by WFListenerAgent
CREATE OR REPLACE TYPE IFS_WF_REPLY AS OBJECT
( IFS_WF_REQUEST_ID INTEGER,
IFS_WF_REQUEST_TYPE VARCHAR2(10),
IFS_WF_REPLY_STATUS_CODE INTEGER ,
IFS_WF_REPLY_DATA VARCHAR2(80),
IFS_WF_REPLY_MESSAGE VARCHAR2(250)
)
WF Listener Agent
A timed based IFS Agent that listens to an Advance Queue for a message
Every 5 seconds, the Agent wakes up to see if a message is on the queue
When a request message is received, the Agent compares the message against a large Case statement
When a match is found, the block of code is executed
The results are stored in a reply message and submitted to AQ
Example
Workflow wants to make a version of a document
Call Procedure Version_Document
Version Document gets the file name, creates a request message and sends it to AQ
WFListener gets the message, reviews the command
The Agent finds the command is a CASE statement
if (ifsMess.getIfsWfRequestType().equals("VERSION")) {
System.out.println("About to version document...");
ifsReply = ifsUtils.VersionDocument(ifsMess.getIfsWfSourcePath());
}
Example
And the version document command is executed using the IFS API
PublicObject po ;
ifsWfReply ifsreply = new ifsWfReply();
try {
// LibrarySession lsession = createLibrarySession();
IfsFileSystem fs = new IfsFileSystem(lsession);
po = fs.findPublicObjectByPath(path);
if (fs.isVersioned(po) == false ) {
System.out.println("Document " + path + " Not Versioned ");
ifsreply.setIfsWfReplyStatusCode(new Integer(1));
ifsreply.setIfsWfReplyMessage("Document " + path + " Not Versioned ");
return ifsreply;
}
else {
System.out.println("Document " + path + " is Versioned ");
ifsreply.setIfsWfReplyStatusCode(new Integer(0));
ifsreply.setIfsWfReplyMessage("Document " + path + " is Versioned ");
return ifsreply;
} }
Notifications
How does Workflow send a notification to a user that can approve a document?
Need a relationship
Members to Document
Relationship already exists
ACL
Approver Permission
Need to create a new permission bundle called Approver
Document ACL
When you add a member to the ACL, you can identify if that member is an approver
Notification
Workflow will look up all users who has a permission attribute set to approver and send a notification to each one
Notification Routing
ACE in a ACL is sequential sensitive. So, you can order the members in this list
Used so that member 1 gets the message first, approves the document, and member to gets a message
Summary
Workflow management is a very high requirement for a successful iFS Document Management System
In order for Workflow to communicate with iFS, the following must occur.
Using Oracle Advance Queues to broker the messages between Workflow’s PL/SQL API and iFS’s Java API.
Determining how iFS will trigger a workflow process
Storing the current workflow status of the iFS document during the workflow process
Summary
In order to solve these problems, the following was done
The sub-class WFDOCUMENT was created to store the current status of the document in a custom attribute called WFSTATUS .
The iFS Agent WFDocAgent was created to assign documents to the new WFDOCUMENT sub-class.
A document property JSP pages that can start a workflow process.
set of PL/SQL procedures that represent basic iFS calls (i.e.: copy document, version document) where created to be used by workflow to call IFS by placing messages on an advance queue.
Summary
(Continue)
The iFS Agent WFListenerAgent was created to listen for messages from workflow, execute basic iFS calls using the iFS API and reply back to workflow.
A set of Java methods that represents basic iFS calls where developed to be used by the WFListenerAgent to execute basic commands for workflow.
Thank You
Kevin Bongiovanni
Oracle Corporation
Kevinbongiovanni@yahoo.com