Wednesday, February 3, 2010

Calling Hello World Webservice from Oracle 10 database



I got a problem where I was required to invoke a web service from Oracle database itself. From the net, I got multiple samples of code to do so using the UTL_HTTP package. The problem none worked for me. So I started from scratch :

  1. Created a HelloWorld web service in .NET 3.5 (VS 2008 SP1).

  2. Checked the service using the Internet Explorer browser. You should see a page similar to one below when you access the url http://localhost/myWeb/testws/Service.asmx?op=HelloWorld (the location of your service may be different):

  3. After lot of time spent on the internet, I found Oracle uses SOAP 1.1 to make web service calls. So look specifically in to the SOAP 1.1 Request format displayed on the browser.


  4. So now lets come to code:

    declare
    http_req utl_http.req;
    http_resp utl_http.resp;
    request_env varchar2(32767);
    response_env varchar2(32767);
    begin

    request_env:='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
    <HelloWorld xmlns="http://tempuri.org/" />
    </soap:Body>
    </soap:Envelope>'

    dbms_output.put_line('Length of Request:' length(request_env));
    dbms_output.put_line ('Request: ' request_env);

    http_req := utl_http.begin_request('http://<your_url>/myWeb/testws/Service.asmx', 'POST', 'HTTP/1.1');
    utl_http.set_header(http_req, 'User-Agent', 'Mozilla/4.0');
    utl_http.set_header(http_req, 'Content-Type', 'text/xml');
    utl_http.set_header(http_req, 'Content-Length', length(request_env));
    utl_http.set_header(http_req, 'SOAPAction', '"http://tempuri.org/HelloWorld"');
    utl_http.write_text(http_req, request_env);

    http_resp := utl_http.get_response(http_req);
    utl_http.read_text(http_resp, response_env);
    utl_http.end_response(http_resp);

    dbms_output.put_line('Response Received');
    dbms_output.put_line('--------------------------');
    dbms_output.put_line ( 'Status code: ' http_resp.status_code );
    dbms_output.put_line ( 'Reason phrase: ' http_resp.reason_phrase );

    dbms_output.put_line('Response: ');
    dbms_output.put_line(response_env);

    EXCEPTION WHEN UTL_HTTP.end_of_body THEN
    utl_http.end_response(http_resp);
    END;


  5. Lets got through the code step by step:


  6. Declare some variables:

    declare
    http_req utl_http.req;
    http_resp utl_http.resp;
    request_env varchar2(32767);
    response_env varchar2(32767);
    begin


  7. Create the SOAP request. It should exactly match what is displayed on the browser. Currenly I am not passing any input parameter to the service but if you need to, just copy paste the SOAP request from the browser and replace the placeholders mentioned in there with actual values.

    request_env:='<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
    <HelloWorld xmlns="http://tempuri.org/" />
    </soap:Body>
    </soap:Envelope>';
    dbms_output.put_line('Length of Request:' length(request_env));
    dbms_output.put_line ('Request: ' request_env);

    Just some debug statements at end to check all is set correctly.


  8. Set the HTTP Request Parameters. The parameters should match the 1st statement displayed in your browser. The only difference is that the browser displays it in 2 statements : 1st with POST and second with a "Host" Soap Header Tag. For web service calls we will include the "Host" in the url itself.

    http_req := utl_http.begin_request('http://<your_url>/myWeb/testws/Service.asmx', 'POST', 'HTTP/1.1');

    Note: Please remember that your web service is on your localhost but the Oracle database is most likely not in your localhost but in some remote server. For the database server, your webservice hosted on your machine is a remote server so use the IP or hostname of your machine instead of "localhost" (spent a lot of time just solving this small issue ;)).


  9. Set the Content-Type as 'text/xml' as displayed in the browser. You can set the charset too but I did not find it mandatory, so skipping it.

    utl_http.set_header(http_req, 'Content-Type', 'text/xml');


  10. Set the Content-Length to length of the SOAP request. Luckily the length() function of Oracle does that for you. If you check in the Browser, it marks 'length' as a placeholder to be replaced by the actual value when the request is sent. So in Oracle we do so using the length function.

    utl_http.set_header(http_req, 'Content-Length', length(request_env));


  11. Set the 'SOAPAction' field in your SOAP header. This is the namespace of your method appended by the actual method name (operation name). Currently its displayed on your browser. To find it out, you can open the WSDL for your service and browse to the end of the file. In there you will notice:

    - <wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
    - <wsdl:operation name="HelloWorld">
    <soap:operation soapAction="http://tempuri.org/HelloWorld" style="document" />

    Thats where the soapAction is set.

    utl_http.set_header(http_req, 'SOAPAction', '"http://tempuri.org/HelloWorld"');


  12. After setting all the SOAP Headers correctly, now write the SOAP Body for the request. As we have already written it in our 1st step, its just a copy paste function.utl_http.write_text(http_req, request_env);


  13. No request the response and read it. Finally close the http connection. I have received the response which is a UTL_HTTP Response object with all the XML DOM defined and with a lot of other functionality available to manipulate the object. To keep things simple, I have actually read the repose to a varchar object 'response_env'.

    http_resp := utl_http.get_response(http_req);
    utl_http.read_text(http_resp, response_env);
    utl_http.end_response(http_resp);


  14. Thereafter all statements are just to print out the response to the DBMS Output.


  15. I have also caught the HTTP end of reponse exception just in case something goes wrong and closed the connection.

Hope this small piece of code helps you out in your first web service call from Oracle. Gradually you can use a lot of good code available on the internet to form your request and parse the response.

