Showing posts with label OSB11g. Show all posts
Showing posts with label OSB11g. Show all posts

Wednesday, September 25, 2013

BPEL calling web services with http basic authentication+authotrization.



Recently my team had an issue where they are easily able to connect to a third party web service protected with basic authentication from SOAP UI and from OSB business service, but not from BPEL-SOA.

Whenever the service is invoked, it throws authorization error.
bpelFault><faultType>0</faultType><remoteFault xmlns="http://schemas.oracle.com/bpel/extension"><part name="summary"><summary>oracle.fabric.common.FabricException: oracle.fabric.common.FabricException: Error in getting XML input stream: https://xxxxxxx.com/incident.do?wsdl: Response: '401: Unauthorized' for url: 'https://xxxxxxx.com/incident.do?wsdl': Error in getting XML input stream: https://xxxxxxx.com/incident.do?wsdl: Response: '401: Unauthorized' for url: 'https://xxxxxxx.com/incident.do?wsdl'</summary></part><part name="detail"><detail>Response: '401: Unauthorized' for url: 'https://xxxxxxx.com/incident.do?wsdl'</detail></part></remoteFault></bpelFault>
OSB
In OSB you can create service account and in the business service add a service account which will have the service account username and password. It will work.


BPEL
In composite.xml , couple of options that were tried . The oracle.webservices.auth usually works, but in this scenario it was failing.
      <property name="oracle.webservices.auth.password" type="xs:string" many="false"> geotho </property>
      <property name="oracle.webservices.auth.username"  type="xs:string" many="false">xxxxx </property>    
or
 The below option doesn’t look like it’s supported.
      <property name="httpBasicPassword"   type="xs:string" many="false"> geotho </property>
      <property name="httpBasicUsername" type="xs:string" many="false">xxxxx </property>

Solution
But the option that worked was to set the javax.xml.ws.security.auth parameters in composite.xml for the reference.
  <property  name="oracle.webservices.preemptiveBasicAuth"  many="false"  override="may">true</property>
<property  name="javax.xml.ws.security.auth.username"  many="false"  override="may"> geotho</property>
  <property  name="javax.xml.ws.security.auth.password"  many="false"  override="may"> xxxxxxxx</property>
 <property  name="weblogic.wsee.wsat.transaction.version"  type="xs:string"  many="false">DEFAULT</property>


Eg implementation:-
 <reference name="ExternalService" ui:wsdlLocation=" ExternalService.wsdl">
    <interface.wsdl interface="http://www.geo.com#wsdl.interface(ExternalService Soap)"/>
    <binding.ws port="http://www.geo.com#wsdl.endpoint(ExternalService _incident/ExternalServiceSoap)"
                location=" ExternalService.wsdl" soapVersion="1.1">
      <property name="weblogic.wsee.wsat.transaction.flowOption" type="xs:string" many="false">WSDLDriven</property>
      <property  name="oracle.webservices.preemptiveBasicAuth"  many="false"  override="may">true</property>
      <property  name="javax.xml.ws.security.auth.username"  many="false"  override="may">geotho</property>
      <property  name="javax.xml.ws.security.auth.password"  many="false"  override="may">xxxxxxx</property>
      <property  name="weblogic.wsee.wsat.transaction.version"  type="xs:string"  many="false">DEFAULT</property>
    </binding.ws>
  </reference>

This will set the values in HTTP AUTH in soa composite reference .


Hope it helps J

Friday, August 9, 2013

Modelling osb error handling for synchronous services


Recently one of the queries I got was regarding the OSB error handling, how errors should be handled. The error handling will differ based on the communication pattern, whether the call is synchronous or asynchronous.
If the services are modeled to be synchronous it will be always useful to return a consistent error structure with a minimum of the error occurring service information, unique id w.r.t message so as to track it, unique error code, summary/details of the error. This needs to be defined properly and laid out before we start on a project. If the services are more asynchronous in nature, then it makes sense to have a common Error logging/handling/auditing framework which will receive the errors and based on any business rules can persist /notify the errors. In both approaches it is mandatory to define the Error message structure. The asynchronous can have more information whereas synchronous can be a subset of this since the caller or consumer need not be given a lot of unnecessary information related to error. The synchronous response should be more formatted to be humanly readable and no stack trace.
  In case of OSB there can be multiple proxies and you will need to control the response message flow and track it. Instead of having multiple reply points from error catch blocks it will be better to have multiple catch blocks which will Raise an Error with the error payload populated into the body. The Global catch block will do a reply with success to the caller Proxy with the body


