Thursday Feb 27, 2014

Consuming Async SOA in a WebService Proxy

Consider a scenario where an application is built using SOA Async processes and needs to be consumed in a WebService Proxy. In this blog, we will be demonstrating how to implement this use case. To achieve this, we will follow a two step process:

  1. Create an Async SOA BPEL process.
  2. Consume it in a WebService Proxy.

Pre-requisite:

 Jdeveloper with SOA extension installed.

Steps:

To begin with step 1, create a SOA Application and name it SOA_AsyncApp.

This invokes Create SOA Application wizard. In the wizard, choose composite with BPEL process in Step 3.


As we are going to build an async processes, in Create BPEL Process dialog, choose Asynchronous BPEL Process from Template drop-down. We will be using BPEL 1.1 Specification for our process. Also, make sure the process is exposed as a SOAP service.


We can see the two one-way operations listed in the process wsdl as it is an async process:

Drag and drop assign activity from Components onto the SOA Composite.


Edit the assign activity to insert a new rule from input variable payload to output variable payload. Click on the Plus symbol to add the rule.

Now, the Async service setup is complete and the project containing Async process can be deployed to a SOA server. With this, we are done with Step 1 of our use case.

To create a proxy for this service, create a custom Application SOA_AsyncProxy. Invoke Create Web Service Proxy wizard and in Step 2 of wizard, give WSDL of the service developed in Part1 of this blog.  In Step 3, check ‘Generate As Async ’ checkbox and give Callback Package name CallBackPackage.

In step 5, make sure generate async method radio button is selected and finish the wizard.

After proxy is generated, run the Callback Service from under the package CallBackPackage. This service will listen to the response from the asynchronous service. Give target URL of Callback Service in proxy class and call the process with appropriate input value.


Run the proxy. Following sequence of actions will take place after proxy is run:

1) The proxy will invoke the SOA process asynchronously and continue with other tasks.

2) SOA async service will store the request and send receipt confirmation (202) to the proxy.

3) The service processes the request and acting as a proxy for Callback Service, sends the response back to the Callback Service.

      4) Callback service, deployed on the proxy side receives the response and sends a confirmation to the async SOA service (202).

After the callback service receives the response, it has to map the response to the request. This is achieved using WS-Addressing Headers. The proxy must set two fields to establish the correlation: 1) ReplyTo address (address of the Callback Service) and 2) A unique Id to identify the request.

Async behavior can be verified by logging in to EM console and examining the flow instance of BPEL Process.


The correct payload in the callbackProxy confirms that async operation has been executed successfully.

Wednesday Dec 18, 2013

Client Proxy Generation for REST style services

This blog mainly talks about generating a client for REST style web services. It begins by creating a REST style service and then consuming that service using some client code.

Pre-requisites:

Use JDeveloper 12c  version.

Creating the Service:

To start with, invoke the New Application wizard, and create a Custom application. Let us call the application EmployeeService and the Project, EmployeeProj. Next invoke the New Gallery window and create a Java class. Lets name the class Employee.java. [Refer Employee.java ].

Similarly, create another Java class and name it EmpService.java. [Refer EmpService.java]

Right click on EmpService.java and select Create RESTful Service. Under Configure HTTP methods, set the following:

Name

Type

Consumes

Produces

getEmpList

GET

Application/xml

addEmployee

PUT

Application/xml

Application/xml

deleteEmployee

DELETE

Under Configure Parameter: For name, select  Annotation - PathParam; Parameter - name

updateEmployee

POST

Application/json

Under Configure Parameter: For name, select  Annotation - PathParam; Parameter - name

Leave getEmp and addEmp methods. They will not be exposed.

createREST

Click on Finish. EmpService.java should now look like [FinalEmpService.java]. Now the web service is ready to use.

Run the web service and test the methods in HTTP Analyzer. Copy the generated WADL URL.

WADL URL

Creating the REST Proxy:

Next, to create the REST proxy, follow the steps mentioned below:

Create a new Custom Project. Let us name it ClientProj.  Right click on the Project and invoke the New Gallery window. Under Business Tier -> Web services category, select RESTful Client and Proxy.

In the Create REST Proxy Client dialog that appears, enter the WADL URL generated on running the service and click on Finish. 

The generated client will consist of some in-built code.

