How to upload file in ADF Mobile

Requirment- How to upload a file in ADF mobile

Solution- ADF Mobile carries with it a similar set of declarative components, but what is missing is an easy way to upload a local file from the mobile device to a remote server. In ADF Faces one would use the component but there is no equivalent present in ADF Mobile, thus leaving the developer no other option than to achieve this programmatically. However, thanks to the fact that ADF Mobile makes use of the PhoneGap (first release)/Apache Cordova (latest version) libraries, using these JavaScript libraries it is possible to implement the file upload facility relatively simply. This document demonstrates a way to upload a local file to a remote server in ADF Mobile.

Setup:
Install JDeveloper 11g Release 2 (version 11.1.2.3 or above) along with Oracle ADF Mobile extension for JDeveloper. This can be done from Help  Check for Updates and then either downloading the extension from Oracle or alternatively installing it from a local copy of the Extension Zip file.
Install Android SDK. Create a virtual device if you would like to deploy on an emulator or else you could also deploy directly to an actual Android device. Configure the ADF Mobile environment for Android from Tools ->Preferences->ADF Mobile-> Platforms.

Steps Involved
We will consider a simple business use case where the user is required to click a photograph with the device camera and upload it to a remote server.
Creating the application and task flow:
Open JDeveloper. Create a new application and select the type as Mobile Application (ADF)

1adf

Click “OK”, name your application (for this example we will name it as “FileTransferDemo”), and then click “Next” on all subsequent dialog windows, accepting all default options, and finally click on “Finish”.

2ad

Create a new feature in the adfmf-feature.xml. Name it as “FileTransfer”. Create a new AMX page under the Contents tab and name it “upload.amx”.

3adf

Create a new JavaScript file, name it “myjs.js”.

4adf

5adf

Include the myjs.js file in the current feature as shown below:

6adf

Now edit the JavaScript file as follows:

