Wednesday Mar 26, 2014

File Upload Using WSDC for an MTOM WebService

Use Case:

In this usecase I will explain about how to upload file in WSDC to the target WebService from the Backing Bean 

What is MTOM ?

MTOM or  Message Transmission Optimization Mechanism is the W3C Message Transmission Optimization Mechanism, a method of efficiently sending binary data to and from Web services.

Implementation:

Lets start by creating a Java WebService with MTOM Enabled to allow transfer of files as shown below.

In the service provide a location where the files have to be saved else create a folder called mytemp in C drive if planning to use the code below. 

package project1;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.activation.DataHandler;

import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebParam;

import javax.jws.WebService;

import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.MTOM;

@WebService(serviceName = "UploadService")
@MTOM
public class UploadService {
    public UploadService() {
        super();
    }

    @WebMethod
    @Oneway
    public void fileUpload(@WebParam(name = "arg0") String fileName, @XmlMimeType("application/octet-stream") @WebParam(name = "arg1") DataHandler data) {
    try {
       
 OutputStream os = new FileOutputStream("C:\\mytemp\\"+fileName);
        InputStream is = data.getInputStream();          
                 byte[] buffer = new byte[1024];
                 int bytesRead;
                 //read from is to buffer
                 while((bytesRead = is.read(buffer)) !=-1){
                     os.write(buffer, 0, bytesRead);
                 }
                 is.close();
                 //flush OutputStream to write any buffered data to file
                 os.flush();
                 os.close();
        
    }
    catch (Exception e)
    {
            throw new WebServiceException(e);
    }
    }
}

Now deploy the Service to Integrated WLS.

Create an ADF Fusion Application and create WebService Data Control from the New Gallery using the WSDL URL of the service deployed. After creating the DC , expand the DC palette where we can observe that the FileUpload method takes 2 arguments , the first argument is the file Name which String type and the Second Argument is Object type 

DCPalette

Now in the ViewController, create a jspx page with Backing Bean or we can create the backing bean separately and bind to the page.

In the Backing Bean add the following Two Methods

