Exception HTTP/1.1 400 Bad Request with Indy TidHttp - dll

I have a main application which calls a DLL. This DLL is where I do my HTTP requests using Indy's TIdHTTP component. It runs fine the first time, but then after closing the DLL and re-opening it, I get an HTTP/1.1 400 Bad Request exception:
var
idgetInfo : TIdHTTP;
begin
idgetInfo := TIdHTTP.Create(nil);
idgetInfo.AllowCookies := True;
idgetInfo.HandleRedirects := True;
try
result := idgetInfo.Get(GetString);
finally
if Assigned(idgetInfo) then
FreeAndNil(idgetInfo);
end;
end;

Related

Should I outsource my database connection in delphi?

My program keeps making new requests to a database while it's running. Now, I am wondering if I should outsource my database connection, since it always creates a new one for a new query and destroys it afterwards.
function TMainMenu.btnInsertPersonClick(Sender: TObject)
var
vDatabase : TADOConnection;
vQuery : TADOQuery;
begin
vDatabase := TADOConnection.Create(self);
vQuery := TADOQuery.Create(self);
try
vDatabase.ConnectionString := 'SECRET_STRING';
vQuery.Connection := vDatabase;
// DO QUERY STUFF HERE
finally
vDatabase.Close;
vQuery.Destroy;
vDatabase.Destroy;
end;
end;
Maybe it's not a good idea to outsource the connection. That's why I am happy about any help or suggestions. Sheers!

Database logging in logging procedure

Perhaps a silly question, but say I have a logging procedure like so (greatly simplified for brevity):
PROCEDURE LOGGER (
p_TYPEOFLOG IN VARCHAR2,
p_LOGSEVERITY IN VARCHAR2,
p_SESSIONID IN VARCHAR2)
AS
v_timestamp DATE := SYSDATE;
BEGIN
PRAGMA autonomous_transaction;
BEGIN
INSERT INTO Log (
TypeOfLog, LogSeverity, SessionID, TimeOfAction)
VALUES (
p_TYPEOFLOG, p_LOGSEVERITY, p_SESSIONID, v_timestamp);
COMMIT;
END;
END LOGGER;
Now, usually I would wrap the begin/end bit up with an exception handler, which would call this logger procedure. But what do I do if I'm already in the Logger? Do I simply do an exception if when others null and skip it? Do I try calling the Logger procedure again? What is standard here?
I don't believe that there is such a thing as "standard".
Personally, if my logging code failed, I'd let whatever exception was generated be thrown and propagate up the stack. If you can't write to the Log table, that implies that something terribly unfortunate has happened. I wouldn't want to catch and ignore such an exception. And given no other way to log the error, I'd raise the exception back to the caller and expect the caller to either display the message to a user (i.e. a stack trace in the front end web app) or to log the message to an application server log.

Fire a trigger before inserting or updating the table, convert into JSON format and post the same on a URL

