0

I'm trying to execute several pl/sql blocks in a Dynamic Action, with feedback to the end user with a modal dialog reporting the current satus.

Something like:

Processing Step 1...

/*Run pl/sql code for step 1*/

Processing Step 2...

/*Run pl/sql code for Step 2*/

and so on...

Both, the pl/sql and javascript code, run as intended but when I combined them on a Dynamic Action in the sequence:

1 - Execute Javascript

2 - Execute PL/SQL block /* With wait for result option checked*/

3 - Execute Javascript

4 - Execute PL/SQL block

The status dialog is not been shown, however the pl/sql blocks are completed without problems.

I realize that this must be something related to javascript not been multithreaded, so I've moved the pl/sql block to application processes and run them as ajax calls like this:

function something(){
    var get;
    var result = 0;
    updateStatus('Running Step1');
    get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
    result = get.get();
    if(result > 0){
        updateStatus('Running Step 2');
        get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
        result = get.get();
    }
    closeStatusDialog();
}

But still, as before, the processes run fine but the dialog doesn't appear. Finally I added a setTimeOut function to each call, like this:

function something(){
    var get;
    var result = 0;
    updateStatus('Running Step1');
    get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
    result = setTimeOut(get.get(),500);
    if(result > 0){
        updateStatus('Running Step 2');
        get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
        result = setTimeOut(get.get(),500);
    }
    closeStatusDialog();
}

But still nothing. What can I do to get this running as needed?.

I've checked the browser console and no exeptions are been thrown, likewise with the pl/sql blocks.

