Hi everyone!
Duke: I'm not using here a webservice datawindow, but hope this helps.
First of all, this is what I'm trying to accomplish: I need to trigger a webservice, let the user interact with the screen and start retrieving the results on screen so the user can see:
1) if it stills running (because the webservice starts a multithread on the server to upload files (last month 120,000) to a content manager server. If a file fails to be uploaded (it's not on the path, has a different content from the e-sign one registered on database) the thread being used continues with the next one, if it gets an error that thread ends. We record any of these situations on file and database so the user (a technical user) can take action.
2) which files are ready to do whatever the user need to do with them.
NOTE: this multithread (the example one) is used to execute different tasks, the webservice that I'm calling, internally uses multithread too but for the same task.
My development enviroment is:
Desktop app: PB 12.5.2 Build 5629 on a Windows 7 (64 bits)
Webservice: PB .Net 12.5.2 Build 5629 on a Windows Server Enterprise (32 bits)
This is my window:
Just as a reference:
Trámite / Servicio, Tipo de Docto. and Fuente are descriptor of the files.
Extensión del Docto.: is the file extension (as a reference for content manager server)
Ruta de Archivos a Subir: is the path of the files to be uploaded.
Ruta de Resultados: is the path for the XMLs with results of every file.
Secuencia del Proceso: is the ID of a massive process of e-signature where the files belong.
Folio Inicial and Folio Final: is the range of files to upload (the names are base on a sequence).
Usuario and Password del WS: User and password to authenticate on the webservice.
Inicio and Término: Start and Finish Date/Hour.
Exitosos: Filters files successfully uploaded on the below datawindow
Fallidos/Erróneos: Filters files that couldn't be uploaded.
Script:
*********************
* User objects *
*********************
1) uo_bcfe_firma (that connects to webservice {uof_conectar} and triggers the method to upload the files {uof_subirDoctoMulti})
NOTE: this NVO wraps all webservice methods (using its proxy)
integer uof_conectar (string as_usuario, string as_pwd, string as_endpoint)
--------------------------------------------------------------------
long ll_log, ll_instance
if isvalid(isoapconn_wsbcfe) then destroy(isoapconn_wsbcfe)
if isvalid(iws_bcfews) then destroy(iws_bcfews)
isoapconn_wsbcfe = create SoapConnection
iws_bcfews = create uo_bcfews
ll_log = isoapconn_wsbcfe.SetSoapLogFile ("mySoapLog.log")
ll_instance = isoapconn_wsbcfe.CreateInstance(iws_bcfews,"uo_bcfeWS",as_endpoint) //My webservice proxy is "uo_bcfeWS"
if ll_instance <> 0 then
istr_error.error = -1
istr_error.mensaje = 'No se pudo instanciar el Webservice'
ib_conectado = FALSE
return -1
end if
is_url = as_endpoint
ib_conectado = TRUE
return 0
uof_subirDoctoMulti (str_bcfe_subirdocto_request astr_request, uo_pro03p_procesomasivo auo_resultados)
------------------------------------------------------------------------------------------------------
this.uof_reset_error()
istr_error.funcion = 'uof_subirDoctoMulti'
try
/* SI NO ESTA CONECTADO, CONECTARSE AL WEBSERVICE */
if not ib_conectado or astr_request.s_endpoint <> is_url then
if this.uof_conectar(astr_request.s_usuario,astr_request.s_pwd,astr_request.s_endpoint) = -1 then
auo_resultados.uof_mostrar_resultado(istr_error)
return
end if
istr_error.funcion = 'uof_subirDoctoMulti'
end if
str_bcfesubirdocrequest lstr_request
str_bcfeError lstr_error
lstr_request = create str_bcfesubirdocrequest
lstr_error = create str_bcfeError
lstr_request.s_usuario = astr_request.s_usuario
lstr_request.s_contrasenia = astr_request.s_pwd
lstr_request.s_pathdoctos = astr_request.s_pathdocsubir
lstr_request.s_pathresult = astr_request.s_pathresult
lstr_request.i_tipotramite = astr_request.i_tipotramite
lstr_request.i_tipotramitespecified = true
lstr_request.i_tipodocto = astr_request.i_tipodocto
lstr_request.i_tipodoctospecified = true
lstr_request.i_fuente = astr_request.i_fuente
lstr_request.i_fuentespecified = true
lstr_request.s_secuencia = astr_request.s_secuencia
lstr_request.s_ext = astr_request.s_ext
lstr_request.s_folioini = astr_request.s_folioini
lstr_request.s_foliofin = astr_request.s_foliofin
lstr_request.s_rfchomo = astr_request.s_rfchomo
lstr_request.b_fnfbit=astr_request.b_fnfbit
lstr_request.b_fnfbitspecified = true
lstr_request.b_buscarpendientes = astr_request.b_bpend
lstr_request.b_buscarpendientesspecified = true
lstr_error = iws_bcfews.subirdoctomulti(lstr_request) // Webservice Call
istr_error.error = lstr_error.i_error // Copy values from the proxy variables to the app variables (different standard)
istr_error.mensaje = lstr_error.s_mensajeerror
auo_resultados.uof_mostrar_resultado(istr_error) // Triggers callback function and sends error (if exists)
catch (soapException e)
istr_error.error = -1
istr_error.mensaje = e.text
auo_resultados.uof_mostrar_resultado(istr_error)
return
end try
2) uo_pro03p_procesomasivo (manages the callback)
uof_setobject (window aw_invocador)
------------------------------------
istr_error.funcion = 'uof_setobject'
iw_ventana = aw_invocador // iw_ventana is an instance window variable
uof_mostrar_resultado (s_util_envia_error astr_error)
------------------------------------------------------
istr_error.funcion = 'uof_mostrar_resultado'
iw_ventana.post dynamic event ue_callback(astr_error) // Triggers whatever script is on the window
*********************
* Window *
*********************
wf_carga_masiva (when user hits "Procesar", input values are validated and then this function is called)
--------------------------------------------------------------------------------------------------------
/* OMITTED SCRIPT (NOT RELEVANT):
1) CLEARS VALUES ON DISPLAY FIELDS
2) CLEANS VARIABLES FOR EVERY RUN
3) GETS WEBSERVICE CONNECTION DATA
4) SET START HOUR ON SCREEN
5) SENDS A STARTING EMAIL TO THE USER
6) ETC.
*/
/* MANDAR DISPARAR LA CARGA MASIVA */
str_bcfe_subirdocto_request lstr_request
iuo_signext = create uo_bcfe_firma // NVO THAT CALLS THE WEBSERVICE
/* VALORES FIJOS */
lstr_request.s_endpoint = is_url
lstr_request.s_usuario = sle_usrws.text
lstr_request.s_pwd = sle_pwdws.text
lstr_request.i_tipotramite = ii_tipotram
lstr_request.i_tipodocto = ii_tipodoc
lstr_request.i_fuente = ii_fuente
lstr_request.s_pathdocsubir = sle_arcfirmar.text + '\'
lstr_request.s_pathresult = sle_arcresult.text + '\'
lstr_request.s_ext = dw_ext.uof_getvalueselected('extension')
lstr_request.s_secuencia = em_secuencia.text
lstr_request.s_folioini = em_secini.text
lstr_request.s_foliofin = em_secfin.text
lstr_request.b_fnfbit=cbx_filenotfound.checked
lstr_request.b_bpend = cbx_bpend.checked
guo_sesion.uof_obtiene_rfcusr(lstr_request.s_rfchomo)
/* DISPARAR HILO ALTERNO */
uo_pro03p_procesomasivo luo_comunicador1 // CALLBACK NVO
luo_comunicador1 = create uo_pro03p_procesomasivo
luo_comunicador1.uof_setobject( this ) // SETS THIS WINDOW AS THE INVOKER
SharedObjectRegister("uo_bcfe_firma", "hilows") // REGISTER NVO
SharedObjectGet("hilows",iuo_signext)
iuo_signext.post function uof_subirdoctomulti(lstr_request,luo_comunicador1) // TRIGGERS NVO METHOD THAT CALLS WEBSERVICE AND PASSES THE CALLBACK OBJECT INSTANCE
SharedObjectUnRegister('hilows')
/* DESHABILITAR MENU */
wf_habilita_menu(FALSE) // DISABLES MENU AND HIDES TOOLBARITEMS SO USER CAN'T TRIGGER ANYTHING BUT KEEPS ACCESS TO RESULTS DATAWINDOW AND PRINT OPTION.
ib_wsCorriendo = true // FLAG FOR WEBSERVICE TRIGGERED
timer(60,this) // STARTS TIMER FOR RETRIEVING RESULTS (1 MINUTE FOR TESTING)
ue_callback (windows user event)
------------------------------------------------------------------------
s_util_envia_error lstr_errorCorreo
string ls_vacio[]
timer(0) //stops timer
if astr_error.error <> 0 then
/* OMITTED SCRIPT
if webservice returns an error:
* an email is sent
* the triggered webservice flag is turn off (FALSE), so the window can be closed if needed.
* menu are enabled (and its toolbaritems are shown)
* error message is displayed on screen.
*/
end if
ib_wsCorriendo = false // the triggered webservice flag is turn off
timer(60) // restart timer
timer (windows event)
------------------------------------------------------------------------
this.wf_traer_resultados()
wf_traer_resultados (windows event)
------------------------------------------------------------------------
double ldb_max
sle_refresh.text = string(now()) // SETS LAST REFRESHING TIME ON SCREEN
/* TRAER LOS FOLIOS NUEVOS */
if dw_result.rowcount() = 0 then // IF THERES NOT RESULTS YET ON SCREEN LDB_MAX = 0 (RETRIEVES ONLY THE DIFFERENCE, USING MAX(FILEID) WHICH IS A SEQUENCE)
ldb_max = 0
dw_result.retrieve(is_secuencia, double(em_secini.text), double(em_secfin.text), ldb_max)
else
/* TRAERSE LOS FOLIOS DE DIFERENCIA Y COPIARLOS UNO POR UNO PARA DARLE EL EFECTO DE AVANCE */
ldb_max = dw_result.getitemnumber(1,'maximo')
openwithparm(w_dgi_espere,'Actualizando Resultados... ')
setpointer(Hourglass!)
idts_result.retrieve(is_secuencia, double(em_secini.text), double(em_secfin.text), ldb_max) // GETS ONLY THE NEW RESULTS
idts_result.rowscopy(1,idts_result.rowcount(),Primary!, dw_result,0, Primary!) // AND COPIES THEM TO DW ON SCREEN
if this.ib_wscorriendo or idb_maxAnt < ldb_max then // DOESN'T STOP THE TIMER UNTIL TRIGGERED WS FLAG IS OFF AND GETS NO MORE RESULTS.
if isvalid(w_dgi_espere) then close(w_dgi_espere)
setpointer(Arrow!)
idb_maxAnt = ldb_max
else
timer(0)
/* OMITTED SCRIPT
* NOTIFIES THE END ON SCREEN AND WITH AN EMAIL
* ENABLES AND SHOWS MENU
*/
messagebox('Aviso','Proceso Terminado Exitosamente')
end if
end if
return 0