I have a requirement in which I need to update the existing records with new values/insert the new records by converting the data into JSON via Oracle backend(pl/sql). These JSON values need to be posted on URL.I am able to post sample values on the URL via Oracle but before updating/inserting any new values, It throws a mutating error in the trigger when I try to read the table..Can you please post some sample code for this?
Thanks in advance
CREATE OR REPLACE TRIGGER get_employees_trig before
INSERT ON emp_table REFERENCING OLD AS OLD NEW AS NEW FOR EACH
ROW DECLARE V_RET VARCHAR2(100);
BEGIN
dbms_output.put_line('fired-0');
IF :NEW.id <>:OLD.id THEN
V_RET := post_json_data_fnc(:NEW.id);
dbms_output.put_line('fired-1');
END IF;
dbms_output.put_line('fired-2');
END;
create or replace FUNCTION post_json_data_fnc(
p_id IN NUMBER)
RETURN CLOB
IS
req utl_http.req;
res utl_http.resp;
url varchar2(200);
l_clob CLOB;
l_xml CLOB;
l_txt CLOB;
--content varchar2(4000) := '{"name":"u14", "pass": "123","mail": "user#a.om"}';
BEGIN
URL := 'http://10.54.8.210:9200/temp/20';
l_xml := json_util_pkg.ref_cursor_to_json (emp_spec.get_employees(p_id));
req := utl_http.begin_request(URL, 'POST',' HTTP/1.1');
utl_http.set_header(req, 'user-agent', 'mozilla/4.0');
utl_http.set_header(req, 'content-type', 'application/json');
utl_http.set_header(req, 'Content-Length', LENGTH(l_xml));
l_txt := l_xml;
utl_http.write_text(req, l_txt);
res := utl_http.get_response(req);
utl_http.read_text(res,l_txt);
UTL_HTTP.END_RESPONSE(res);
dbms_output.put_line(l_txt);
return l_txt;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(res);
END;
create or replace FUNCTION post_json_data_fnc(
p_id IN NUMBER)
RETURN CLOB
IS
req utl_http.req;
res utl_http.resp;
url varchar2(200);
l_clob CLOB;
l_xml CLOB;
l_txt CLOB;
BEGIN
URL := 'http';
l_xml := json_util_pkg.ref_cursor_to_json (emp_spec.get_employees(p_id));
req := utl_http.begin_request(URL, 'POST',' HTTP/1.1');
utl_http.set_header(req, 'user-agent', 'mozilla/4.0');
utl_http.set_header(req, 'content-type', 'application/json');
utl_http.set_header(req, 'Content-Length', LENGTH(l_xml));
l_txt := l_xml;
utl_http.write_text(req, l_txt);
res := utl_http.get_response(req);
utl_http.read_text(res,l_txt);
UTL_HTTP.END_RESPONSE(res);
dbms_output.put_line(l_txt);
return l_txt;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(res);
END;
First, the mutating table exception is being thrown because you cannot in general query the table on which a row-level trigger is defined (emp_table in this case) from within the trigger or within code called by that trigger. My assumption is that something in the json_util_pkg.ref_cursor_to_json (emp_spec.get_employees(p_id)) call is querying emp_table. If you really, really wanted to do this from within a row-level trigger, you would need to remove any code that queries emp_table and recreate it using just the :new and :old pseudorecords.
However, you almost certainly don't want to do this or anything non-transactional in a trigger. What happens, for example, if your transaction is rolled back? Do you really want to have passed values to the web service that never actually existed in the table? What happens if Oracle does a partial or complete rollback and then re-executes the transaction for write consistency? Is your web service going to have a problem if you pass in duplicate data? In addition, do you really want to tie the availability of your system to the availability of the web service? So if the web server is down for a couple minutes, transactions on emp_table would fail?
It would make drastically more sense architecturally to build an asynchronous process. In the simplest case, you'd insert the primary key from emp_table into a separate table like emp_rows_to_be_processed. A background job (presumably using dbms_scheduler) would then periodically read that table, assemble the JSON, call the service, and then delete the row from emp_rows_to_be_processed. That allows the database to continue functioning if the web service is down briefly. The background job will only see rows that were actually committed. It won't see duplicates. And it doesn't have any problems with mutating tables.

Getting TNS :Connect timeout occurred in Oracle

I have the below function and I am quite frequently getting the below errors when front end ( ADF ) calls this function to get count.
Different errors comes at different times.
I think sometimes the listener is down so it might occur but other errors ?It happens when user from front end click on the link and that link in turn calls this database function.
I'm not able to find the issue in the function :-(
1) error "-12170 : ORA-12170: TNS:Connect timeout occurred"
2) error "-12571 : ORA-12571: TNS:packet writer failure"
3) error "-12541 : ORA-12541: TNS:no listener
4) error "-12514 : ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
5) error "-3113 : ORA-03113: end-of-file on communication channel
ORA-02063: preceding line from DBLINK"
6) error "-2051 : ORA-02051: another session or branch in same transaction failed or finalized
ORA-02063: preceding line from DBLINK"
FUNCTION GET_A (p_in IN VARCHAR2) RETURN NUMBER
AS
PRAGMA AUTONOMOUS_TRANSACTION;
PRE_COUNT NUMBER := NULL;
BEGIN
SELECT GET_B#DBLINK (p_in,NULL)INTO PRE_COUNT FROM dual;
COMMIT;
-- dbms_lock.sleep(2);
DBMS_SESSION.CLOSE_DATABASE_LINK('DBLINK');
COMMIT;
RETURN PRE_COUNT;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
LOG_ERR ( p_cd => SQLCODE,p_msg => SQLERRM);
RETURN -1;
END GET_A;

Consuming WCF service from Oracle

