Showing posts with label SOAP. Show all posts
Showing posts with label SOAP. Show all posts

Friday, September 28, 2018

Working with an SOA MDS: using abstract WSDL's

The WSDL plays an essential role in defining a web service. Besides describing the structure of the SOAP message, it often contains additional implementation details about the location of the service by having the endpoint described in the service tag. This is what we call a concrete WSDL and it may look as follows:


When we populate our MDS we want it to contain abstract WSDL’s that do not contain these implementation details. This way we take away the direct dependencies between services. It means that the actual referenced services don’t need to be deployed and active in order for our SOA composite to be compiled. It also means we keep our MDS clean in the sense that it does not have any references to other environments.

The way of working with abstract WSDL’s in jDeveloper differs slightly compared to concrete WSDL’s. When creating a reference to a service, you would typically select the WSDL needed from the MDS, as below:


In contrary to using a concrete WSDL you will now get the following warning to notify you the WSDL doesn’t contain any bindings. This is perfectly fine and we can just continue by clicking ‘Yes’.


If you now check the composite.xml, you will notice that no binding details were provided in the binding.ws tag.


We need to provide them manually by looking up the concrete WSDL within the development environment. The format is as follows for the port details:
<Namespace service>#wsdl.endpoint(Service name/Port name)


In our case it becomes:
http://www.stellent.com/FolderInfo/#wsdl.endpoint(FolderInfo/FolderInfoSoap)

In the location attribute we provide the endpoint. Altogether your service reference should look like this:


When we create a deployment for installation on a different environment we will create a deployment plan which contains the endpoints of the target environment. This will overwrite the endpoint we provided in the location attribute of the composite.xml.

Wednesday, April 25, 2018

Error calling an external service from composite: oracle.fabric.common.FabricInvocationException: Unable to find the WSDL service defined for service name


I want to share an error that has kept me busy for a bit. I could not find the cause of the error easily, but as always with troubleshooting: afterwards it all made sense.