The auto generated code consists of 2 important public classes -

Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java and 

Localhost_EmployeeServiceEmployeeProjContextRootResources.java.

The former class basically consists of a main() method using which we can readily invoke the REST service methods. The latter, i.e., Localhost_EmployeeServiceEmployeeProjContextRootResources.java consists of all the internal logic involved in invoking the methods and handling data.

This class has various methods which allow access to the web service methods. 

For example, to access the getEmpList() method of the service, normally, the code would look like:

Client client = Client.create();

WebResource service = client.resource(UriBuilder.fromUri("http://localhost:7101/REST_Sanity-Project1-context-root/resources/employeeproj").build());

System.out.println(service.accept(MediaType.APPLICATION_XML).get(String.class));

But, now we can use the auto generated class and methods to invoke the GET method as follows:

Open Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java and add the following lines where it is written "//add your code here".

System.out.println(localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class));

The put method invocation would look like:

localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.putXml("<?xml version = '1.0' encoding = 'UTF-8'?> <employee><id>2</id><name>Simon</name></employee>",String.class);

The delete method uses @PathParam in the service. So its invocation would be:

localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.name("Simon").deleteAs(String.class);

Here localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.name(..) returns an instance of the static Name class present within the Localhost_EmployeeServiceEmployeeProjContextRootResources class. Using that, you can then access the methods within the Name class.

Similarly, the post method can be invoked as:

localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.name("Test").postAsJson(String.class);

Below is the complete main method:

public class Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient {

public static void main(String[] args) {

Client client = Localhost_EmployeeServiceEmployeeProjContextRootResources.createClient();   Localhost_EmployeeServiceEmployeeProjContextRootResources.Employeeproj localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj = Localhost_EmployeeServiceEmployeeProjContextRootResources.employeeproj(client);

// add your code here

System.out.println("Put a new employee:" + localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.putXml("<?xml version = '1.0' encoding = 'UTF-8'?> <employee><id>2</id><name>Simon</name></employee>", String.class)); localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.name("Simon").deleteAs(String.class); System.out.println("Delete new employee:"+localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class)); System.out.println("After Post:" + localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.name("Test").postAsJson(String.class));

}

[Refer Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java ].

On running the client, the following output will be seen in the log:

ClientOutput

The first line of the output corresponds to Put operation. In the put operation, we enter a new employee, Simon's details and the XML data after this operation is shown in the output.

The next line shows the result of delete operation after deleting the employee with name "Simon".

This is followed by the result of post operation which is displayed in Json format. 

Monday Oct 07, 2013

XML Parsing in ADF Mobile

Usecase:

In this usecase, we have a web service that returns employee details(like name, designation, salary etc.) for an employee with given ID. In the mobile app, we will be calculating tax on the returned salary and displaying it to the user in a pop-up.

To do this, we will be parsing the returned XML to fetch the current salary and add a tax of 5% on it.

Here, we are assuming that tax is 5% of the current salary.

Steps:

Run EmployeeService.java in RESTApp.zip. Copy the target URL. 

Create a new ADF Mobile application. 

Name the application ‘XmlParsingSample’ and finish the wizard.

Create a URL Connection in the ApplicationController project.

Name the connection ‘conn’ and suppy the target URL copied earlier. Remember to use IP instead of localhost. Test the connection and click OK to close the wizard.

Since the service returns XML data, also create a Data control. This will be useful for designing the UI page. To create DC, invoke URL Service data control wizard in the ApplicationController project.

Test the URL connection in the last step and finish the wizard.

Now, let us create the AMX pages. Open adfmf-feature.xml present in ViewController project. Add a new feature ‘EmpFeature’ by clicking the plus icon as shown.

Go to the content tab and add an AMX page.

Call it EmpPage.amx. We don’t need the primary and secondary actions. So, uncheck them.

Drag and drop ‘id’ parameter from the DC palette onto the Panel Page of the Structure pane for this page.

Drag and drop a button from the component palette onto the page. Change the text of the button to ‘Get salary’.

As we want to invoke the service on click of this button, let us associate an ActionListener with this. Focus on the button and from the PI, select the arrow button for Action Listener propery and click Edit to bring up the below dialog. Click New to create a new managed bean.

Name the manged bean as  myBean and class as myClass.

Next, create a new method called calculateTax.