Friday, January 22, 2010

Qwest @ Facebook

Update: Got an unique url for it : https://www.facebook.com/QwestQ
Could not Qwest : FB does not specify any rule for it but looks like its for sale only.
-------------------------------------
Recently am developing a Facebook app for Qwest. Got something going at

http://www.facebook.com/pages/Qwest/261042222880.

Looks good, isn't it.

Wednesday, September 9, 2009

Install Microsoft.mshtml on client machines using ClickOnce

I had recently published an application using ClickOnce which used MS Office Primary Interop Assemblies. When a user tried to install it, he got an error :

MSHTML Error

I was surprise at first as I was not at all using Microsoft.mshtml in my application. As it turned out, the PIA's refer to this dll internally. As I have Visual Studion installed in my workstation, the Microsoft.mshtml had got added to my GAC and the appliaction worked fine on my workstation. People who have not installed Visual Studio or .NET Framework SDK dont have it in there GAC hence the error. Now that I found the problem, I had to find a solution.

Tried to force users to install .NET Framework SDK by setting it as Prerequisite in ClickOnce (under Publish -> PreRequisite) solved the issue but it does not make much sense to ask users to download a 350+ MB package and install it just to get a dll. There has to be a easy way out.

So I started thinking of alternatives. Any application looks for dlls in GAC only after it has looked in to the current directory. The solution was to push Microsoft.mshtml.dll in to the bin directory.
By default if you go to Project Properties -> Publish -> Application Files you will see something like :

app files

Clickonce correctly identifies Microsoft.mshtml.dll as a prerequisite but has marked "None" as the dowload group i.e. it does not get downloaded to the user's machine. To enable it going in to the user's machine, you can just mark the Publish Status of the dll to "Include (Auto)" . You will see the download group automatically being changed to "(Required)". Now publish it.
Clickonce will now identify the dll as a required download dll so will download it to the user's workstation. While installation, the Interop dll's will find Microsoft.mshtml.dll in their current directory hence will no longer look in to GAC for the dll and the install will go on smoothly.

And this is a cheaper a better solution too.

Saturday, August 1, 2009

USB Mass Storage Issues - v2

In an earlier post USB Mass Storage Issues I talked about uninstalling MS Windows drivers and installing Intel drivers.
Today I found the issues again and found that my drives are too old. To check for your drivers check the Intel site : http://www.intel.com/support/graphics/detect.htm . Please get the latest Intel drivers and install them. Post install you should have the latest chipset drivers and you USB should be working fine.

P.S: Ealier I preferred Intel over MS drivers. Therafter I read more documentation at the Intel site and found that Intel is supporting USB driver updates from Windows update site. So for latest drivers you can get it from MS Windows update site too. Still check for the latest updates at the Intel site too.

Friday, July 24, 2009

Virtual Provider Error

Recently I faced a Virtual Provider issue on which I spent considerable amount of time but to no avail. The issue is reported multiple times in google and also in Microsoft Bug 307978 and is even marked as closed but it still comes up.
The error message is:

The VirtualPathProvider returned a VirtualFile object with VirtualPath set to '/MasterPageDir/SharedMasterPage.master.cs' instead of the expected '//MasterPageDir/SharedMasterPage.master.cs'.

All the posts mentioned that its a compilation error but how to find it out. I tried a lot of code but did not help. So the solution is:
Use EventViewer. Under Application the error will be logged as a ASP .NET 2.0 error. Looking at the details you can figure out the details of the compilation issue. :)

Saturday, May 16, 2009

How to work better

Was reading in the net and found this usefule advice:
  1. Do one thing at a time.
  2. Know the problem.
  3. Learn to listen.
  4. Learn to ask questions.
  5. Distinguish sense from nonsense.
  6. Access change is inevitable.
  7. Admit mistakes.
  8. Say it simple.
  9. Be calm.
  10. Smile :)

Friday, May 8, 2009

Enable Upload of Documents in Dokuwiki

Recently I installed Dokuwiki on IIS as the wiki for my team and projects.
The installation went on fine but it did not allow upload of images, documents, pdfs etc.

Looking through the internet I was able to find the solution step by step.
So I have consolidated all in here:


  1. I have my wiki installed at C:\Inetpub\wwwroot\wiki. I created an upload folder to allow php engine to write files in there. I got in created at C:\Inetpub\wwwroot\wiki\uploads and gave Domain\Users , Internet Guest Account and Launch IIS Process Account "Full Control" over the folder. This allows IIS worker process to write files to the folder.

  2. I have my php installed at C:\PHP. Open the C:\PHP\php.ini file and make the following changes:

    1. Look for the config param "open_basedir" and set it to wiki base directory.

      open_basedir = "C:\Inetpub\wwwroot\wiki"

    2. Look for the config param "upload_tmp_dir" and set it to the Uploads directory created in Step 1.

      upload_tmp_dir="C:\Inetpub\wwwroot\wiki\uploads"

    3. You may also want to set the maximum file size that can be uploaded. Look for the config params "post_max_size" and "upload_max_filesize" and set it to the required file size.

      post_max_size = 20M
      upload_max_filesize = 20M

    4. Just confirm one more thing i.e. the config param "file_uploads". It should be set to ON.

      file_uploads = On

    5. You may also want to set the mail setting for php application under the "[mail function]" section. You will need to set the config params "SMTP" (SMTP server), "smtp_port" and "sendmail_from".

  3. This should set you up and you should be able to upload to your dokuwiki.

Happy wiki'ing.