Monday, November 2, 2015

Oracle Apex and IBM File Net Integration

One of my recent challenges this year was about integration of Apex and IBM filenet EMS, to know more about this product you can go to this , We had a requirement where the clients need a CMS and work flow engine that automate their process.

What we have done, is building the interface using Oracle Apex and the WF Engine on IBM Filenet, in order to integrate with this tool you have to use webservice calls with the right parameter to initiate the connection and start the workflow or resume the workflow process at a point of time where the user action is needed.

Below code is to initiate the case manager which is namely the workflow engine, and then return back the folder id that we are going to store our documents on later.

DECLARE
   l_clob            CLOB;
   l_response        CLOB;
   l_values          apex_json.t_values;
   l_user            VARCHAR2 (1000);
   lv_CASEFOLDERID   VARCHAR2 (1000);
BEGIN
   apex_web_service.g_request_headers (1).name := 'Content-Type';
   apex_web_service.g_request_headers (1).VALUE := 'application/json';
   l_clob :=
      apex_web_service.make_rest_request (
         p_url           => 'http://<hostname:port>/CaseManager/CASEREST/v1/cases',
         p_http_method   => 'POST',
         p_username      => '<username>',
         p_password      => '<password>',
         p_parm_name     => APEX_UTIL.string_to_table ('format'),
         p_parm_value    => APEX_UTIL.string_to_table ('json'),
         p_body          =>    '{
  "CaseType": "<Case Name>",
  "TargetObjectStore": "<Store Name>",
  "ReturnUpdates": true,
  "Properties" :
  [ // the array of case property values may be empty
    {
      "SymbolicName": "<parameter 1>",
      "Value" : "value1"
    },
    {
      "SymbolicName": "parameter2",
      "Value" : "value2"
    }

  ]
}}');


   apex_json.parse (p_values => l_values, p_source => l_clob, p_strict => TRUE);

   lv_CASEFOLDERID :=
      apex_json.get_varchar2 (p_path     => 'CaseFolderId',
                              p0         => 1,
                              p_values   => l_values);
/*Store your folder id some where to use it later*/

END;


As we mentioned before, we will upload document to this folder that we get it's ID when we fired the workflow engine for the first time:

DECLARE
   v_soap_request    CLOB;                                 --VARCHAR2 (32767);
   v_soap_response   CLOB;                                 --VARCHAR2 (32767);

   v_http_request    UTL_HTTP.req;
   v_http_response   UTL_HTTP.resp;
   v_action          VARCHAR2 (4000) := '';
   l_filename        VARCHAR2 (255);
   l_BLOB            BLOB;
   l_CLOB            CLOB;
   l_envelope        CLOB;
   l_mime_type       VARCHAR2 (1000);
   l_response_msg    VARCHAR2 (32767);
   l_xml             XMLTYPE;


   l_folder_id       VARCHAR2 (1000);
   req_length        BINARY_INTEGER;
   offset            PLS_INTEGER := 1;
   amount            PLS_INTEGER := 32767;
   buffer            VARCHAR2 (32767);
   v_error           VARCHAR2 (32767);
BEGIN
   -- l_CLOB := apex_web_service.blob2clobbase64 (l_BLOB);
   FOR rec IN (SELECT FILENAME, ATTACH_IMAGE, mime_type
                 -- INTO l_filename, l_BLOB, l_mime_type
                 FROM <images_table>
                WHERE application_no = :P3_APPLICATION_NO)
   LOOP
      offset := 1;
      amount := 32767;

      SELECT fn_folder_id
        INTO l_folder_id
        FROM <where we stored the folder id>
      

      l_CLOB := apex_web_service.blob2clobbase64 (rec.attach_image);
--this is the envelope to pass the file into File Net with some parameters depends on the case you have
      v_soap_request :=
            '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://docs.oasis-open.org/ns/cmis/messaging/200908/" xmlns:ns1="http://docs.oasis-open.org/ns/cmis/core/200908/">
   <soapenv:Header />
   <soapenv:Body>
      <ns:createDocument>
         <ns:repositoryId>{26F0ED12-B5F7-40FD-AD74-343530D7B13C}</ns:repositoryId>
         <ns:properties />
         <ns:folderId>'
         || l_folder_id
         || '</ns:folderId>
         <ns:contentStream>
            <ns:length>
          </ns:length>
            <ns:mimeType>'
         || rec.mime_type                                        --l_mime_type
         || '</ns:mimeType>
            <ns:filename>'
         || rec.filename                                          --l_filename
         || '</ns:filename>
            <ns:stream>'
         || l_CLOB
         || '</ns:stream>
         </ns:contentStream>
         <ns:versioningState>{NONE}</ns:versioningState>
         <ns:policies />
         <ns:addACEs />
         <ns:removeACEs />
         <ns:extension />
      </ns:createDocument>
   </soapenv:Body>