9
  • Should if(result > 0){ be if(result.length > 0){ or should it be if(ParseInt(result) > 0){. Commented Apr 6, 2016 at 14:49
  • You don't need setTimeOut because .get() is synchrone. Commented Apr 6, 2016 at 14:51
  • What do you return from PL/SQL block? Commented Apr 6, 2016 at 14:51
  • Hi @hinotf, a number Commented Apr 6, 2016 at 15:05
  • 1
    @Typo I verified the specification (11.8.5 The Abstract Relational Comparison Algorithm) and if there is one string compared (only theses operetors <, >, <=, >) to a number and the string can be parsed to a number, it will be compared as numbers. You are right. Commented Apr 6, 2016 at 15:55

1 Answer 1

1

I've solved it, although the solution doesn't rely on dynamic actions, just javascript and applicacion processes. I'm posting this for anyone with a similar problem.

The htmldb_Get Javascript object is an oracle-apex wrapper for the XMLHttpRequest AJAX object. Poorly documented though.

I've found a copy of the code (at the bottom) and it turns out it has another function called GetAsync that allows to pass a function as a parameter to asign it to the onreadystatechange attribute on the XMLHttpRequest object, which will be executed each time the attribute readyState of the underlying XMLHttpRequest changes.

The function passed as a parameter can't have parameters on its own definition.

So, instead of calling get() on the htmldb_Get object you need to call GetAsync(someFunction)

With this solution in my case:

function something(){
    var get;
    get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
    get.GetAsync(someFunctionStep1);
}

function someFunctionStep1(){
    if(p.readyState == 0){ /*p is the underlying XMLHttpRequest object*/
        console.log("request not initialized");
        updateStatus('Running Step 1');
    } else if(p.readyState == 1){
        console.log("server connection established");
    } else if(p.readyState == 2){
        console.log("request received");
    } else if(p.readyState == 3){
        console.log("processing request");
    } else if(p.readyState == 4){
        console.log("request finished and response is ready");
        callStep2();
    }
}

function callStep2(){
    var get;
    get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
    get.GetAsync(someFunctionStep2);
}

function someFunctionStep2(){
    if(p.readyState == 0){
        console.log("request not initialized");
        updateStatus('Running Step 2');
    } else if(p.readyState == 1){
        console.log("server connection established");
    } else if(p.readyState == 2){
        console.log("request received");
    } else if(p.readyState == 3){
        console.log("processing request");
    } else if(p.readyState == 4){
        console.log("request finished and response is ready");
        closeDialog();
    }
}

Here's the htmldb_get definition, at the end is the GetAsync function

/*
  str should be in the form of a valid f?p= syntax
*/

function htmldb_Get(obj,flow,req,page,instance,proc,queryString) {
  //
  // setup variables
  //
  this.obj      = $x(obj);                   // object to put in the partial page
  this.proc     = proc != null ? proc  : 'wwv_flow.show'; // proc to call 
  this.flow     = flow != null ? flow  : $x('pFlowId').value;          // flowid
  this.request  = req  != null ? req  : '';               // request 
  this.page     = page; // page
  this.params   = '';   // holder for params
  this.response = '';   // holder for the response
  this.base     = null; // holder fot the base url
  this.queryString = queryString!= null ? queryString : null ; // holder for passing in f? syntax
  this.syncMode     = false;
  //
  // declare methods
  //

  this.addParam     = htmldb_Get_addParam;
  this.add          = htmldb_Get_addItem;
  this.getPartial   = htmldb_Get_trimPartialPage;
  this.getFull      = htmldb_Get_fullReturn;
  this.get          = htmldb_Get_getData;
  this.url          = htmldb_Get_getUrl;
  this.escape       = htmldb_Get_escape;
  this.clear        = htmldb_Get_clear;
  this.sync         = htmldb_Get_sync;
  this.setNode      = setNode;
  this.replaceNode  = replaceNode
  //
  // setup the base url
  //
   var u = window.location.href.indexOf("?") > 0 ?
             window.location.href.substring(0,window.location.href.indexOf("?"))
             : window.location.href;
   this.base = u.substring(0,u.lastIndexOf("/"));

   if ( this.proc == null || this.proc == "" ) 
           this.proc = u.substring(u.lastIndexOf("/")+1);

   this.base = this.base +"/" + this.proc;


  //
  // grab the instance form the page form   
  //
  if ( instance == null || instance == "" ) {
    var pageInstance = document.getElementById("pInstance");
      if ( typeof(pageInstance) == 'object' ) {
        this.instance = pageInstance.value;
      }
  } else {
    this.instance = instance;
  }


  //
  // finish setiing up the base url and params
  //
  if ( ! queryString ) {
      this.addParam('p_request',     this.request) ;
      this.addParam('p_instance',    this.instance);
      this.addParam('p_flow_id',     this.flow);
      this.addParam('p_flow_step_id',this.page);
  }

  function setNode(id) {
    this.node = html_GetElement(id);
  }
  function replaceNode(newNode){
      var i=0;
      for(i=this.node.childNodes.length-1;i>=0;i--){
        this.node.removeChild(this.node.childNodes[i]);
      }
      this.node.appendChild(newNode);
  }
}
function htmldb_Get_sync(s){
  this.syncMode=s;
}

function htmldb_Get_clear(val){
  this.addParam('p_clear_cache',val);
}

//
// return the queryString
//
function htmldb_Get_getUrl(){
    return this.queryString == null ? this.base +'?'+ this.params : this.queryString;
}

function htmldb_Get_escape(val){
    // force to be a string
     val = val + "";
     val = val.replace(/\%/g, "%25");
     val = val.replace(/\+/g, "%2B");
     val = val.replace(/\ /g, "%20");
     val = val.replace(/\./g, "%2E");
     val = val.replace(/\*/g, "%2A");
     val = val.replace(/\?/g, "%3F");
     val = val.replace(/\\/g, "%5C");
     val = val.replace(/\//g, "%2F");
     val = val.replace(/\>/g, "%3E");
     val = val.replace(/\</g, "%3C");
     val = val.replace(/\{/g, "%7B");
     val = val.replace(/\}/g, "%7D");
     val = val.replace(/\~/g, "%7E");
     val = val.replace(/\[/g, "%5B");
     val = val.replace(/\]/g, "%5D");
     val = val.replace(/\`/g, "%60");
     val = val.replace(/\;/g, "%3B");
     val = val.replace(/\?/g, "%3F");
     val = val.replace(/\@/g, "%40");
     val = val.replace(/\&/g, "%26");
     val = val.replace(/\#/g, "%23");
     val = val.replace(/\|/g, "%7C");
     val = val.replace(/\^/g, "%5E");
     val = val.replace(/\:/g, "%3A");
     val = val.replace(/\=/g, "%3D");
     val = val.replace(/\$/g, "%24");
     //val = val.replace(/\"/g, "%22");
    return val;
}

//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addParam(name,val){
    if ( this.params == '' ) 
     this.params =  name + '='+ ( val != null ? this.escape(val)  : '' );
  else
     //this.params = this.params + '&'+ name + '='+ ( val != null ? val  : '' );
     this.params = this.params + '&'+ name + '='+ ( val != null ? this.escape(val)  : '' );
     return;
}


//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addItem(name,value){
  this.addParam('p_arg_names',name);
  this.addParam('p_arg_values',value);  
}

//
// funtion strips out the PPR sections and returns that
//
function htmldb_Get_trimPartialPage(startTag,endTag,obj) {
   setTimeout(html_processing,1);
   if (obj) {this.obj = $x(obj);}
   if (!startTag){startTag = '<!--START-->'};  
   if (!endTag){endTag  = '<!--END-->'};
   var start = this.response.indexOf(startTag);
   var part;
   if ( start >0 ) {
       this.response  = this.response.substring(start+startTag.length);
       var end   = this.response.indexOf(endTag); 
       this.response  = this.response.substring(0,end);
   }         
       if ( this.obj ) {
          if(this.obj.nodeName == 'INPUT'){
            if(document.all){
              gResult = this.response;
              gNode = this.obj;
              var ie_HACK = 'htmldb_get_WriteResult()';
              setTimeout(ie_HACK,100);
            }else{
              this.obj.value = this.response;
            }
          }else{
            if(document.all){
              gResult = this.response;
              gNode = this.obj;
              var ie_HACK = 'htmldb_get_WriteResult()';
              setTimeout(ie_HACK,100);
            }else{
              this.obj.innerHTML = this.response;
            }
          }
       }
   //window.status = 'Done'
   setTimeout(html_Doneprocessing,1);
   return this.response;
}


var gResult = null;
var gNode = null
function htmldb_get_WriteResult(){
    if(gNode && ( gNode.nodeName == 'INPUT' || gNode.nodeName == 'TEXTAREA')){
    gNode.value = gResult;
    }else{
    gNode.innerHTML = gResult;
    }
    gResult = null;
    gNode = null;
  return;
}

//
// function return the full response
//
function htmldb_Get_fullReturn(obj) {
   setTimeout(html_processing,1);
   if (obj) { this.obj = html_GetElement(obj);}

       if ( this.obj ) {
          if(this.obj.nodeName == 'INPUT'){
            this.obj.value = this.response;
          }else{
            if(document.all){
              gResult = this.response;
              gNode = this.obj;
              var ie_HACK = 'htmldb_get_WriteResult()';
              setTimeout(ie_HACK,10);
            }else{
              this.obj.innerHTML = this.response;
            }
          }
       }
       setTimeout(html_Doneprocessing,1);
  return this.response;
}

//
// Perform the actual get from the server
//
function htmldb_Get_getData(mode,startTag,endTag){
   html_processing();
   var p;
   try {
      p = new XMLHttpRequest();
    } catch (e) {
      p = new ActiveXObject("Msxml2.XMLHTTP");
    }
    try {
        var startTime = new Date();
        p.open("POST", this.base, this.syncMode);           
        p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        p.send(this.queryString == null ? this.params : this.queryString );
        this.response = p.responseText;
        if ( this.node ) 
         this.replaceNode(p.responseXML);
        if ( mode == null || mode =='PPR' ) {
            return this.getPartial(startTag,endTag);
        } if ( mode == "XML" ) {
            setTimeout(html_Doneprocessing,1);
            return p.responseXML;
        } else {
            return this.getFull();
        }

    } catch (e) {
       setTimeout(html_Doneprocessing,1);
       return;
    }
 }

function html_Doneprocessing(){
  document.body.style.cursor="default";
}

function html_processing(){
    document.body.style.cursor="wait";
}

/* 
this adds better aysnc functionality 
to the htmldb_Get object 
pVar is the function that you want to call when the xmlhttp state changes
in the function specified by pVar the xmlhttp object can be referenced by the variable p
*/
htmldb_Get.prototype.GetAsync = function(pVar){
   try{
      p = new XMLHttpRequest();
    }catch(e){
      p = new ActiveXObject("Msxml2.XMLHTTP");
    }
    try {
        var startTime = new Date();
            p.open("POST", this.base, true);
            if(p) {
                    p.onreadystatechange = pVar;
                    p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                    p.send(this.queryString == null ? this.params : this.queryString );
                    return p;
        } 
        }catch(e){
      return false;
    }
 }



 /* PDF OUTPUT */
/*Gets PDF src XML */



function htmldb_ExternalPost(pThis,pRegion,pPostUrl){
   var pURL = 'f?p='+html_GetElement('pFlowId').value+':'+html_GetElement('pFlowStepId').value+':'+html_GetElement('pInstance').value+':FLOW_FOP_OUTPUT_R'+pRegion
   document.body.innerHTML = document.body.innerHTML + '<div style="display:none;" id="dbaseSecondForm"><form id="xmlFormPost" action="' + pPostUrl + '?ie=.pdf" method="post" target="pdf"><textarea name="vXML" id="vXML" style="width:500px;height:500px;"></textarea></form></div>';
   var l_El = html_GetElement('vXML');
   var get = new htmldb_Get(l_El,null,null,null,null,'f',pURL.substring(2));
   get.get();
   get = null;
   setTimeout('html_GetElement("xmlFormPost").submit()',10);
  return;
}


function $xml_Control(pThis){
        this.xsl_string = '<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html"/><xsl:param name="xpath" /><xsl:template match="/"><xsl:copy-of select="//*[@id=$xpath]"/></xsl:template></xsl:stylesheet>';
        if(document.all){
            this.xsl_object = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
            this.xsl_object.async=false;
            this.xsl_object.loadXML(this.xsl_string)
            tmp = new ActiveXObject("Msxml2.XSLTemplate.3.0");
            tmp.stylesheet = this.xsl_object;
            this.xsl_processor = tmp.createProcessor();
        }else{
          this.xsl_object = (new DOMParser()).parseFromString(this.xsl_string, "text/xml");
            this.xsl_processor = (new XSLTProcessor());
            this.xsl_processor.importStylesheet(this.xsl_object);
            this.ownerDocument = document.implementation.createDocument("", "test", null);
        }
        this.xml = pThis;
        this.CloneAndPlace = _CloneAndPlace;
        return

        function _CloneAndPlace(pThis,pThat,pText){
           var lThat = $x(pThat);
             if(document.all){
                this.xsl_processor.addParameter("xpath", pThis);
                this.xsl_processor.input = this.xml;
                this.xsl_processor.transform;
                var newFragment = this.xsl_processor.output;
             }else{
                 this.xsl_processor.setParameter(null, "xpath", pThis);
                 var newFragment = this.xsl_processor.transformToFragment(this.xml,this.ownerDocument);
             }
             if(lThat){
                if(document.all){
                 lThat.innerHTML='';
                 lThat.innerHTML=newFragment;
                }else{
                 lThat.innerHTML='';
                 lThat.appendChild(newFragment);
                }
             /*
             in IE newFragment will be a string
             in FF newFragment will be a dome Node (more useful)
             */
             return newFragment;
             }
        }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.