Progress 4GL web service procedure - web-services

I'm trying to update our stocks thought the Magento API using Progress 4GL (OpenEdge 10.2B)
So far so good, ie: I can update the stock if the SKU is a match. But if it isn't, it doesn't return an error.
So I looked into how ABL manages SAOP fault errors, and found some examples which I tried to implement. But to no avail.
My new code is as follows:
DEFINE VARIABLE hWebService AS HANDLE NO-UNDO.
DEFINE VARIABLE hMage_Api_Model_Server_V2_HandlerPortType AS HANDLE NO-UNDO.
DEFINE VARIABLE username AS CHARACTER NO-UNDO.
DEFINE VARIABLE apiKey AS CHARACTER NO-UNDO.
DEFINE VARIABLE stock AS CHARACTER NO-UNDO.
DEFINE VARIABLE codigo AS CHARACTER NO-UNDO.
DEFINE VARIABLE loginReturn AS CHARACTER NO-UNDO.
DEFINE VARIABLE product AS CHARACTER NO-UNDO.
DEFINE VARIABLE data AS LONGCHAR NO-UNDO.
DEFINE VARIABLE resultado AS INTEGER NO-UNDO.
DEFINE VARIABLE SOAP-FAULT-CODE AS CHARACTER NO-UNDO.
DEFINE VARIABLE SOAP-FAULT-DETAIL AS CHARACTER NO-UNDO.
DEFINE VARIABLE iError AS INTEGER NO-UNDO.
DEFINE VARIABLE cError AS CHARACTER NO-UNDO.
DO ON ERROR UNDO, THROW:
CREATE SERVER hWebService.
/* TODO: Definir variaveis globais */
username = 'username'.
apiKey = 'password'.
hWebService:CONNECT(" -WSDL 'http://www.medicalemcasa.com/api/v2_soap?wsdl'").
RUN Mage_Api_Model_Server_V2_HandlerPortType SET hMage_Api_Model_Server_V2_HandlerPortType ON hWebService.
RUN login IN hMage_Api_Model_Server_V2_HandlerPortType(INPUT username, INPUT apiKey, OUTPUT loginReturn).
product = "100asda001a".
data = "
<data>
<qty>'250'</qty>
</data>
".
PROCEDURE catalogInventoryStockItemUpdate:
DEFINE INPUT PARAMETER data AS CHARACTER NO-UNDO.
END PROCEDURE.
RUN catalogInventoryStockItemUpdate IN hMage_Api_Model_Server_V2_HandlerPortType (INPUT loginReturn, INPUT product, INPUT data, OUTPUT resultado).
DISPLAY resultado.
CATCH mySoapErrorObject AS Progress.Lang.SoapFaultError:
DO iError = 1 TO mySoapErrorObject:NumMessages:
cError = cError + mySoapErrorObject:getMessage(iError) + "~n".
END.
DELETE OBJECT mySoapErrorObject.
END CATCH.
CATCH mySystemErrorObject AS Progress.Lang.SysError:
DO iError = 1 TO mySystemErrorObject:NumMessages:
cError = cError + mySystemErrorObject:getMessage(iError) + "~n".
END.
DELETE OBJECT mySystemErrorObject.
END CATCH.
FINALLY:
IF cError <> "" THEN DO:
MESSAGE "Errors occured:" SKIP
cError
VIEW-AS ALERT-BOX ERROR.
END.
END FINALLY.
END.
hWebService:DISCONNECT().
DELETE OBJECT hWebService.