</soapenv:Envelope>';
      v_http_request :=
         UTL_HTTP.begin_request ('<host:port><wsdl path>/ObjectService',
                                 'POST',
                                 'HTTP/1.1');

      UTL_HTTP.set_header (v_http_request,
                           'Content-Type',
                           'text/xml;charset=UTF-8');
      UTL_HTTP.set_authentication (r           => v_http_request,
                                   username    => 'user',
                                   password    => 'Password',
                                   scheme      => 'Basic',
                                   for_proxy   => FALSE);
      UTL_HTTP.set_persistent_conn_support (TRUE);
      UTL_HTTP.set_transfer_timeout (600);

      UTL_HTTP.set_detailed_excp_support (TRUE);

      UTL_HTTP.set_header (v_http_request, 'Content-Type', 'text/xml');
      req_length := DBMS_LOB.getlength (v_soap_request);
      UTL_HTTP.set_header (v_http_request, 'Content-Length', req_length);



      UTL_HTTP.set_header (v_http_request, 'Transfer-Encoding', 'chunked');

      WHILE (offset < req_length)
      LOOP
         DBMS_LOB.READ (v_soap_request,
                        amount,
                        offset,
                        buffer);
         UTL_HTTP.write_text (v_http_request, buffer);
         offset := offset + amount;
      END LOOP;

      BEGIN
         v_http_response := UTL_HTTP.get_response (v_http_request);
      EXCEPTION
         WHEN OTHERS
         THEN
            UTL_HTTP.end_request (v_http_request);
            DBMS_OUTPUT.put_line ('error in request' || SQLERRM);
      END;

      BEGIN
         UTL_HTTP.read_text (v_http_response, v_soap_response);
      EXCEPTION
         WHEN UTL_HTTP.end_of_body
         THEN
            DBMS_OUTPUT.put_line ('error in reponse' || SQLERRM);
            UTL_HTTP.end_response (v_http_response);                --   NULL;
      END;

    --  UTL_HTTP.end_request (v_http_request);
   --UTL_HTTP.end_response (v_http_response);
   END LOOP;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line ('response' || SQLERRM);
      UTL_HTTP.end_response (v_http_response);
END;

Now at a specific point of time we need to make the workflow to do a step forward after some user decision or action.


DECLARE
   l_clob            CLOB;
   l_response        CLOB;
   l_values          apex_json.t_values;
   l_user            VARCHAR2 (1000);
   lv_CASEFOLDERID   VARCHAR2 (1000);
   lv_WF_NO          VARCHAR2 (200);
   l_url             VARCHAR2 (1000);
BEGIN

   SELECT WF_NUMBER
     INTO lv_WF_NO
     FROM <where you stored it>;
   

   BEGIN
      apex_web_service.g_request_headers (1).name := 'Content-Type';
      apex_web_service.g_request_headers (1).VALUE := 'application/json';
      apex_web_service.g_request_headers (2).name := 'If-Match';
      apex_web_service.g_request_headers (2).VALUE := '89.0';
      l_url := --'URL Of the WF service';
         q'!http://<your path>/!';
      l_url := l_url || lv_WF_NO;
      l_url := l_url || q'!?cp=MainWFSystemCP1&action=lock&responseContent=1!';
      l_clob :=
         apex_web_service.make_rest_request (
            p_url           => l_url,
            p_http_method   => 'PUT',
            p_username      => 'user',
            p_password      => 'password',
            p_parm_name     => APEX_UTIL.string_to_table ('format'),
            p_parm_value    => APEX_UTIL.string_to_table ('json'),
            p_body          => '{"eTag" : "89.0"}');
   END;

   BEGIN
      apex_web_service.g_request_headers (1).name := 'Content-Type';
      apex_web_service.g_request_headers (1).VALUE := 'application/json';
      apex_web_service.g_request_headers (2).name := 'If-Match';
      apex_web_service.g_request_headers (2).VALUE := '89.0';



      l_url :=
         q'!http://<your path>/!';
      l_url := l_url || lv_WF_NO;
      l_url :=
         l_url || q'!?cp=MainWFSystemCP1&action=dispatch&responseContent=0!';


      l_clob :=
         apex_web_service.make_rest_request (
            p_url           => l_url,
            p_http_method   => 'PUT',
            p_username      => 'user',
            p_password      => 'password',
            p_parm_name     => APEX_UTIL.string_to_table ('format'),
            p_parm_value    => APEX_UTIL.string_to_table ('json'),
            p_body          => '{"systemProperties":{"selectedResponse":"Reject"}}');

   END;
END;

I hope you find this helpful.