// This Method is used to read the file provided by the user and pass it to the DC
public void fileUploaded(ValueChangeEvent event)
     {
       UploadedFile file = (UploadedFile) event.getNewValue();
       if (file != null)
       {
        FacesContext context = FacesContext.getCurrentInstance();
        FacesMessage message = new FacesMessage("Successfully uploaded file " + file.getFilename()+" (" + file.getLength()+" bytes)");
        context.addMessage(event.getComponent().getClientId(context), message);
        DCBindingContainer bc = (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
        OperationBinding op = bc.getOperationBinding("fileUpload");
            try {
                //Convert the file Data into Byte Array and then pass this to the DC
                byte[] buffer = readFully(file.getInputStream());
                if(op!=null){
                   Map param = op.getParamsMap();
                   param.put("arg0",file.getFilename());
                   param.put("arg1",buffer);
                    op.execute();
                }
            } catch (IOException e) {
            }
            
       }
     }
    public byte[] readFully(InputStream input) throws IOException
    {
        byte[] buffer = new byte[8192];
        int bytesRead;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        while ((bytesRead = input.read(buffer)) != -1)
        {
            output.write(buffer, 0, bytesRead);
        }
        return output.toByteArray();
    }

In jspx page, Drag and drop the ADF Input File Component  and bind the Value Change Listener component to the fileUploaded() Method given above

pageSource

Go to the page definitions of the page, in  the bindings add the Method Action as shown below


Once after adding the method action, drag &drop a button onto the page for submit.Now when the jspx page is rendered , browse and select a file then click on Submit button 

createREST

Now we can observe that file gets transferred to the location mentioned in the Service



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.

Tuesday Feb 04, 2014

HTTP Basic Auth in REST Client

When a web service is secured using basic authentication, the client can access the web service only after providing the appropriate credentials.

In this blog, I take you through the code which will enable the client to access such a service.

Pre-requisites:

Use JDeveloper 12c  version or above.

Creating the Service:

Let us start by creating a REST service and securing it with basic authentication. 

For creating the service, please refer the section "Creating the service" in blog.

Basic Authentication setup:

Once the REST service has been created, in order to secure it using basic authentication, follow the below steps:

Open the web.xml file. At the end of the file, add the lines:

<login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>myrealm</realm-name>
    </login-config>
    <security-constraint>
        <web-resource-collection> 
           <web-resource-name>MyResource</web-resource-name> 
           <url-pattern>/*</url-pattern> 
        </web-resource-collection> 
        <auth-constraint> 
           <role-name>MyRole</role-name> 
        </auth-constraint> 
    </security-constraint>
    <security-role> 
        <role-name>MyRole</role-name> 
    </security-role> 
</web-app>

Next, you need to create a weblogic.xml file. For this, go to New Gallery -> General -> Weblogic Deployment Descriptor.

weblogic xml file

On clicking Ok, another popup appears. Under Select Descriptor, select weblogic.xml and click Next. Select the deployment descriptor version in accordance with your weblogic version and then click Finish. This will generate a weblogic.xml file under WEB-INF. Open weblogic.xml file and select 'Security' from LHS. Under 'Security Role Assignments', add the Role Name 'MyRole', and add the Principals 'Administrators' as shown.

Configuring weblogic.xml file

At this point, your web service has been secured using basic authentication mechanism. Run the service and copy the generated WADL URL. This will be used to create the proxy for the service.

Accessing the service through REST Client:

First, to create the REST Client, 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 REST Client and Proxy. Provide the generated WADL URL and click Next.

A prompt will appear asking for username/password.

Credential pop up

Provide the Administrator username and password that you would use to log into the WLS Console.On providing the correct credentials and clicking on Finish, the client class gets generated with some in-built code. Within the class 'Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java' auto generated for you, write the following lines:


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
        client.addFilter(new HTTPBasicAuthFilter("weblogic","weblogic1"));
        System.out.println(localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class));
    } 

Use the import as below:

import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;

We use the HTTPBasicAuthFilter provided by Jersey to pass the basic auth credentials. Refer link for more details.

Alternate method:

Alternately, within the public class Localhost_EmployeeServiceEmployeeProjContextRootResourcesClient.java auto generated for you, write the following lines:

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
        Authenticator.setDefault(new MyAuthenticator());
        System.out.println(localhost_employeeserviceemployeeprojcontextrootresourcesemployeeproj.getAsXml(String.class));
    }
    
    static class MyAuthenticator extends Authenticator {    
        public PasswordAuthentication getPasswordAuthentication() {
                
        return (new PasswordAuthentication("weblogic", "weblogic1".toCharArray()));
            }
        } 

Use the imports:

import java.net.Authenticator;

import java.net.PasswordAuthentication;

Here, in the code block above, we basically extend the Authenticator class, and override the getPasswordAuthentication method, in which we pass the username and password. (Replace username and password above with the credentials you provided to create the client class)

In the main method, we then invoke the setDefault method of the Authenticator class and pass our Authenticator class name. This method will set the credentials whenever a proxy or HTTP server asks for authentication. The next two lines are for invoking a method of the service.

If you run the client code by supplying incorrect credentials, you will get a 401 Unauthorized error.

Wednesday Jan 15, 2014

Consuming Query and Path Parameter in REST DC

Use Case:

In this blog I will explain on how to configure the REST DC when there are Query and Path Parameters present in the Service that is to be consumed.
The Query and Path parameters in the DC are exposed as method Input Parameters in the DC palette allowing the user for easy Drag and Drop.

JDeveloper Version : 12.1.2

Implementation:

Configuring Query Parameters

Service API Uri:

http://<Server>/SampleApp/resources/rest-deleteservice?name=’Abby’

Scenario Details:
In this Uri ‘name’ is a Query Parameter which will be used to delete a specific record, to expose this follow the below steps

1.    Invoke the Rest DC  and create the connection

2. In the Resources tab, enter the  remaining resource uri without providing the ‘?name=’  as shown below

3. In the Method Details tab select the delete method, and in the URL Parameters panel click on ‘+’ and enter the parameter details.
Provide an Default value which will be invoked whenever the service is loaded

NOTE:
Providing a Valid Default Value becomes crucial when there is a GET with Query Param for which you would like the XSD to be generated by the Jdeveloper itself. 

Configuring Path Parameters


Service Uri:
http://<ServerDetails>/sqlrest/CUSTOMER/7/


Scenario Details:
In the above case ‘7’ is an customer id value based on which the specific customer record will be fetched, so this customer id is dynamic so we will be discussing on how to expose this as an dynamic field in the REST DC


1.    Invoke the Rest DC and create the Connection with Server details as mentioned in the  Step 1 for the Query Parameter
2.    In the Resources Tab, enter the resource url  and select the Method type , provide an valid name for the method

Here we can observe that Instead of the Value 7 we have provided that field as ##CustomerId##, now click on Next.

3. In the Method Details page, the ##CustomerId## is exposed in the URL Attributes panel, provide the default value of the Customer Id  , Click Next 

4. Now In this case , I have not provided the Response XSD which will be auto generated by the Jdeveloper and the DC palette will look as shown below after completing the wizard

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 Dec 16, 2013

XSLT Transformation in REST DC

Use Case:
This blog explains about applying XSLT transformation on a REST Service while creating the Rest DataControl. Here I will be explaining on how the data is getting manipulated and is rendered by the REST DC when XSL is applied on it.

JDeveloper Version used : 12.1.2

Steps:
1. Consider an Scenario where an REST Service API is retuning an XML response as mentioned below

<?xml version = '1.0' encoding = 'UTF-8' standalone = 'yes'?>
<departments>
   <department>
      <deptId>1001</deptId>
      <deptName>HumanResource</deptName>
   </department>
   <department>
      <deptId>2002</deptId>
      <deptName>Finance</deptName>
   </department>
   <department>
      <deptId>3003</deptId>
      <deptName>Research</deptName>
   </department>
   <department>
      <deptId>5005</deptId>
      <deptName>Sales</deptName>
   </department>
</departments>


2. Lets create an XSD structure to contain two more new attributes e.g CUSTOMNAME of type String and UNIQUEID of type integer

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xsd:element name="departments">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="department" maxOccurs="unbounded">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="deptId" type="xsd:integer"/>
              <xsd:element name="deptName" type="xsd:string"/>
              <xsd:element name="customUniqueId" type="xsd:integer"/>
              <xsd:element name="customName" type="xsd:string"/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

3. Now we have to create an XSL File to transform data , so that the values can be populated for the new attributes.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns2="http://project1/">
    <xsl:template match="departments">
        <departments>
          <xsl:for-each select="department">
              <department>
                  <deptName><xsl:value-of select="deptName"/></deptName>
                  <deptId><xsl:value-of select="deptId"/></deptId>
                  <customName><xsl:value-of select="concat('CUST_',deptName)"/></customName>
                  <customUniqueId><xsl:value-of select="deptId * 2"/></customUniqueId>
              </department>      
          </xsl:for-each> 
        </departments>
    </xsl:template>
</xsl:stylesheet>

4. In Jdeveloper, invoke the WSDC wizard, select the type as REST, in the wizard provide the name for the DC and create the connection.



5. In the Next Step of the wizard, provide the resource path and the method name for the operation



6. In the Method Details Step of the wizard provide the Cutsom XSD and  XSL file for the method as shown below



7.  Click Next and Complete the Wizard, then Expand the DC palette to find the Structure as shown below



8. Drag and Drop the departmentNode onto the page as an ADF table and Run the page


9. Here we can observe the value being populated for the customUniqueId and customName as per the definition given in the XSL file

Thursday Aug 02, 2012

Exposing Multiple Methods under One Resource In a Single URL Data Control

Previously, a URL Data Control could be associated with only one HTTP Method. So  if the developer had to expose multiple operations under  a single Resource, he/she had to create one DC for each operation.  Now since Jdeveloper  supports such a functionality from 11.1.2.2.0 version, multiple operations can be included in a single DC. This blog explains how to include all the operations exposed by a REST Service Resource in a single Data Control. We will use following REST Service to create URL Data Control.

import java.util.ArrayList;
import java.util.Iterator;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

@Path("project1")
public class EmployeeService {
    private ArrayList<Employee> EmpList = new ArrayList<Employee>();

    public EmployeeService() {
        EmpList.add(new Employee("Adam", 1001, 35, "ADF"));
        EmpList.add(new Employee("Bob", 1002, 42, "HR"));
        EmpList.add(new Employee("George", 1003, 54, "Apps"));

    }

    @GET
    @Produces("application/xml")
    public ArrayList<Employee> getEmpList() {
        return EmpList;
    }

    @POST
    @Consumes("application/xml")
    @Produces("application/xml")
    public ArrayList<Employee> addEmployee(Employee emp) {
        EmpList.add(emp);
        return EmpList;
    }

    @DELETE
    @Consumes("text/plain")
    public ArrayList<Employee> deleteEmployee(@QueryParam("name")
                                              String name) {
        Iterator it = EmpList.iterator();
        while (it.hasNext()) {
            Employee tmp = (Employee) it.next();
            if (tmp.getName().equalsIgnoreCase(name))
                EmpList.remove(tmp);

        }
        return EmpList;
    }

}
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Employee {
    String name;
    int id;
    int age;
    String dept;
    
    public Employee() {
        super();
    }

    Employee(String name, int id, int age, String dept) {
        this.name= name;
        this.id=id;
        this.age=age;
        this.dept=dept;
        
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public String getDept() {
        return dept;
    }
}

Run the REST Service before commencing with Data Control. 

To begin with, create ADF Fusion Application. In Model project invoke create DC Wizard. Name your Data Control RESTDC and click on Next to create URL Connection.



In the next step, give a name to the URL connection, for example URLConn and specify localhost address in the URL Endpoint field.

Also, choose GET as HTTP Method and supply remaining part of REST Service URL in the source field.



In Step 4, choose XML as the data format from the drop down menu. Click Next. XSD will be auto generated by the jdeveloper. In step 5, click on Test URL Connection to check if the connection has been successfully generated.



Click on finish to complete the wizard. The Data Control for GET method in the REST Service has been created successfully and can be viewed under Data Controls Panel.




Now, we will add remaining HTTP Methods in the service to RESTDC. Invoke Create URL DC Wizard in the Model project. Give RESTDC (same name as the previous DC) in the Name field and choose URLConn from the drop- down. Select POST as the HTTP Method and supply the path to POST Operation in source field.



In the next step, specify the XSD which specifies the structure of the request content. Click Next.Choose XML Data format from the drop-down and complete the wizard. You can see another operation added to the same Data Control in the DC Panel.




Similarly invoke Create URL DC Wizard to add DELETE Method to RESTDC.



In step 3, you will be asked to enter a value to test whether URL and source are valid. Enter  "abc" in the values field against param.



Choose XML as Data format and complete the wizard.

Now the Data Controls Panel has all three operations GET, POST and DELETE which are in the resource under a single URL DC.



The names of these methods (loadData, loadData1 etc) can be changed from DataControls.dcx file.


Monday May 21, 2012

Executing Put operation of REST service programatically from ADF App

In quite some cases, we would like to call the PUT method on a REST service by constructing the parameters during runtime and pass it on. In this article, we would go through how to deal with such cases when building an ADF Application.

Refer this tutorial for introduction to REST service in where, GET and DELETE methods are explained. In this sample, we'll see how to implement PUT operation using a HashMap. In fact, as like in the above tutorial, we can directly execute the PUT method as well. This article is mainly concentrated on how to construct the parameters dynamically at runtime.

First let us create a simple POJO to hold employee records.

package project1;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement

public class Emp {
    public Emp() {
        super();
    }
    
    private String name;
    private int id;
    private int exp;
    private int salary;

    public Emp(String name, int id, int exp, int salary) {
        super();
        this.name = name;
        this.id = id;
        this.exp = exp;
        this.salary = salary;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setExp(int exp) {
        this.exp = exp;
    }

    public int getExp() {
        return exp;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getSalary() {
        return salary;
    }
    
    public String toString() {
        String empXml = "<name>"+getName()+"</name>"+"\n"+
                       "<id>"+getId()+"</id>"+"\n"+
                        "<experience>"+getExp()+"</experience>"+"\n"+
                       "<salary>"+getSalary()+"</salary>";
        return empXml;                  
    }
}
Then, create a REST service using the for the Employee.

package project1;

import javax.ws.rs.Path;
import java.util.*;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;

import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;

@Path("/test")
public class Service {
    
   static ArrayList<Emp> emp = new ArrayList<Emp>();
  
    public Service() {
        super();
     }
    
    @GET
    @Produces("application/xml")
    public  ArrayList<Emp> getEmps() {
       
        return emp;
        
    }
    
    @DELETE
    public void deleteEmp(@QueryParam("id") int id) {
       emp.remove(getObj(id));
    }
    
    @PUT
    @Consumes("application/xml")
    public void addEmp( Emp e) {
        emp.add(e);
    }
    
    @PUT
    @Path("defaultEmp")
    public Response addEmp() {
        emp.add(new Emp("abc",1,5,10000));
        emp.add(new Emp("xyz",2,7,15000));
        emp.add(new Emp("lmn",3,5,8000));
        return Response.ok().build();
            
    }
    
    @POST
    public void upadteEmp(@QueryParam("id")int id,Emp e) {
      deleteEmp(id);
      addEmp(e);
    }
    
    public Emp getObj(int id) {
        Iterator i = emp.iterator();
        while(i.hasNext()){
        Emp emp = (Emp)i.next();
        if((emp.getId())==id)
        {
            System.out.println(emp.getName());
            return emp;
        }
        } 
        return null;
    }
}

We'll come to the UI part now.

After creating a Fusion Web Application from JDeveloper, create a new URL Data Control for the REST service created above (for GET and PUT Operations).

DataControls.dcx looks like below

DataControls.jpg



Now, our aim is to have a UI, from where we can enter the employee details. Once after having the data, construct parameter object and execute loadData (PUT) method.

This is done by having 4 input texts and bind them to attributes in the backing bean. Drag and Drop the loadData method from RestPut DataControl (and do not specify a value for the parameter).



And the code snippet of the jspx page

<af:panelFormLayout id="pfl1">
    <f:facet name="footer">
        <af:commandButton text="Put"
          disabled="#{!bindings.loadData.enabled}" id="cb1"
          actionListener="#{pageFlowScope.RestBean.performPut}"/>
    </f:facet>
    <af:inputText label="Id" id="it1" 
                  value="#{pageFlowScope.RestBean.id}" autoSubmit="true"/>
    <af:inputText label="Name" id="it2" 
                  autoSubmit="true" value="#{pageFlowScope.RestBean.name}"/>
    <af:inputText label="Exp" id="it3" 
                  value="#{pageFlowScope.RestBean.exp}" autoSubmit="true"/>
    <af:inputText label="Sal" id="it4" 
                  autoSubmit="true" value="#{pageFlowScope.RestBean.sal}"/>
</af:panelFormLayout>

In the backing bean (RestBean), we have 4 attributes with accessors that are mapped to the Text Items.

    private Number id,sal,exp;
    private String name;


    public void setId(Number id) {
        this.id = id;
    }

    public Number getId() {
        return id;
    }

    public void setSal(Number sal) {
        this.sal = sal;
    }

    public Number getSal() {
        return sal;
    }

    public void setExp(Number exp) {
        this.exp = exp;
    }

    public Number getExp() {
        return exp;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }


Now, we'll add an actionListener code in the backing bean, in that, we can construct a Map with the required values and then execute the method by passing Map to it.

    public void performPut(ActionEvent actionEvent) {
        BindingContainer bindings = getBindings();
        Map putParamMap = new HashMap();
        putParamMap.put("id", getId());
        putParamMap.put("name", getName());
        putParamMap.put("exp", getExp());
        putParamMap.put("sal", getSal());

        OperationBinding operationBinding = bindings.getOperationBinding("loadData");
        operationBinding.getParamsMap().put("emp",putParamMap);
        Object result = operationBinding.execute();
        if (!operationBinding.getErrors().isEmpty()) {
            System.out.println("Error processing put operation..");    
        }
    }

    public BindingContainer getBindings() {
        return BindingContext.getCurrent().getCurrentBindingsEntry();
    }
In the above code, we find the loadData method from the DataBindings entry, create a Map with all the required attributes to create an Employee record, get the Parameter list for the method and pass the Map to method as parameter to execute it.


Monday Jun 20, 2011

Database Web Service using Toplink DB Provider

With JDeveloper 11gR2 you can now create database based web services using JAX-WS Provider. The key differences between this and the already existing PL/SQL Web Services support is:

  • Based on JAX-WS Provider
  • Supports SQL Queries for creating Web Services
  • Supports Table CRUD Operations

This is present as a new option in the New Gallery under 'Web Services'

ToplinkDBWS_NewGallery.jpg


When you invoke the New Gallery option, it present you with three options to choose from:

ToplinkDBWS_ThreeOptions.jpg


In this entry I will explain the options of creating service based on SQL queries and Table CRUD operations.

SQL Query based Service

When you select this option, on 'Next' page it asks you for the DB Conn details. You can also choose if you want SOAP 1.1 or 1.2 format. For this example, I will proceed with SOAP 1.1, the default option.

ToplinkDBWS_DBConn.jpg


On the Next page, you can give the SQL query. The wizard support Bind Variables, so you can parametrize your queries. Give "?" as a input parameter you want to give at runtime, and the "Bind Variables" button will get enabled. Here you can specify the name and type of the variable.

ToplinkDBWS_BindVariable.jpg


Finish the wizard. Now you can test your service in Analyzer:

ToplinkDBWS_TestServiceQuery.jpg


See that the bind variable specified comes as a input parameter in the Analyzer Input Form:

ToplinkDBWS_AnalyzerQuery.jpg


CRUD Operations

For this, At Step 2 of Wizard, select the radio button "Generate Table CRUD Service Provider"

ToplinkDBWS_CRUDSelect.jpg


At the next step, select the DB Connection and the table for which you want to generate the default set of operations:

ToplinkDBWS_CRUDTableSelect.jpg


Finish the Wizard. Now, run the service in Analyzer for a quick check.
See that all the basic operations are exposed:

ToplinkDBWS_CRUDTableAnalyzer.jpg

Tuesday Jan 25, 2011

Using Global Policy Attachment with JRF Proxies

[Read More]
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