Go to myClass.java. In calculateTax method, write the code provided in the below table. Use the imports:

import oracle.adfmf.amx.event.ActionEvent;

import oracle.adfmf.dc.ws.rest.RestServiceAdapter;

import oracle.adfmf.framework.api.AdfmfContainerUtilities;

import oracle.adfmf.framework.api.Model;

import org.xmlpull.v1.XmlPullParser;

import org.kxml2.io.KXmlParser;

import java.io.Reader;

import java.io.StringReader;

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

44.

45.

46.

47.

48.

49.

50.

public void calculateTax(ActionEvent actionEvent) {

// Add event code here...

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();

restServiceAdapter.setConnectionName("conn");

restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);

restServiceAdapter.addRequestProperty("Content-Type", "application/xml");

restServiceAdapter.addRequestProperty("Accept", "application/xml; charset=UTF-8");

restServiceAdapter.setRetryLimit(0);

Object emppIDObj = AdfmfJavaUtilities.evaluateELExpression("#{bindings.id.inputValue}");

String empIDString = emppIDObj.toString();

restServiceAdapter.setRequestURI("/byID?id="+empIDString);

String response = "";

try {

response = restServiceAdapter.send("");

System.out.println("Response received!");

String name = "";

int sal = 0;

int salAfterTax = 0;

KXmlParser parser = new KXmlParser(); //create a parser instance

Reader stream = new StringReader(response);

parser.setInput(stream);

parser.nextTag();

parser.require(XmlPullParser.START_TAG, null, "employee");

while (parser.nextTag() != XmlPullParser.END_TAG) { //loop through until you encounter an end tag

parser.require(XmlPullParser.START_TAG, null, null); //go to start tag

String tagName = parser.getName(); //get the name of the current tag

String tagValue = parser.nextText(); //get the value within the current tag

if (tagName.equals("name")) { //if current tag is ‘name’, assign its value to variable ‘name’

name = tagValue;

}

if (tagName.equals("salary")) { //if current tag is ‘salary’, calculate salary after tax

System.out.println("Salary:" + tagValue);

sal = Integer.parseInt(tagValue);

salAfterTax = (int)(sal - sal * 0.05);

}

parser.require(XmlPullParser.END_TAG, null, tagName); //go to end tag of current tag

//parse through all the tags

}

parser.require(XmlPullParser.END_TAG, null, "employee");

parser.next();

parser.require(XmlPullParser.END_DOCUMENT, null, null);

AdfmfContainerUtilities.invokeContainerJavaScriptFunction("EmpFeature", "navigator.notification.alert",

new Object[] { "Salary for employee " + name +

" is " + sal +

". After tax deduction, salary is:" +

salAfterTax, "", "Note", "OK!" });

} catch (Exception e) {

System.out.println("Exception is:" + e);

}

}

}

 Lines 3 to 15 set various properties required to invoke the web service. In lines 10 and 11, we are getting the value input by the user and converting that to String inorder to pass the parameter to the service. In line 20, we are creating a kXml parser instance. kXML is one of the core ADF Mobile libraries that provides API that you can use to parse XML. As the parser needs a Reader object, we are converting our services’ response into Reader in line 21 and passing it in line 22.

 The response returned by our service is of the form

<?xml version="1.0" encoding="UTF-8"?>
<employee>
<dept>HR</dept>
<desig>Officer</desig>
<id>2</id>
<name>Myra</name>
<salary>70000</salary>
</employee>

To parse this response, we are setting the parser to the first tag ‘employee’ in line 24. In lines 25 through 42, we are going through the XML elements. The comments are in-line for these lines. Finally, lines 43 through 47 are for displaying the pop-up. To display the pop-up, we are utilizing AdfmfContainerUtilities.invokeContainerJavaScriptFunction. For more information, see link.

As mentioned in the article, we make use of the javascript function which comes from phonegap-1.0.0.js. Hence, we need to include an entry to this javascript file in our AMX page. Put the below entry in EmpPage.amx above the panelPage.

<script type = "text/javascript" charset="utf-8" src="../../../www/js/phonegap-1.0.0.js"></script>

That’s it. Deploy the app to a device or an emulator. Some snippets from the final app. 

Enjoy coding! 

About

Tips and Tricks from Oracle's JDeveloper & ADF QA

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today