In those API's I've worked with SOAP errors only occur when there's a "bigger" error. For instance if the webservice is down, login criteria isn't met, datatypes are wrong etc. Usually a return value is rather in the response and not in the SOAP-envelope.
Could it be that it's simply OK to set a non existent product to inventory 0? What happens if you try to set it to 1? Perhaps you should double check from PHP (or whatever language you usually work with) that the web service actually provides the code you expect in this case?
Otherwise you should look at the wsdl-documentation created - are you 100% sure that the result-parameter (resultado in you code) is an INTEGER and not any form of more complicated xml-document (an object basically)? If it's really a HANDLE it might be that there's no run time error but no value is inserted into the INTEGER.
Also you should remove all your current error handling and replace it with a more general way to handle errors (and make that code more specific if needed rather than working from an example out of the documentation):
DEFINE VARIABLE iError AS INTEGER NO-UNDO.
DEFINE VARIABLE cError AS CHARACTER NO-UNDO.
CATCH mySoapErrorObject AS Progress.Lang.SoapFaultError:
DO iError = 1 TO mySoapErrorObject:NumMessages:
cError = cError + mySoapErrorObject:getMessage(iError) + "~n".
END.
DELETE OBJECT mySoapErrorObject.
END CATCH.
CATCH mySystemErrorObject AS Progress.Lang.SysError:
DO iError = 1 TO mySystemErrorObject:NumMessages:
cError = cError + mySystemErrorObject:getMessage(iError) + "~n".
END.
DELETE OBJECT mySystemErrorObject.
END CATCH.
And insert in the FINALLY-block:
IF cError <> "" THEN DO:
MESSAGE "Errors occured:" SKIP
cError
VIEW-AS ALERT-BOX ERROR.
END.

Related

variable being shadowed in trading view pinescript, saying use := instead

I am new to pinescript and have coded a simple indicator in trading view pinescript. I can get my buy and sell labels and also send alert when conditions are met.
I am trying to store the entry price as a variable when a sell or buy signal has been met. I also pass a var called pos which is 1 for sell and 2 for long.
i am trying to make the indicator send an alert when the entry price is above or below 20 pips. however my variable which is passed to the alert is being shadowed??? why??? im sure my code is correct?
var pos=0
var short_update = false
var entry_price = 0
if sellSignal
longLabel = label.new(
x=bar_index,
y=na,
text="Sell - "+ str.tostring(RoundUp(hlc3,2)),
xloc=xloc.bar_index,
yloc=yloc.abovebar,
color=color.red,
textcolor=color.white,
style=label.style_label_down,
size=size.normal)
entry_price=close
pos=1
alertcondition(sellSignal, "Short Alert", "Go short")
price_lower=entry_price-20
current_price=close
if pos==1 and current_price < price_lower
short_update=true
alertcondition(short_update, "Move Stop at BE", "BE")
above is my attempt at coding an alert condition if the entry price of a short is now 20 pips less...not working? please help
Actually all your variables defined with var on top are being shadowed not only "the one" you're referring to.
Shadowing variable 'pos' which exists in parent scope. Did you want to
use the ':=' operator instead of '=' ?
What does it mean?
You have declared your variables and assigned the first values correctly by the assignment operator: = in the global scope. If you want to update these values later on you'll need the reassignment operator though: :=.
The := is used to reassign a value to an existing variable. It says
use this variable that was declared earlier in my script, and give it
a new value.
source
So in your case var pos=0, var short_update = false, var entry_price = 0 are not getting updated through your whole script, are jut being redeclared as new variables in your local scopes that have no effect on the global ones, though having the same name.The solution is as simple as the error message says: use := instead of = if you want to update a declared variable.
Final note: try updating eg.: pos like this pos=1 in the global scope below you var pos=0 declaration. You'll get an error saying "'pos' is already defined". The same applies to your example, the only difference is that it is not illegal to redeclare a variable in a local scope, but Pine Script warns you correctly that it's probably not what you wanted.

Is there a way to get the BigQuery function or procedure name inside the function or procedure?