(function () {
    if (!window.application)
        window.application = {
        };

    snapUpload = function () {
        // take picture
        navigator.camera.getPicture(uploadPhoto, function (message) {
            alert("get picture failed");
        },
        {
            quality : 50, destinationType : navigator.camera.DestinationType.FILE_URI, 
  sourceType : navigator.camera.PictureSourceType.CAMERA
        });
    };

    function uploadPhoto(imageURI) {
        var options = new FileUploadOptions();
        options.fileKey = "file";
        // extract filename from URI
        options.fileName = imageURI.substr(imageURI.lastIndexOf('/') + 1);
        options.mimeType = "image/jpeg";
        var params = {
        };
        options.params = params;
        var ft = new FileTransfer();
        // upload to server
        ft.upload(imageURI, encodeURI("http://10.87.194.23:7101/FileUpload-ViewController-
context-root/upload.jsp"), success, fail, options);
    }

    function success(response) {
        alert("File uploaded successfully");
        // log response
        console.log("Code = " + response.responseCode);
        console.log("Response = " + response.response);
        console.log("Sent = " + response.bytesSent);
    }

    function fail(error) {
        alert("An error has occurred: Code = " + error.code);
        // log error
        console.log("Upload error source " + error.source);
        console.log("Upload error target " + error.target);
    }
})();

Now we will add code in the AMX page that will call the JavaScript functions. First create a bean with a method that will call the JavaScript function snapUpload, and register it as a managed bean in the adf-mobile-config.xml file as shown:

7adf

package mobile; 
import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfContainerUtilities;

public class MyBean {
    
    public void snapUpload(ActionEvent ae) {	// action listener method
        // call JavaScript function to take picture and upload to server
        AdfmfContainerUtilities.invokeContainerJavaScriptFunction("FileTransfer", 
"snapUpload", new Object [] {});
    }
}

Edit the upload.amx page as follows:

<?xml version="1.0" encoding="UTF-8" ?>
<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"
          xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">
  <amx:panelPage id="pp1">
    <amx:facet name="header">
      <amx:outputText value="Image Upload" id="ot1"/>
    </amx:facet>
    <amx:commandButton text="Upload Photo" id="cb1" actionListener="#{pageFlowScope.myBean.snapUpload}"/>
    </amx:panelPage>
</amx:view>

Basically, we are associating an action listener with a button that calls the JavaScript function from our Java code.
The server must be up and running for the file upload to work. The URL provided must point to a page that accepts a file whose contents are sent in the body of a POST request. In our case, we are using a JSP page, but any other web technology may be used like PHP, ASP.NET etc.
The following code lists our simple upload.jsp page:

<%@ page language="java" import="java.io.*" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%        
// get the content type information from JSP Request Header
String contentType = request.getContentType();        
// content type should not be null and data passed from mulitpart/form-data is greater than // or equal to 0
if ((contentType != null) && (contentType.indexOf("multipart/form-data") >= 0)) {
	DataInputStream in = new DataInputStream(request.getInputStream());
	// get length of the data content
	int formDataLength = request.getContentLength();
	byte dataBytes[] = new byte[formDataLength]; 
	int byteRead = 0;
	int totalBytesRead = 0;
	// read bytes while available
	while (totalBytesRead < formDataLength) {
		byteRead = in.read(dataBytes, totalBytesRead, formDataLength);
		totalBytesRead += byteRead;
	}                                        
	String file = new String(dataBytes);                
	// get filename for saving                
	String saveFile = file.substring(file.indexOf("filename=\"") + 10);                
	saveFile = saveFile.substring(0, saveFile.indexOf("\n"));                
	saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1,saveFile.indexOf("\""));                
	int lastIndex = contentType.lastIndexOf("=");
          // get boundary delimiter from header               
	String boundary = contentType.substring(lastIndex + 1, contentType.length());                
	int pos;                
	// locate start and end positions of file data within request                 
	pos = file.indexOf("filename=\"");                
	pos = file.indexOf("\n", pos) + 1;                
	pos = file.indexOf("\n", pos) + 1;                
	pos = file.indexOf("\n", pos) + 1;                
	int boundaryLocation = file.indexOf(boundary, pos) - 4;                
	int startPos = ((file.substring(0, pos)).getBytes()).length;                
	int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;
                
	// create a new file with the same name as source and copy the file contents to it                
	FileOutputStream fout = new FileOutputStream(saveFile);                
	fout.write(dataBytes, startPos, (endPos - startPos));                
	fout.flush();                
	fout.close();

%>
<br></br>
<table border="2">
    <tr>
        <td>
            <b>You have successfully uploaded the file by the name of:</b>
            <%=new File(saveFile).getAbsolutePath()%>
        </td>
    </tr>
</table>
<%
} // end if
%>

Finally, deploy the application to an Android device or emulator using the Application  Deploy menu.
Tapping on the “Upload Photo” button opens up the device camera using which you can snap a picture.
8adf

9adf

After you have clicked the photo the file is uploaded to the server. Upon successful upload the user is alerted accordingly.

10adf

Looking at the log file “FileTransferDemo.txt” under the sdcard root you can see the response code, the HTML response from the server and the number of bytes transferred has been logged. You can view the log file by typing “file:///sdcard/FileTransferDemo.txt” in the address bar of the device browser.

Notes
Using PhoneGap/Apache Cordova it is possible to upload any kind of file by simply changing the URI and the MIME type. For a better user experience we could integrate a file browser to locate and select our desired file from the device’s local file system. For a demonstration on using a filesystem browser in ADF
At the server side we have used a very simple implementation of an upload page. However, depending on requirements this upload page might need to be able to read one or more parameters and involve other complexities. Typically, if we are leveraging Apache and JEE technology to host our server it is often a popular choice to use Apache HttpClient or HttpComponents libraries.

References

1. Oracle Fusion Middleware Mobile Developer’s Guide for Oracle Application Development Framework (http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/toc.htm)
2. PhoneGap API Documentation (http://docs.phonegap.com/en/1.0.0/index.html)
3. Uploading Single File by Using JSP (http://www.roseindia.net/jsp/file_upload/Sinle_upload.xhtml.shtml)

Happy ADF Mobile learning with Vinay Kumar in techartifact…..

JSP EL expression is not evaluated

JSP or EL expression is not evaluated. I have seen couple of times JSP directly displaying the el-expression on webpages.

It may be because of couple reasons

1) Typo in your jsp.
2) Attributes are not set in reqeust or pageContext.
3) You have not enabled EL expression in your JSP or not enabled in your web container.

From Servlet specs 2.5 finally El expression are enabled by default. You don’t need enabled them manually in your JSP.

In case you are using older version Servlet Container, add following line to enable them.

<%@ page isELIgnored="false" %>