So I had an SOA composite calling an external service. Invoking this service resulted in the error below. This happened after deploying the service in my test environment.

      <bpelFault>
        <faultType>0</faultType>
         <remoteFault xmlns="http://schemas.oracle.com/bpel/extension">
           <part name="summary">
              <summary>oracle.fabric.common.FabricInvocationException: Unable to find the WSDL service defined for service name {http://www.stellent.com/GetCaseNumberWCC/}GetCaseNumberWCC.  Please make sure that the port attribute for the binding defined in the composite file is correct by checking the namespace and service name in the #wsdl.endpoint element. In addition, check that the WSDL associated with the binding namespace is imported and currently reachable (check the import nodes at the top of the composite file). Finally, validate any HTTP proxy settings for the server.</summary>
           </part>
            <part name="code">
              <code>null</code>
            </part>
           <part name="detail">
              <detail>Unable to find the WSDL service defined for service name {http://www.stellent.com/GetCaseNumberWCC/}GetCaseNumberWCC.  Please make sure that the port attribute for the binding defined in the composite file is correct by checking the namespace and service name in the #wsdl.endpoint element. In addition, check that the WSDL associated with the binding namespace is imported and currently reachable (check the import nodes at the top of the composite file). Finally, validate any HTTP proxy settings for the server.</detail>
           </part>
         </remoteFault>
       </bpelFault>

It didn’t make sense to me as the external service was up and running and I could call it from SoapUI. The endpoint looked good and I could view the WSDL in my browser. I checked my composite as the text in the exception suggested, but it looked fine and in accordance with my WSDL:



The SOA service worked fine in my development environment but failed in my test environment. It lead me to the configuration plan I generated using jDeveloper. In the reference part I changed the location to my test environment, the rest I had left untouched.



When I viewed the WSDL in my browser (http://tstenvironment:80/default/WCC/Services/GetCaseNumberWcc/V1?wsdl) I saw the following:



Apparently the service and port names were different in OSB, so it made sense that the port attribute wasn’t updated correctly in the configuration plan. This caused the invocation of the service to throw an error about the service name. I corrected the configuration plan (see yellow underlined text), redeployed the composite and it resolved my problem!





In my case the error was caused by a wrong service name and port generated in the configuration file. But while looking for a solution I saw that this error could also be caused by using version specific abstract WSDL’s or the WSDL location in your composite.xml pointing to the wrong destination (for example your local machine). If you’re using an MDS make sure it is in sync with the target MDS.

Friday, March 2, 2018

How to pass a SOAP header in BPEL

A while back I had to do some research to find out how I could pass a username and password dynamically to an external service in BPEL through the SOAP header using the wss_username_token_policy. Turns out it’s quite easy so let me share a simple implementation with you.
 

This is what we are aiming for, a simple BPEL process that calls an external service to return some data to the client. Both require authentication through the UsernameToken. The security header which will contain the UsernameToken consisting of a username and password and will be received as input and passed on to the target service. 


The composite looks as follows. The client and target are both secured with the wss_username_token_policy.


To achieve this we will:
1-Create a schema that contains the definition of the security header
2-Update our WSDL so it will contain the header element
3-Create a variable in BPEL for the header and use it to pass it on

1. Create the XSD schema
Create an XSD schema that specifies the UsernameToken profile in accordance with the OASIS standard. It’s not necessary to create a separate XSD schema. You could also add it to the existing XSD schema that was already generated with your project.



2. Update the WSDL
In the WSDL we will have to add the namespace, import the XSD schema and add the message type of our security header. Lastly, we add the header to the binding. See the four snippets of code I put together below:


3. BPEL
Add the namespace (here it has xmlns:ns1) and import the XSD schema. Next, create a variable that will hold the security header. I named the variable SecurityHeader. Now you can use the 'Assign' or 'Transform' activity to assign values to the elements of the header.


Now, when you edit the receive, invoke and reply constructs, you can add your header variable via the ‘Headers’ tab.


When the security header has been added for all three constructs your code should look similar like the following. The highlighted parts are the references to our security header.


Now this is how you retrieve the header passed by the client service and use it to invoke a target service. If your target service returns a header, it will be returned to the client service.

That’s all! Hope this helped :)

Friday, February 23, 2018

Changing a BPEL process' interface definition from asynchronous to synchronous (and vice versa)


So it happened to me before that during development I came to realize that my BPEL process should have been designed as synchronous in the first place instead of having an asynchronous definition. When you were already well under way developing you're not really keen on throwing your work away and start all over. Well the good news is that you don't have to. It's actually quite easy to transform your BPEL process from an asynchronous into a synchronous interface. It even works the other way around. I'll demonstrate how.

So this is what we're talking about. When you start off you used the asynchronous BPEL process template.


With hindsight, you wanted to use the synchronous BPEL process template.


Now to change the interface definition we will have to make alterations in three files:
 - The composite.xml
 - The .bpel file
 - The WSDL 

1. The composite.xml
Look for the interface.wsdl tag and remove the yellow part. If you need to convert your BPEL from synchronous to asynchronous, add the yellow part.
<interface.wsdl interface="http://xmlns.oracle.com/WCC_Orchestration_BPELapp/SampleProject/SampleProjectBpel#wsdl.interface(SampleProjectBpel)" callbackInterface="http://xmlns.oracle.com/WCC_Orchestration_BPELapp/SampleProject/SampleProjectBpel#wsdl.interface(SampleProjectBpelCallback)"/>

Look for the callback tag and remove the yellow part. If you need to convert your BPEL from synchronous to asynchronous, add the yellow part within the <service></service> tags.
<callback>
<binding.ws port="http://xmlns.oracle.com/WCC_Orchestration_BPELapp/SampleProject/SampleProjectBpel#wsdl.endpoint(sampleprojectbpel_client_ep/SampleProjectBpelCallback_pt)"/>
</callback>

Look for the componentType tag and remove the yellow part. If you need to convert your BPEL from synchronous to asynchronous, add the yellow part.
<componentType>
<service name="sampleprojectbpel_client" ui:wsdlLocation="WSDLs/SampleProjectBpel.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/WCC_Orchestration_BPELapp/SampleProject/SampleProjectBpel#wsdl.interface(SampleProjectBpel)"
 callbackInterface="http://xmlns.oracle.com/WCC_Orchestration_BPELapp/SampleProject/SampleProjectBpel#wsdl.interface(SampleProjectBpelCallback)"/>
</service>
</componentType>

Look for the following property:
<property name="bpel.config.oneWayDeliveryPolicy" type="xs:string" many="false">async.persist</property>
Change it to:
<property name="bpel.config.transaction" type="xs:string" many="false">required</property>
If you need to convert your BPEL from synchronous to asynchronous, replace the blue with the yellow parts.

2. The .bpel file
Look for the partnerlink tag and remove the yellow part.
If you need to convert your BPEL from synchronous to asynchronous, add the yellow part.
<partnerLink name="sampleprojectbpel_client" partnerLinkType="client:SampleProjectBpel" myRole="SampleProjectBpelProvider" partnerRole="SampleProjectBpelRequester"/>

Look for the invoke construct:
<invoke name="callbackClient" partnerLink="sampleprojectbpel_client" portType="client:SampleProjectBpelCallback" operation="processResponse" inputVariable="outputVariable"/>
Change it to:
<reply name="replyOutput" partnerLink="sampleprojectbpel_client" portType="client:SampleProjectBpel" operation="process" variable="outputVariable"/>
If you need to convert your BPEL from synchronous to asynchronous, replace the blue with the yellow parts.

3. The WSDL 
Look for the portType tag that contains the Callback and remove it.
If you need to convert your BPEL from synchronous to asynchronous, add it.
<wsdl:portType name="SampleProjectBpelCallback">
   <wsdl:operation name="processResponse">
       <wsdl:input message="client:SampleProjectBpelResponseMessage"/>
    </wsdl:operation>
</wsdl:portType> 

Now look for the other portType tag and add the yellow part to set the output message.
If you need to convert your BPEL from synchronous to asynchronous, delete it.
<wsdl:portType name="SampleProjectBpel">
    <wsdl:operation name="process">
       <wsdl:input message="client:SampleProjectBpelRequestMessage"/>
       <wsdl:output message="client:SampleProjectBpelResponseMessage"/>
    </wsdl:operation>
</wsdl:portType>

Look for the partnerLinkType tag and delete the yellow part.
If you need to convert your BPEL from synchronous to asynchronous, add it.
<plnk:partnerLinkType name="SampleProjectBpel">
      <plnk:role name="SampleProjectBpelProvider" portType="client:SampleProjectBpel"/>
      <plnk:role name="SampleProjectBpelRequester" portType="client:SampleProjectBpelCallback"/>
</plnk:partnerLinkType>

That's all!