Bussiness logic class for the Assentis DocBase web service BL.Sys.FOP.Common 1 %RegisteredObject 192.168.1.97 8888 0 0 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Methods for handling the RequestInfo proxy-object | /// | | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// Bepaalt of het CallType sync of Async is. Geeft boolean terug (1=Async) 1 CallType:%String %Boolean "vh_renderAndSaveToPostprocoutdataNotifyProcessor"]]> 1 Process:%String,CallType:%String %String Build the DocBase process to test DocBase2 functionality Oproepen als : s sc=##class(BL.Sys.FOP.DocBase).RequestFromTest() w sc,! 1 %Status Build the DocBase process from the arTask array and returns it via fopReq. fopReq als .local doorgeven 1 %Status This method can be called from the PreProcess-event in the BL.Sys.FOP.Verwerker classmethod RunTaskSequence() 1 SeqItem:Sys.FOP.emSeqItem,Doc:Sys.FOP.emDoc,DocBaseTemplate:%String %Status This method can be called from the PreProcess-event in the BL.Sys.FOP.Verwerker classmethod RunTaskSequence() Suffix PPC = Pre Process Command 1 SeqItem:Sys.FOP.emSeqItem,TSeq:Sys.FOP.TaskSequence,FilePath:%String %Status 1 SeqItem:Sys.FOP.emSeqItem,FilePath:%String %Status 1 blnDirect:%Boolean=0 %String Call the DocBase process via WebService and returns the status. In case of the Sync WS (CallType=S), the response is returned by reference (.local SyncResponse) if the FOP process was successful. 1 %Status Call DocBase WS via sync method. The response is returned by reference (.local SyncResponse) if the FOP process was successful. 1 %Status Call DocBase WS via Async method. The JobID of the async DocBase process/thread is returned immediatly (.local JobID) 1 %Status Call DocBase WS via Async method and wait (event - signal) until DocBase fopProcess is finished. The JobID is returned, unless the DocBase WS is not available. The response fopRes is returned in case of fopProcess errors. 1 %Status after an Async call to DocBase WS, the system waits until the DocBase fopProcess (identified by JobID) is finished. It returns the status result. The wait-event can be triggered by :
  • a signal from the DocBase WS "SendFopStatus"
  • a Wait timeout, returned with an DocBase error status which is retrieved via GetAsyncResponse()
  • deleting the Resource waiting; the last DocBase status is retrieved via GetAsyncResponse() In normal circumstances, it's the "SendFopStatus" that triggers the Wait event (when no error occurs). The response fopRes is returned by reference in case of fopProcess errors.]]> 1 %Status WS OK . Do wufAddToTempLog("Signal OK") . Set sc=$$$OK Else If (Rslt=0)&&(JobID["vh_")&&(JobID'["Notify") Do . Do wufAddToTempLog("Processed") . Set sc=$S($$$FopResStatus($$$adbResultFAILED):$$$ERROR($$$GeneralError,fopRes.errorMessage), 1:$$$OK) Else If Rslt=-1 Do . ; The resource has been deleted . ; if $IsObject(fopRes) and fopRes.jobStatus="F" then sc=fopRes.errormsg . Set sc=$S(1:$$$ERROR($$$GeneralError,"No Wakeup signal before the resource is deleted (ResID="""_$G(ResourceID)_""")")) . Do wufAddToTempLog("Res Deleted") Else If Rslt=0 Do . ; The wait event has timed out . If $$$FopResStatus($$$adbResultFAILED) Do . . Set msg=" Status=Failed; Msg="_fopRes.errorMessage . . Set sc=$$$ERROR($$$GeneralError,"Error in DocBase process (ResID="""_$G(ResourceID)_""")"_msg) . Else If $$$FopResStatus($$$adbResultCOMPLETED) Do . . Set msg="" . . Set sc=$$$OK . . Do:($$$Not(IgnoreWarningStatusCompleted)) wufSendWarningMail() . Else Do . . Set msg="" . . Set sc=$$$ERROR($$$GeneralError,"No Wakeup signal before the wait event timed out (ResID="""_$G(ResourceID)_""")") . Do wufAddToTempLog("Not Signalled") Else Do . ; Unknown status . Set sc=$$$ERROR($$$GeneralError,"Unknown status "_$G(Rslt)_" for wait event triggered (ResID="""_$G(ResourceID)_""")") Quit sc wufInitResource() Set Rslt=$SYSTEM.Event.Create(ResourceID) Quit:(Rslt) $$$OK ; Else Resource already created --> Renew Resource Set Rslt=$SYSTEM.Event.Delete(ResourceID) ; Aborts al previous Wait-events for this Resource Set Rslt=$SYSTEM.Event.Create(ResourceID) Quit:(Rslt) $$$OK Quit $$$ERROR($$$GeneralError,"$SYSTEM.Event can't create the resource named """_$G(ResourceID)_""" to wait for the SendFOPStatus trigger") ; can't create resource ??? --> wufSendWarningMail() ;New From,lbTo,Subj,Body,scMail Set Body="Fop DocBaseWS WARNING : JobID="_JobID Set Body=Body_$$$CRLF_"SendFopStatus WS NOT received while WaitUntilAsyncFinished(), but the FopResult returned Status=COMPLETED !"_$$$CRLF Set:($L($G(%TaskInfo("TSEQID")))) Body=Body_$$$CRLF_"TaskSequence "_%TaskInfo("TSEQID")_" - Task "_$G(%TaskInfo("TASKID"))_" - SeqItem "_$G(%TaskInfo("TSEQ-ITEM")) Set:($IsObject($G(fopRes))) Body=Body_$$$CRLF_$$$CRLF_$$ObjToText^vhLib(fopRes) Do ##class(Sys.FOP.Logging).GetMailFields(.From,.lbTo,.Subj,"Warning DocBaseWS") Set scMail=$$SendMiniMailForced^vhLib.Mail(From,lbTo,Subj,Body,,,,,) Quit wufAddToTempLog(sLog) ; Add to temp log, only if global node already exists Do ..AddToTempLog(ResourceID,$G(LogPrefix)_sLog,,1) ; blnCheckEmpty=1 Quit wufRepeatWait(TimeOut) #define DebugKeepWaiting $G(^Sys.FOP.Settings("DocBase","AsyncWS-Wait"))=1 ;New Rslt,blnWaitAgain,Status Set TimeOut=$G(TimeOut,10) Set RtnIncrement="$$wufIncrementTimeOut^"_$ZN ; $G(RtnIncrement,"$$wufIncrementTimeOut^"_$ZN) Kill fopRes For Set Rslt=$SYSTEM.Event.Wait(ResourceID,TimeOut\1) Do Quit:('blnWaitAgain) ; Quit:($D(fopRes)) ; . do WL^vhDBG("RunDocBaseWS Async "_$S(Rslt=0:"intermediate Wait ("_TimeOut_" sec)",1:"after Wait (max "_TimeOut_" sec)")_" --> Result:"_Rslt) . If Rslt=1 Do Quit . . Set blnWaitAgain=0 . . Set fopRes="" ; Aanvullen indien status toch moet gecontroleerd worden (om zeker te zijn) . ;Else Do . Do wufGetAsyncResponse(1) ; Check the status of the FopProcess; create/simulate response if error . Set Status=fopRes.jobStatus ; fopRes must exist! . ;do WL^vhDBG("Returned status: "_Rslt_$$$CRLF_$$ObjToText^vhLib(fopRes)) . Set blnWaitAgain=(Status=$$$adbResultPROCESSING)||(Status=$$$adbResultWAITING)||(Status=$$$adbResultCONTINUE)||($$$DebugKeepWaiting) . If blnWaitAgain=0 Do Quit ; (Status'?1(1"CONTINUE",1"BUSY",1"PROCESS")) . . ; Finished or error or unexpected status . . ;Set blnWaitAgain=0 . . Do wufAddToTempLog("Status="_Status) . ; Else Do . ;Set blnWaitAgain=1 . Do wufAddToTempLog("Waited for "_(TimeOut\1)_"s. ("_Status_")") . Kill fopRes . Set:(($L($G(RtnIncrement)))) TimeOut=$$wufIncrementTimeOut(TimeOut) ; X:($L($G(RtnIncrement))) "Set TimeOut="_RtnIncrement_"(TimeOut)" . Do:('$SYSTEM.Event.Defined(ResourceID)) $SYSTEM.Event.Create(ResourceID) ; In case the resource was deleted by someone else Do wufDeleteResource() Quit Rslt wufGetAsyncResponse(blnSimulOnError) Lock +AsyncResponse:2 Set scAsync=..GetAsyncResponse(JobID,.fopRes) ; ,.status,.err) ; ##class(BL.Sys.FOP.DocBase) Lock -AsyncResponse If $G(blnSimulOnError)&&($$$ISERR(scAsync))&&('$IsObject($G(fopRes))) Do . ; Simulate AsyncResponseObj . Set fopRes=##class(WSAsyncResponse).%New() . Set fopRes.jobStatus="FOP_VH_ERROR" . Set fopRes.errorMessage=$$ParseStatus^vhLib(scAsync) Quit wufDeleteResource() If $SYSTEM.Event.Delete(ResourceID) Do . ; Resource deleted Else Do . ; Could not delete the Resource Quit wufIncrementTimeOut(evtWaitTimeOut) #define TimeOutIsMax(%v) (evtWaitTimeOut'>%v) Quit:(..#PseudoAsync)||($G(SnellereFopStatusCheck)=1) $S($$$TimeOutIsMax(1):1.1, evtWaitTimeOut=1.1:2, $$$TimeOutIsMax(2):2.1, evtWaitTimeOut=2.1:3, $$$TimeOutIsMax(3):3.1, $$$TimeOutIsMax(4):5, 1:10) Quit $S($$$TimeOutIsMax(5):10, $$$TimeOutIsMax(10):30, $$$TimeOutIsMax(30):60, 1:120) ; $$$TimeOutIsMax(60):300, 1:900) ;Quit $S($$$TimeOutIsMax(1):5, $$$TimeOutIsMax(10):11, $$$TimeOutIsMax(12):13, $$$TimeOutIsMax(14):15, 1:16) ; // Om het verhogen van de timer te testen, moet de flag "AsyncWS-Wait" in de global ^Sys.FOP.Setting() tijdelijk op 1 gezet worden ]]> Result="ADBfop1c783c510f85c5f80d7ffd"]]> 1 JobID:%String %String Prepares the DocBase WS Client : Set TimeOut, if defined - Can check that WS is alive, via PeekServer (param blnPeek) - Set Proxy, if specified (programmer mode) 1 cl:%SOAP.WebClient,TimeOut:%Integer,blnPeek:%Boolean %Status SOAPService niet actief/bereikbaar d:(blnPeek) WL^vhDBG($G(%PrefixWL)_"PeekServer OK") ;Do cl.SetLocation($S(locIndx>0:$LG(lbLocs,locIndx),1:"")) ; Only one location, i.e. the default is already set Do cl.SetTimeOut($G(TimeOut,60)) Set cl.HttpUsername="uta" Set cl.HttpPassword="uta" If $G(%blnProxy,..#UseProxy)||($G($$$globSettingUseProxy,..#UseProxy)) Do . d WL^vhDBG("Set Proxy") . Set cl.HttpProxyServer=$G($$$globSettingUseProxySub("ProxyServer"),..#ProxyServer) . Set cl.HttpProxyPort=$G($$$globSettingUseProxySub("ProxyPort"),..#ProxyPort) Quit $$$OK ]]> This is the core method to call DocBase WS process (Type=Sync/Async). The response depends on the specified Type: sync returns fopRes and JobID, Async returns JobID only (.locals fopRes and JobID) Returns the Status as the result, and sends a mail in case of a WS error ($ZTRAP). 1 %Status Async WS (0/1): "_$G(blnAsync) Set msg=msg_$$$CRLF_"blnPeek : "_$G(blnPeek) Set msg=msg_$$$CRLF_"WSClient : "_$G(ProcSvc)_$$$CRLF_$$ObjToText^vhLib(ProcSvc) Set msg=msg_$$$CRLF Set msg=msg_$$$CRLF_"FopRequest : "_tmpReq_$$$CRLF_$$ObjToXML^vhLib(tmpReq) Set msg=msg_$$$CRLF Quit msg cwpSnipDataStream(tmpReq) ; .tmpReq als .local doorgeven // For Debugging purposes // Removes the DataStream from the SeedData. ;New sdKey,SeedD,tmpSuffix,tmpData Quit:('tmpReq.%IsA("BL.Sys.FOP.WSRequestInfo2")) Set sdKey="" For Set SeedD=tmpReq.SeedData.GetNext(.sdKey) Quit:(sdKey="") Do . Quit:('$IsObject(SeedD.StreamPropertyValue)) ; (SeedD.targetPropertyKey'="renderInfo.sourceBytesToRender") . ;w $$ObjToText^vhLib(SeedD),! . Set tmpSuffix=" ... "_$$$CRLF_"SNIPPED by WimV." . Set tmpData=SeedD.StreamPropertyValue.Read(512-$L(tmpSuffix))_tmpSuffix . Do SeedD.StreamPropertyValue.Clear() . Do SeedD.StreamPropertyValue.Write(tmpData) . Set SeedD.newPropertyValue=tmpData Quit ]]> Check the status of an on-going DocBase process w ##class(BL.Sys.FOP.DocBase).GetAsyncResponse(...) Set msg="Status: "_fopStatus_$S($L(ErrorMsg):$$$CRLF_ErrorMsg, 1:"") RetriesOnError: Aantal nieuwe pogingen (getJobStatus) wanneer de method faalt (WebService blijkt soms niet stabiel te zijn) 1 %Status Check the status of an on-going DocBase process. Same as method GetAsyncResponse(), except that this method returns the status Error if fopResponse contains an ErrorMsg w ##class(BL.Sys.FOP.DocBase).GetAsyncResponseOK(...) Set msg="Status: "_fopStatus_$S($L(ErrorMsg):$$$CRLF_ErrorMsg, 1:"") 1 %Status +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// | Methods handling the response of the DocBase web service: | /// | calltypes: WSResponse / WSAsyncResponse | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /// Uitlezen/verwerken van de resultaten 1 fopRes:WS.FOP.WSResponse,fopReq:WS.FOP.WSRequestInfo %Status Status msg: "_$$ParseStatus^vhLib(sc)) . Else If fopReq.process?1(1"SimpleXslTransformationOnly") Do .. Set FileName=##class(%File).NormalizeDirectory("C:\FOP\PDFTemp\")_"Result.fo.xml" .. Set sc=$$fprResponseToFile(fopRes,FileName) .. d WL^vhDBG($G(%PrefixWL)_"Response.data saved to file : ["_$$$Server_"] "_FileName_$$$CRLF_" --> Status msg: "_$$ParseStatus^vhLib(sc)) . Else Do .. d WL^vhDBG($G(%PrefixWL)_"Data: "_fopRes.data) Else Do . Set sc=..HandleFopResponseError(fopRes,fopReq) Quit sc fprResponseToFile(response,FileName) ;New sc,stream Set stream=##class(%FileCharacterStream).%New() Set sc=stream.LinkToFile(FileName) Quit:($$$ISERR(sc)) sc Set sc=stream.Write(response.data) Set sc=stream.SaveStream() Quit $$$OK */ ]]> 1 fopRes:WSResponse,JobID:%String,fopReq:WSRequestInfo %Status 1 ResourceID:%String,LogData:%String,Delim:%String="\",blnCheckEmpty:%Boolean=0 Event triggered by the WebService "StatusServer", called from Assentis DocBase processes. Should be called when using an Asynchronous implementation of the DocBase fop Server, usually as the last task in the DocBase Process. 1 DocBaseID:%String,Status:%String,NumberOfPages:%Integer,DocURL:%String Resource not defined . ; - Async wait timed out --> Resource already deleted . Do WL^vhDBG("Resource=UNDEF : "_ResourceID) . Do sfsAddToTempLog("Resource=UNDEF") . ; Retry after about 1,5,10 sec, in case of a delayed resource creation. . ; This should be done in a separate Job/thread. Set $ZTRAP="" Quit sfsAddToTempLog(sLog) ; Add to temp log (only if global node already exists) Do ..AddToTempLog(ResourceID,"SFS:"_sLog,,1) ; blnCheckEmpty=1 Quit sfsErrorFeedback Set $ZTRAP="" Set Body=$$sfsErrorMailBody() Do ##class(Sys.FOP.Logging).GetMailFields(.From,.lbTo,.Subj,"Error SFS") Set sc=$$SendMiniMailForced^vhLib.Mail(From,lbTo,Subj,Body,,,,,) Set $ZE="" Quit sfsErrorMailBody() #define BodyTitle "FOP SendFOPStatus Error : " Set Body="" Set Body=Body_$$$BodyTitle_$$$CRLF Set Body=Body_"Error message: "_$$ParseStatus^vhLib($G(%objlasterror))_$$$CRLF Set Body=Body_""_$$$CRLF Set Body=Body_$$$CRLF_"DocBase ID: "_$G(DocBaseID) Set Body=Body_$$$CRLF_"ResourceID: "_$G(ResourceID) Set Body=Body_$$$CRLF_"Status: "_$G(Status)_$$$CRLF_"NumberOfPages: "_$G(NumberOfPages)_$$$CRLF_"DocURL: "_$G(DocURL) Set Body=Body_$$$CRLF Set Body=Body_$$$CRLF_"$ZError: "_$ZError Set:($L($ZError)) Body=Body_$$$CRLF_"Line : "_$$sfsErrorToLine Set:($L($G(%objlasterror))) Body=Body_$$$CRLF_"Object Last Error: "_$$ParseStatus^vhLib(%objlasterror) Set Body=Body_$$$CRLF_"$ECode: "_$ECode Set Body=Body_"--- End of message ---"_$$$CRLF Set Body=Body_$$$CRLF_##class(Sys.FOP.Logging).GetJobInfo() Quit Body sfsErrorToLine() Set:($L($P($ZError,">",2))) sLine=$TEXT(@$P($ZError,">",2,32767)) Quit $G(sLine) ]]>