JSP Life cycle

Life cycle of a JSP page consists of two phases, translation phase and execution phase. Every JSP is a Servlet, a JSP page is translated and compiled into servlet and the resulting servlet handles the request, So life cycle of a JSP page largely depends on the Servlet API.

JSP engine does the following 7 phases.

• Page translation: page is parsed, and a java file which is a servlet is created.
• Page compilation: page is compiled into a class file
• Page loading : This class file is loaded.
• Create an instance : Instance of servlet is created
• jspInit() method is called
• jspService is called to handle service calls
• jspDestroy is called to destroy it when the servlet is not required.

Translation phase

During the translation phase, JSP page is translated into a servlet class. The entire static markup in the JSP page is converted into the code that writes the data to response stream. If you look at the source of the generated Servlet class you will find calls to the out.write() which write data to ServletOutputStream.

If you have following HTML code into your JSP page
JSP life cycle tutorial
It will generate code like
out.write(“JSP life cycle tutorial”)

During the translation phase JSP elements are treated as follows:
• JSP directives controls the behavior of the resultant servlet.
• Scripting elements results into the equivalent Java code.
• Custom tags are converted into the code that calls method on tag handlers.

JSP Page Compilation:

The generated java servlet file is compiled into a java servlet class.
Note: The translation of a JSP source page into its implementation class can happen at any time between initial deployment of the JSP page into the JSP container and the receipt and processing of a client request for the target JSP page.


Class Loading:

The java servlet class that was compiled from the JSP source is loaded into the container

Execution phase

JSP life cycle’s execution phase is almost similar to that of the Servlet life cycle, because ultimately it’s a servlet which is being executed. The Servlet class generated at the end of the translation phase represents the contract between container and the JSP page. According to the JSP specification the servlet class must implement the HttpJspPage interface which defines the life cycle methods.
JSP life cycle includes three methods jspInit(), _jspService() and jspDestroy()

Initialization:

jspInit() method is called immediately after the instance was created. It is called only once during JSP life cycle.
_jspService() execution:
This method is called for every request of this JSP during its life cycle. This is where it serves the purpose of creation. Oops! it has to pass through all the above steps to reach this phase. It passes the request and the response objects. _jspService() cannot be overridden.
jspDestroy() execution:
This method is called when this JSP is destroyed. With this call the servlet serves its purpose and submits itself to heaven (garbage collection). This is the end of jsp life cycle.
jspInit(), _jspService() and jspDestroy() are called the life cycle methods of the JSP.

The HttpJspPage Interface

The javax.servlet.jsp.HttpJspPage contains three methods

Public void jspInit()

This method is invoked when the JSP page is initialized. This method is similar to init() method in servlet. If you want to provide initialization for a JSP page, you define this method in declaration part of the JSP page. But most of the time you will not need to define this method.

public void _jspService
void _jspService(HttpServletRequest request, HttpServletResponse response)ThrowsIOException, ServletException
This method represents the body of the JSP page and invoked at each client request. This method is similar to service() method in servlet.
Note: You should never provide implementation _jspService() method as web container automatically generates this method based on the content of the JSP page

Public void jspDestroy()

This method is invoked just before the JSP page is destroyed by the web container. This method is similar to destroy() method in servlet. If you want to provide some cleanup code, you can define this method in declaration part of the JSP page.

Understanding the Servlet life cycle with an example

This example explains how to execute code at JSP initialization phase and destroy phase of JSP Life Cycle.
It is a simple request counter that displays how many time the page has been called or how many requests the page has received. The page declares a counter variable of type integer, the counter is set to zero when the page is initialized. Each time the page receives a request, the value of counter variable is incremented by one and displayed to user. During each life cycle stage, A message is logged to server log.
lifecycle.jsp

	<%! 
	int counter;
	public void jspInit() {
		counter = 0;
		log("The lifecycle jsp has been initialized");
	}		
	%>	
 
<html>
	<head>
		<title>JSP Life Cycle Example</title>	
	</head>
	<body>
		<%
		log("The lifecycle jsp has received a request");
		counter++;
		%>		
		<h2>JSP Life cycle : Request counter</h2>
		<p>This page has been called <%=counter %> times </p>
	</body>
</html>
	<%!
		public void jspDestroy() {
		log("The lifecycle jsp is being destroyed");
	}
	%>

Pin it