Thursday, 24 April 2014

File Upload in Jersey Restful service


About:

There are many blogs which discuss on how to do file transfer in JAX-RS /Restful service all this blogs discuss using the Multipartformdata i.e. FormDataParam as the input Stream.
In this Blog, I will  be discussing on one of the way about how to create a service which will accept the File Object as input for the method which it consumes in the form XML.


Code: 

Bean Class
package model;
import java.io.InputStream;
import javax.activation.DataHandler;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class FileData {
    public FileData() {
        super();
    }
    
    String fileName;
    byte[] fileInfo;


    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileName() {
        return fileName;
    }


    public void setFileInfo(byte[] fileInfo) {
        this.fileInfo = fileInfo;
    }

    public byte[] getFileInfo() {
        return fileInfo;
    }

}

Service Class

package model;


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

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

@Path("model")
public class FileService {
    public FileService() {
        super();
    }


    @POST
    @Consumes("application/xml")
    public void uploadFile(FileData fd) {
        try {
            OutputStream os = new FileOutputStream("" + fd.getFileName());
            InputStream is = new ByteArrayInputStream(fd.getFileInfo());
             
            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) {
            System.out.println("Inside the Service"+e);
        }

    }

}


For Client :

I will explain in another blog on how to consume this in REST DataControl / URL DataControl 

Monday, 21 April 2014

How to pass complex Input Parameters to WSDC (WebServiceDataControl)


About :

One of the most common usecases in WS is passing complex Input parameters, but incase if the user wants to pass the multiple occurence of the same complex Input parameter type, how to achieve this in WSDC ?.

This blog explains about passing the multiple complex Employee records to the WebService from the WSDC via the Backing Bean.

Implementation :

Let us Consider an ADFBC Component which contains an Employees Entity, now the user can select multiple employee records from the page containing list of Employee records and post it to the WebService.

1. Create an Web Service which takes the Input Argument as ArrayList of Employee Object  and returns the ArrayList .

The Sample SOAP Request/Response looks like as shown below , here we can observe that the the occurence of the "emp" object is dynamic which contains different employee records with three attributes (empEmail, empId, empName).

SOAP Request

<ns1:addEmp>
    <emp>
 <empEmail>SLROCK</empEmail>
        <empId>101</empId>
        <empName>ShawnRock</empName>
    </emp>
    
 <emp>
        <empEmail>OKOKHLO</empEmail>
        <empId>202</empId>
        <empName>OnkBank</empName>
    </emp>
</ns1:addEmp>

SOAP Response

<ns2:addEmpResponse xmlns:ns2="http://project1/">
 <return>
        <empEmail>SLROCK</empEmail>
        <empId>101</empId>
        <empName>ShawnRock</empName>
    </return>
    <return>
        <empEmail>OKOKHLO</empEmail>
        <empId>202</empId>
        <empName>OnkBank</empName>
    </return>
</ns2:addEmpResponse>

2. Create Business Components from Employee Table.


3. Drag and Drop the EmployeesView1 node from the DC palette onto the page1.jspx as ADF Table, Ensure that the page1.jspx is bounded to a Backing Bean.


4. Create a WSDC using the WSDL url of the service deployed to the server

5. Create a Command Button in page1.jspx and bound it to an Action Listener method in the Backing Bean . The Method is used to retrieve the records selected by the user from the page1.jspx and post it to the WS.

BindingContainer bindings = getBindings();
//From the Table exposed in the Backing Bean 
RowKeySet selectedEmps = getT1().getSelectedRowKeys();   
Iterator selectedEmpIter = selectedEmps.iterator();
DCBindingContainer bx =  (DCBindingContainer) getBindings();
DCIteratorBinding empIter = bx.findIteratorBinding("EmployeesView1Iterator");
RowSetIterator empRSIter = empIter.getRowSetIterator();
This is Achieved by marshalling the selected data as an Employee Objects and adding them to an ArrayList.
ArrayList<employee> al = new ArrayList<employee>();
while(selectedEmpIter.hasNext()){
Key key = (Key)((List)selectedEmpIter.next()).get(0);
Row currentRow = empRSIter.getRow(key);                
al.add(new Employee((String)currentRow.getAttribute("FirstName"),(Integer)currentRow.getAttribute("EmployeeId"),(String)currentRow.getAttribute("Email")));
This ArrayList is then passed onto the Params Map of the WSDC method as shown below
OperationBinding operationBinding =  bindings.getOperationBinding("addEmp");
operationBinding.getParamsMap().put("emp",al);
operationBinding.execute();

6. In page2.jspx, Drag and Drop the Return type of the WSDC method as ADF Table

7. Run the Page1.jspx, select the list of Employee records and click on the post to webservice button

8. In the Next Page we can observe that the selected 4 records are posted to the WebService


Wednesday, 9 April 2014

Passing Header parameters in WebService Data Control


About

In this blog, I will be explaining on how to pass header parameters in WebServiceDataControl

Implementation:

In this example, i have webservice where based on the Header parameter value the system will greet the user such as any value other than John will be treated as USER.

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(serviceName = "HeaderService")
public class HeaderService {
    public HeaderService() {
        super();
    }
    @Resource
    WebServiceContext ctx ;

    public String greetUser() {
        try{
        String tenantID = null;
        MessageContext context = ctx.getMessageContext();
        Map requestHeaders =
            ((Map)context.get(MessageContext.HTTP_REQUEST_HEADERS));
        if (requestHeaders != null && requestHeaders.get("TenentID") != null) {
            tenantID =
                    ((List)requestHeaders.get("TenentID")).get(0).toString();
        }
        if (tenantID.equalsIgnoreCase("John")) {
            tenantID = "ADMIN";
        } else {
            tenantID = "USER";
        }
            return "Hello " + tenantID;
        }catch(Exception e)
        {
        e.printStackTrace();
        }
       return null;
    }
}

In JDeveloper, create a New Fusion Web Application and Invoke the WebService DataControl from the New Gallery


Provide the WSDL of the above service deployed and click on Next. In the DataControl Operations page select the method to exposed in our case the greetUser and select the Include Http Headers Check box.


Click on finish and complete the wizard. Now Expand the DC palette we can observe that the method exposes  the Http Header Parameter (Map Type) as input parameter for the method and the output as String.



In the ViewController project create a jspx page with bacing bean or you can also create java class and associate it to the page.I will go with the latter approach as it is easy

Now open the Backing Bean java Class and add a Map variable with getters and setters. Then set the value for the Map field and initialize in the setf1 method as it is executed when the page loads.
 private Map httpheadermap;
public void setHttpheadermap(Map httpheadermap) {
        this.httpheadermap = httpheadermap;
    }

public Map getHttpheadermap() {
        return httpheadermap;
    }
// Here we are setting the value to the Map , you can also set in //the setters of the Map

public void setF1(RichForm f1) {
        this.f1 = f1;
        setHttpheadermap(new HashMap());
        httpheadermap.put("TenentID", "John");
    }



After creating the jspx page, Drag and Drop the method from the DC palette onto the page as ADF parameter form
On dropping it you will get the Edit Form Fields dialog where delete the HttpHeader Field that is exposed

In  the Edit Action Binding Dialog for the Http Header Parameter bind it to  the Map defined in the Backing bean 


Now Run the page.  Click on the GreetUser, we can see that it says as Hello ADMIN as we have set the value as JOHN in  the backing bean