TLDR; look at last paragrap.
A developer from our partner software company needs to call our WCF (basic http binding) service, and he asked us to turn it to asmx for themselves, cause he has trouble with calling it from Oracle. WCF service is being used on different platforms (.net, java, php) with no error.
His code gives him Status code: 500 - Internal Server Error. I assume its about sending wrong soap format or content.
So i learned you should use utl_dbws instead of utl_http as that developer did.
Ok, this seemed an easy task to me first. Find a working code sample from internet and send a e-mail like "Hi fellow developer friend you should use utl_dbws package not utl_http and the sample code at this link".
I'm not the only person in the world that needs to do this, right ?
Weird but i couldn't find any sample approved working piece of code that accomplishes calling a WCF service from Oracle.
Here is some of link i found about it;
https://forums.oracle.com/forums/thread.jspa?threadID=2354357
https://forums.oracle.com/forums/thread.jspa?threadID=1071996
http://steveracanovic.blogspot.com/2008/10/using-utldbws-package-to-call-web.html
https://forums.oracle.com/forums/thread.jspa?messageID=4205205&tstart=0#4205205
http://www.oracle-base.com/articles/10g/utl_dbws-10g.php
Noone writes any working code example or noone tells that this is not possible.
I would appreciate if anyone had a working code example that calling a WCF service from Oracle.
When you get a Http 500 error it is normally an internal error. For example that the developer is calling your service without setting all the input values, your code could then generate a divide by zero error, which when not caught is returned to the client as a http 500 error.
You can configure the soap version of a WCF service to be the same as an asmx service.
If you are getting response 500 (internal error) from WCF service, try set in web.config of WCF service includeexceptiondetailinfaults=true .
(http://msdn.microsoft.com/cs-cz/library/system.servicemodel.description.servicedebugbehavior.includeexceptiondetailinfaults(v=vs.110).aspx)
Then you will get detailed exception (wrong soap action, wrong format...)
Call WCF service from PL/SQL.
utl_http but it works.
/*
declare
p_request VARCHAR(32767);
p_plainResult VARCHAR2(32767);
begin
p_request := '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:Sum>
<tem:a>1</tem:a>
<tem:b>2</tem:b>
</tem:Sum>
</soapenv:Body>
</soapenv:Envelope>';
select callSOAPService(p_request,'http://tempuri.org/IMathService/Sum','http://localhost:51106/MathService.svc') into p_plainResult from dual;
end;
*/
create or replace function callSOAPService
(
p_plainRequest IN varchar2(20000),
p_actionName IN varchar2(1024), --SOAP Action ( in WCF, attribute [OperationContract(Action="ActionName")
p_url IN varchar2(1024),
p_userName varchar2(1024) := null,
p_password varchar2(1024) := null,
p_isAsynchronous boolean:= FALSE,
p_proxy varchar2(1024):=null,
p_transferTimeout number :=null,
)
RETURN VARCHAR2(32767)
IS
p_charset varchar2(1024) :='AL32UTF8'; --by default utf-8
p_request utl_http.req;
p_response utl_http.resp;
p_plainResponse varchar2(32767);
BEGIN
p_url := utl_url.escape(url => p_url); --escape url
if p_TransferTimeout > 0 THEN --set oracle timeout ( by defualt is 60 sec )
utl_http.set_transfer_timeout(timeout => p_transferTimeout);
END IF;
if p_proxy IS NOT NULL THEN --if proxy is provided, then set it
utl_http.set_proxy(proxy => p_proxy);
end if;
utl_http.set_response_error_check(enable => TRUE); --http status errorCheck ( 404 not found, 500 internal error...)
utl_http.set_detailed_excp_support(enable => TRUE); --detailed error stack
p_request := UTL_HTTP.begin_request(url => p_url,method => 'POST' /*u SOAP bude vzdy POST meotda*/ ,http_version => 'HTTP/1.1');
--pripravim si obalku
UTL_HTTP.set_header (r => p_request,name => 'Content-Type', value => 'text/xml');
UTL_HTTP.set_header (r => p_request,name => 'Content-Length',value => LENGTH (p_plainRequest));
UTL_HTTP.set_header (r => p_request, name => 'SOAPAction',value => p_actionName); --if status is 500 check SOAP action
UTL_HTTP.write_text(r => p_request,data => p_plainRequest);
p_response := UTL_HTTP.get_response (p_request);
if p_isAsynchronous THEN --one-way service
UTL_HTTP.end_response (p_response); --proto ukoncim request a vratim prazdno
RETURN '';
end if;
utl_http.read_text (p_response, p_plainResponse); --read response
utl_http.end_response (p_response); --close resposne
dbms_output.put_line ('Response from: ' || p_url || ' is ' || p_plainResponse); --vypisu odpoved pro kontrolu
return p_plainResponse;
EXCEPTION
when others then
dbms_output.put_line('Chyba ' || UTL_HTTP.get_detailed_sqlerrm()); --get error stack
utl_http.end_response (p_response);
END;