Saturday, November 18, 2017

Parsing XML using Oracle Objects(Types)

In the back to back system integrations, the common transmission language is the XML, since it is supported by most of the platforms, easy to understand and implement.

In Oracle, if there is a requirements to receive message body as XML, and this message structure is pre defined, and both parties, sender and receiver are aware of this, we can use the following technique to parse it and make use of the data.

Lets' say we have an XML coming as the following:

<PERSON_PROFILE>
  <FIRSTNAME>Mohammad</FIRSTNAME>
  <SECONDNAME>Ahmed</SECONDNAME>
  <LASTNAME>Abdullah</LASTNAME>
  <PERSONID>1231789456</PERSONID>
  <QUALIFICATION_LST>
    <QUALIFICATION>
      <QUAL_NAME>basic school</QUAL_NAME>
      <QUAL_DESC> basic school</QUAL_DESC>
    </QUALIFICATION>
    <QUALIFICATION>
      <QUAL_NAME>secondary school</QUAL_NAME>
      <QUAL_DESC> secondary school</QUAL_DESC>
    </QUALIFICATION>
    <QUALIFICATION>
      <QUAL_NAME>Bs Degree</QUAL_NAME>
      <QUAL_DESC> Bs Degree</QUAL_DESC>
    </QUALIFICATION>
  </QUALIFICATION_LST>
</PERSON_PROFILE>


First thing we will do, we will define an oracle types( Objects ) and tables that has the same structure of the XML root element:

--CREATE OBJECT TO HOLD THE QUALIFICATION INFO

CREATE OR REPLACE TYPE "QUALIFICATION_OBJ" AS OBJECT (
   QUAL_NAME   VARCHAR2 (100),
   QUAL_DESC   VARCHAR2 (1000)
);
/

--CREATE TABLE OF OBJECTS TO HOLE THE MULTI OBJECT VALUES

CREATE OR REPLACE TYPE "QUALIFICATION_LIST_TBL" AS TABLE OF QUALIFICATION_OBJ;
/

--CREATE THE ROOT OBJECT THAT REPRESENT THE WHOLE XML STRUCTURE

CREATE OR REPLACE TYPE "PERSONPROFILE_OBJ" AS OBJECT (
   FIRSTNAME            VARCHAR2 (200),
   SECONDNAME           VARCHAR2 (200),
   LASTNAME             VARCHAR2 (200),
   PERSONID             NUMBER (16),
   QUALIFICATION_LIST   QUALIFICATION_LIST_TBL
);

CREATE TABLE "PERSON_TABLE"  (
   ID NUMBER PRIMARY KEY,FIRSTNAME            VARCHAR2 (200),
   SECONDNAME           VARCHAR2 (200),
   LASTNAME             VARCHAR2 (200),
   PERSONID             NUMBER (16)
);

CREATE TABLE "QUALIFICATION_TABLE" (
   QUAL_NAME   VARCHAR2 (100),
   QUAL_DESC   VARCHAR2 (1000),
   PERSON_ID NUMBER ,FOREIGN KEY(PERSON_ID) REFERENCES PERSON_TABLE(ID)
);

Now we have the structure ready to accept the information from XML, we will create a procedure to be called and use these objects.


CREATE OR REPLACE PROCEDURE CREATEPERSONPROFILE_PRC (
   PX_MSG_IN    IN       CLOB,
   PX_MSG_OUT   OUT      CLOB
)
AS
   L_MYOBJECT   PERSONPROFILE_OBJ;
   L_XMLTYPE    XMLTYPE;
   OUT_XML      XMLTYPE;
BEGIN
   L_XMLTYPE := XMLTYPE (PX_MSG_IN);
   L_XMLTYPE.TOOBJECT (L_MYOBJECT);

   INSERT INTO PERSON_TABLE
               (FIRSTNAME, SECONDNAME,
                LASTNAME, PERSONID
               )
        VALUES (L_MYOBJECT.FIRSTNAME, L_MYOBJECT.SECONDNAME,
                L_MYOBJECT.LASTNAME, L_MYOBJECT.PERSONID
               );

   FOR I IN (SELECT VALUE (TD) OBJ_IN_COL
               FROM TABLE (L_MYOBJECT.QUALIFICATION_LIST) TD)
   LOOP
      INSERT INTO QUALIFICATION_TABLE
                  (QUAL_NAME, QUAL_DESC,PERSON_ID 
                  )
           VALUES (I.OBJ_IN_COL.QUAL_NAME, I.OBJ_IN_COL.QUAL_DESC,
L_MYOBJECT.PERSONID
                  );
   END LOOP;

END;




PS. The code is not based on the standards and best practices, it was only to show the concept.

Tuesday, September 26, 2017

انشاء معرض صور وعرضها من خلال اوراكل ابيكس\Image Slider using Carousel Region in Oracle APEX 5

السلام عليكم ورحمة الله وبركاته,

لقد تم مؤخرا اضافة خاصية جميلة جدا الى النسخة الخامسة من اداة الابيكس, بحيث تمكن المطورين من عمل مجموعة صور وعرضها بشكل معين وتبديلها بشكل اوتوماتيكي وهو ما لم يكن سابقا مدعوم من قبل هذه الاداة بشكل مباشر, حيث كان يتوجب على المطورين استخدام مكتبات من خارج الابيكس.

 1- انشاء منطقة (region) من نوع  (static content) واختيار القالب(template) الخاص بها بحيث يكون Carousel Container

ملاحظة: يمكن التحكم باعدادات المعرض من خلال خيارات القالب (Template Options) من حيث الابعاد والشكل والوقت



2- انشاء مناطق (regions) بعدد الصور المطلوبة من نوع (Static Content) , وجعل المرجع (Parent Region)  لهذه المناطق هو المنطقة الاولى (Banner)

3- كل ممنطقة من المناطق الفرعية يجب ان تحتوي على صورة معينة توضع في مصدر المنطقة (Region Source Text) 

<img src='/image1.jpg' style='width:100%' />

4- يتم وضع هذه الخاصية (style='width:100%') هنا لكي تاخذ الصورة كامل المنطقة.





نرجو الاستفادة من هذه اللمحة السريعة 

بانتظار اي تعليقات بناءة

مشكورين 

أخوكم : مهند عمارنة

Saturday, February 6, 2016

HTML table sorting, search and pagination

Hey guys,

Have you tried to make a dynamic plsql tabular report? did you face some issues with pagination, column sorting and searching?

Now it's super easy and in few seconds you can implement:

1- Include the required libraries.
//cdn.datatables.net/1.10.10/css/jquery.dataTables.min.css
//cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js

2- initialize the library.

$(document).ready(function(){
    $('#myTable').DataTable();
});

3- Specify the table id and use it:
<table id="myTable">
.
.
.
</table>

4- Enjoy it:



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.