OSB Implementation
The different stages in OSB should be segregated and defined properly. And each stage should be having Error Handler-catch block. In each catch block

Catch the error globally and Reply with success
An error should contain minimum of below listed information so that it helps in identifying/tracking the error.
ResponseStatus: "-1"
ErrorSource: Atomic service
MessageDate: "2013-08-08T15:48:13.013-07:00",
ServiceName: "Validation Service",
OperationName: ": validateRequest",
Code: "VALIDATION_ERROR-ERR103",
Summary: "Validation Failure ",
Details: "BEA-382515: oops!!! Duplicate Request Signature",
SeverityLevel: "1"

If we are having a Gateway architecture then we can evaluate the error response at the gateway, see the error code and based on that can work out appropriate error handling mechanisms.

Thursday, July 18, 2013

Behavior of OSB response Content-Type based on Request-Response message types/Trasport-Header



While designing a single proxy service which will return different formats- say for example json and xml, the response Content-Type plays a big role in browsers or consumer systems understanding the return structure. If the consumer receives the content –type populated as application/json then it can have the json parser interpret the data and if the response content-type is populated as application/xml , then consumer can have the xml parser in action.
For this test I choose the proxy service which has Request-Response message type as text, as the response can vary based on underlying service, as well as consumer requirement. When you design you need to support all the formats, so selecting TEXT type will be the best option.
The issue here is that response content-type will be text/plain by default. The solution is to have a Transport-Header which will overwrite the Content-Type as required. You can do it this way or have the Content-Type copied from the response header if underlying service has set it properly.

Proxy response - no transport header set
Response Metadata      
  -- Default behavior of the proxy
  
<con:metadata     xmlns:con="http://www.bea.com/wli/sb/test/config">
          <tran:headers            xsi:type="http:HttpResponseHeaders" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:tran="http://www.bea.com/wli/sb/transports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <http:Content-Type>text/plain; charset=utf-8</http:Content-Type>
                </tran:headers>
                <tran:response-code          xmlns:tran="http://www.bea.com/wli/sb/transports">0</tran:response-code>
                <tran:encoding    xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
</con:metadata>

Proxy response -transport header is set
 Response Metadata     
<con:metadata     xmlns:con="http://www.bea.com/wli/sb/test/config">
                <tran:headers      xsi:type="http:HttpResponseHeaders" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:tran="http://www.bea.com/wli/sb/transports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <http:Content-Type>application/json; charset=utf-8</http:Content-Type>
                </tran:headers>
                <tran:response-code          xmlns:tran="http://www.bea.com/wli/sb/transports">0</tran:response-code>
                <tran:encoding    xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
</con:metadata>



Wednesday, June 19, 2013

OSB Reporting using Report action (OSB Reporting/Analytics –Part2)



              The Reporting Service will be one of the framework services within SOA environment. The Reporting Service will be a generic service which will listen to Reporting queue of OSB, log or record transaction or exception data, or to raise a notification or alert to an end user or technical
Support group.
How to build a custom Reporting handler has been explained in detail in Zoggel’s blog

        The options are useful in case you have custom OSB Reporting Data Handler (Reporting Service) which will be listening to the OSB JMS Provider QUEUE. OSB will perform reporting using the OSB JMS Provider QUEUE and message payload will contain ReportData and ReportMetadata. These variables can be XML elements or Strings. These will need to be retrieved in the custom OSB reporting handler and processed further.

I will mention 2 approaches for logging/processing of report data
1.         You can report all the parameters separately as key-value pair
         