I have searched around on Google and here for an answer to this, and found nothing.
What I want to be able to do is something like:
DECLARE thisName string;
SET thisName = CurrentProcedure();
There is no way to fetch function name, but below procedure could help you to get procedure name from call stack.
It is a bit silly but there is no way to fetch call stack without throwing and catching an exception:
-- Returns name of the procedure which calls this procedure.
-- Returns NULL if called from top level of a script (not from a procedure).
CREATE OR REPLACE PROCEDURE yourDataset.CurrentProcedure(OUT name STRING)
BEGIN
RAISE USING MESSAGE = 'error on purpose';
EXCEPTION WHEN ERROR THEN
IF ARRAY_LENGTH(##error.stack_trace) >= 2 THEN
SET name = ##error.stack_trace[OFFSET(1)].location;
END IF;
END;
CREATE OR REPLACE PROCEDURE yourDataset.yourWorkProcedure()
BEGIN
DECLARE name STRING;
CALL yourDataset.CurrentProcedure(name);
SELECT name;
END;
CALL yourDataset.yourWorkProcedure();

How to convert XML response to temp-table in OpenEdge Progress4GL?

Hello Progress4GL Developers,
I am trying to use progress to consume a SOAP API. At the moment, I am just using a opensource sample SOAP service called: http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL.
The following program works a dream (i.e user inputs country code such as "ESP" and details about Spain are showed to user). The result is stored in temp-table1 and temp-table2:
/******* Sample Application to show Progress4GL Consuming a SOAP API *************/
/******* VARIABLES ***************************************************************/
DEFINE VARIABLE lReturn AS LOGICAL NO-UNDO.
DEFINE VARIABLE hServer AS HANDLE NO-UNDO.
DEFINE VARIABLE hPortType AS HANDLE NO-UNDO.
DEFINE VARIABLE capitalCity as LONGCHAR NO-UNDO.
DEFINE VARIABLE iCntryCode as char no-undo label "Country Code".
DEFINE VARIABLE oResponse as LONGCHAR no-undo.
/******* CONNECTION SETTINGS TO SOAP SERVICE *************************************/
CREATE SERVER hServer.
lReturn = hServer:CONNECT("-WSDL http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL").
IF lReturn = NO THEN DO:
MESSAGE
"Could not connect to WebService server".
END.
/******* SETTING PORT TYPE *******************************************************/
RUN CountryInfoServiceSoapType SET hPortType ON SERVER hServer.
IF NOT VALID-HANDLE(hPortType) THEN DO:
MESSAGE
"Could not establish portType".
END.
/****** USER UPDATE FORM**********************************************************/
UPDATE iCntryCode.
/****** NAME OF DATA FUNCTION TO RUN *********************************************/
RUN FullCountryInfo IN hPortType (INPUT iCntryCode, OUTPUT oResponse) NO-ERROR.
/****** TEMP TABLE TO HOLD ALL CAPITAL CITY FIELDS *******************************/
DEFINE TEMP-TABLE temptable1
SERIALIZE-NAME "sCapitalCity"
FIELD capitalCity AS CHAR XML-NODE-TYPE "text".
/****** DATASET WHICH RUNS CONVERSION ********************************************/
DEFINE DATASET dsa SERIALIZE-NAME "FullCountryInfoResult" FOR temptable1.
/***** TEMP TABLE TO HOLD ALL CURRENCY FIELDS ************************************/
DEFINE TEMP-TABLE temptable2
SERIALIZE-NAME "sCurrencyISOCode"
FIELD currencyCode AS CHAR XML-NODE-TYPE "text".
/****** DATASET WHICH RUNS CONVERSION ********************************************/
DEFINE DATASET dsb SERIALIZE-NAME "FullCountryInfoResult" FOR temptable2.
/****** POPULATE DATASET AND TEMP-TABLES FROM SOAP RESPONSE **********************/
DATASET dsa:READ-XML( "longchar", oResponse, ?, ?, ? ).
DATASET dsb:READ-XML( "longchar", oResponse, ?, ?, ? ).
FOR EACH temptable1 no-lock, each temptable2 no-lock:
DISPLAY temptable1.capitalcity temptable2.currencyCode.
END.
PAUSE 100.
/****** STOP CONNECTION TO SERVER ************************************************/
DELETE PROCEDURE hPortType.
hServer:DISCONNECT().
DELETE OBJECT hServer.
However, this sample web-service also has a procedure called FullCountryInfoAllCountries. This will give response for all countries. I have tried to re-factor the code above so that all temp-table1 and temp-table2 will be populated with all countries however I am having difficulty parsing the XML data.
I have tried experimenting with the NAMESPACE-URI, SERIALIZATION-NAME, and XML-NODE-NAME statements, but can't get it to work. The problem I have is that the XML response from FullCountryInfoAllCountries is structured differently to FullCountryInfo, and I always recieve an error along the lines of 'Namespace not found', or it will return nothing in the temp-tables.
Many Thanks in Advance!
You can peek at the output by messaging the response (commented out), this can then be mapped to dataset, temp-table and field names:
define variable hs as handle no-undo.
define variable hp as handle no-undo.
define variable lcresponse as longchar no-undo.
define temp-table tt serialize-name "tCountryInfo"
field sISOCode as character
field sName as character
.
define dataset ds serialize-name "FullCountryInfoAllCountriesResult" for tt.
create server hs.
hs:connect( "-WSDL http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL" ).
run CountryInfoServiceSoapType set hp on server hs.
run FullCountryInfoAllCountries in hp ( output lcresponse ).
// message string( substring( lcresponse, 1, 30000 ).
dataset ds:read-xml( "longchar", lcresponse, ?, ?, ? ).
for each tt:
display tt.
end.
delete procedure hp.
hs:disconnect().
delete object hs.

Error - Cannot assign to value: function call returns immutable value

I'm doing an introductory iOS developer's course, and am doing a cat-years calculator as an exercise. The following code returns the error:
Int(AgeInCatYears.text!) = CatsROld!
Error - Cannot assign to value: function call returns immutable value
In case it's important, the var CatsROld was set equal to Int(humanYears.text!)! * 7 one line earlier.
Any advice?
If you are setting value to the Label or textField then you need to simply set value (as String) to its property text, but you are try to convert the value to Int and then you assigning value of CatsROld to it, that is the reason you are getting this error. So simply write like AgeInCatYears.text = "\(CatsROld!)"
AgeInCatYears.text = "\(CatsROld!)"
Note: You are force wrapping CatsROld value with !, if you are 100% sure that it will not nil then its ok other wise you need to use if let or guard for optional wrapping.

Exception handling in PostgreSQL function with Django

have write the following store procedure in Postgres. This SP simply accept the incoming parameters, insert it into the table and return current identity. More I have also declare an addition variable that will tell is the sp runs successfully or not.
I am new to Postgres and have not much knowledge about Postgres way to do this. I want some thing like BEGIN TRY, END TRY and BEGIN CATCH, END CATCH like we do in MSSQL.
CREATE OR REPLACE FUNCTION usp_save_message(msg_sub character varying(80), msg_content text, msg_type character(12), msg_category character(255),msg_created_by character(255),msg_updated_by character(255))
RETURNS msg_id character, success boolean AS
$BODY$
DECLARE
msg_id character;
success boolean;
BEGIN
BEGIN TRY:
set success = 0
set msg_id = INSERT INTO tbl_messages(
message_subject, message_content, message_type, message_category,
created_on, created_by, updated_on, updated_by)
VALUES (msg_sub, msg_cont, msg_type,msg_category, LOCALTIMESTAMP,
msg_created_by, LOCALTIMESTAMP, msg_updated_by) RETURNING message_id;
set success = 1
RETURN msg_id,success;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
I want something like this:
begin proc()
BEGIN
BEGIN TRY:
set success = 0
execute the query
set success = 1
END TRY
BEGIN CATCH:
set success = 0
END CATCH
set success = 1
END
More I have to catched both these return values in django views.
I have updated the question and it is as now;
Here is the table,
CREATE TABLE tbl_messages
(
message_subject character varying(80),
message_content text,
message_type character(12),
message_category character(255),
created_on timestamp without time zone,
created_by character(255),
updated_on timestamp without time zone,
updated_by character(255),
message_id serial NOT NULL,
CONSTRAINT tbl_messages_pkey PRIMARY KEY (message_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE tbl_messages
OWNER TO gljsxdlvpgfvui;
Here is the function i created;
CREATE FUNCTION fn_save_message(IN msg_sub character varying, IN msg_cont text, IN msg_type character varying, IN msg_category character varying, IN msg_created_by character varying, IN msg_updated_by character varying, OUT success boolean, OUT msg_id integer) RETURNS integer AS
$BODY$BEGIN
BEGIN
INSERT INTO tbl_messages
(message_subject, message_content, message_type, message_category,
created_on, created_by, updated_on, updated_by)
VALUES
(msg_sub, msg_cont, msg_type, msg_category, LOCALTIMESTAMP,
msg_created_by, LOCALTIMESTAMP, msg_updated_by)
returning message_id
into msg_id;
success := true;
EXCEPTION
WHEN others then
success := false;
msg_id := null;
END;
return msg_id,success;
END;$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF
COST 100;
ALTER FUNCTION public.fn_save_message(IN character varying, IN text, IN character varying, IN character varying, IN character varying, IN character varying)
OWNER TO gljsxdlvpgfvui;
But it is not still working... i don't know what id have done wrong now, any django/postgres expert here kindly help me out.
There are several problems with your function:
Statements need to be terminated with a ; - always
Variable assignments are done using := (see: http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-ASSIGNMENT)
You can't return more than one value from a function (unless you create a set returning function, return an object or use out parameters)
Boolean values are true or false. Not 0 or 1 (those are numbers)
The result of an automatically generated ID value is better obtained using lastval() or `` INSERT ... RETURNING expressions INTO ...not through aSET` statement.
Exception handling is done using the exception clause as documented in the manual
So you need something like this:
DECLARE
....
BEGIN
BEGIN
INSERT INTO tbl_messages
(message_subject, message_content, message_type, message_category,
created_on, created_by, updated_on, updated_by)
VALUES
(msg_sub, msg_cont, msg_type,msg_category, LOCALTIMESTAMP,
msg_created_by, LOCALTIMESTAMP, msg_updated_by)
returning message_id
into msg_id;
success := true;
EXCEPTION
WHEN others then
success := false;
msg_id := null;
END;
return msg_id;
END;
But as I said: you can't return more than one value from a function. The only way to do this is to declare OUT parameters, but personally I find them a bit hard to handle in SQL clients.
You have the following options to report an error to the caller:
let the caller handle the exception/error that might arise (which is what I prefer)
define a new user defined data type that contains the message_id and the success flag and return that (but that means you lose the error message!)
return a NULL for the message_id to indicate that something went wrong (but that also means you lose the error information)
Use out parameters to pass both values. An example is available in the manual: http://www.postgresql.org/docs/current/static/xfunc-sql.html#XFUNC-OUTPUT-PARAMETERS
CREATE FUNCTION fn_save_message3(IN msg_sub character varying, IN msg_cont text, IN msg_type character varying, IN msg_category character varying, IN msg_created_by character varying, IN msg_updated_by character varying) RETURNS integer AS
$BODY$ DECLARE msg_id integer := 0;
BEGIN
INSERT INTO tbl_messages
(message_subject, message_content, message_type, message_category,
created_on, created_by, updated_on, updated_by)
VALUES
(msg_sub, msg_cont, msg_type, msg_category, LOCALTIMESTAMP,
msg_created_by, LOCALTIMESTAMP, msg_updated_by);
Select into msg_id currval('tbl_messages_message_id_seq');
return msg_id;
END;$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF
COST 100;
ALTER FUNCTION public.fn_save_message(IN character varying, IN text, IN character varying, IN character varying, IN character varying, IN character varying)
OWNER TO gljsxdlvpgfvui;
SELECT fn_save_message3('Test','fjaksdjflksadjflas','email','news','taqi#gmail.com','');