The Report Metadata will contain all the key-value pairs in side labels tag.
<ReportMetadata = <rep:messagecontext xmlns:rep="http://www.bea.com/wli/reporting"><rep:content-encoding>iso-8859-1</rep:content-encoding><rep:labels>QUERYSTRING=id=100;PROJECT_NAME=GEOTEST;;MODULE_NAME=HR;SERVICE_NAME=searchById;CORRELATION_ID=sdsadad123213123asdasd;START_TIME;SERVICE_TYPE;HTTP_METHOD</rep:labels><rep:inbound-endpoint name="ProxyService$GEOGateway$REST$v1$GEORestfulGateway"><rep:service/><rep:transport><rep:uri>/geo_services/GEOBus/GEOGateway/REST/v1/GEORestfulGateway</rep:uri><rep:mode>request-response</rep:mode><rep:qualityOfService>best-effort</rep:qualityOfService></rep:transport></rep:inbound-endpoint><rep:origin><rep:state>REQUEST</rep:state><rep:node>GatewayPipeline</rep:node><rep:pipeline>GatewayPipeline_request</rep:pipeline><rep:stage>CheckRegistryStage</rep:stage></rep:origin><rep:timestamp>2013-05-30T18:19:08.086-07:00</rep:timestamp></rep:messagecontext>>
2.       You will need to write an Xquery to populate the variable with the REPORT_DATA data structure.

Code snippet of Xquery
declare function xf:PopulateReportData($inbound as element(*))
    as element(ns0:REPORT_DATA) {
         <ns0:REPORT_DATA>
             <ns0:PROJECT_NAME>GEO</ns0:PROJECT_NAME>
            <ns0:MODULE_NAME>{substring-before(data($inbound/ctx:transport/ctx:request/http:relative-URI),"/")}</ns0:MODULE_NAME>
            <ns0:SERVICE_NAME>{substring-after(data($inbound/ctx:transport/ctx:request/http:relative-URI),"/") }</ns0:SERVICE_NAME>
            <ns0:SERVICE_TYPE>REST</ns0:SERVICE_TYPE>
            <ns0:HTTP_METHOD>{data($inbound/ctx:transport/ctx:request/http:http-method)}</ns0:HTTP_METHOD>
            <ns0:USER_NAME>{xf:GetHttpQueryParameter($inbound/ctx:transport/ctx:request/http:query-string/text(),'geo-username')}</ns0:USER_NAME>
            <ns0:USER_ID>{xf:GetHttpQueryParameter($inbound/ctx:transport/ctx:request/http:query-string/text(),'geo-userid')}</ns0:USER_ID>
            <ns0:START_TIME>{fn:current-dateTime()}</ns0:START_TIME>
            <ns0:SYSTEM_ID>{xf:GetHttpQueryParameter($inbound/ctx:transport/ctx:request/http:query-string/text(),'geo-key-id')}</ns0:SYSTEM_ID>
            <ns0:CORRELATION_ID>{fn-bea:uuid()}</ns0:CORRELATION_ID>
            <ns0:MSG_ID>{fn-bea:uuid()}</ns0:MSG_ID>
            <ns0:QUERYSTRING>{$inbound/ctx:transport/ctx:request/http:query-string/text() }</ns0:QUERYSTRING>
            <ns0:STATUS>REQUEST_RECIEVED</ns0:STATUS>
             <ns0:PROCESS_FLOW_STAGE>REQUEST</ns0:PROCESS_FLOW_STAGE>
          </ns0:REPORT_DATA>
};

In this case ReportData will contain the payload in XML format.
Report Data
<head:REPORT_DATA xmlns:head="http://geo.com/report/header"><head:PROJECT_NAME>GEO</head:PROJECT_NAME><head:MODULE_NAME>Employee</head:MODULE_NAME><head:SERVICE_NAME>RequestEmployeeId</head:SERVICE_NAME><head:SERVICE_TYPE>REST</head:SERVICE_TYPE><head:HTTP_METHOD>GET</head:HTTP_METHOD><head:USER_NAME>george</head:USER_NAME><head:USER_ID>geo123</head:USER_ID><head:START_TIME>2013-05-30T18:19:08.080-07:00</head:START_TIME><head:SYSTEM_ID>DAD</head:SYSTEM_ID><head:CORRELATION_ID>d10e6395-da61-44cf-b004-a4b0360bf965</head:CORRELATION_ID><head:MSG_ID>e52c1b84-4da9-4134-9c5f5ccd7bb8778</head:MSG_ID><head:QUERYSTRING><![CDATA[requesterFirstName=George&requesterLastName=Thomas&requesterEmail=george.Thomas@geo.com&userID=geo]]></head:QUERYSTRING><head:STATUS>SUCCESS</head:STATUS></head:REPORT_DATA>


References :