Generating Callbacks For JSONP Code

Here’s a code snippet demonstrating how to wrap JSON text within a JSONP response.

The text of the JSON object is in the string json. The variable resp represents a HttpServletResponseobject. Callback represents contents of the HTTP parameter callback , which should be set with the name of the Javascript function to call. Before calling this code, it’s a good idea to validate that parameter.

String callback = req.getParameter("callback");
String json_text = callback + "(" + json + ");";
resp.getWriter().println(json_text);

Here’s an example of a simple JSONP response:

findIP({"ip": "8.8.8.8"});

This response will call the JS function findIP (the callback parameter contents), with an object containing the property ip (the JSON data).

Extracting Files From A Zip File

Here’s a code snippet demonstrating how to download a zip file and extract the files contained within.

The variable zip_url_string represents the URL to download the zip file from. To read in each file, put your code after the BufferedReader statement.

/**
 * Our first task is to grab the file, and open up a ZipInputStream to decompress the file.
 * A ZipEntry processes each entry within the ZipInputStream.
 */
URL url_addr = new URL(zip_url_string);
HttpURLConnection con = (HttpURLConnection)url_addr.openConnection();
InputStream fis = con.getInputStream();
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry entry = zis.getNextEntry();
/**
 * We are going to loop through each ZipEntry until we get to a null entry (which 
 * represents the end of the ZipEntry list within the ZipInputStream).
 **/
while (entry != null) {
    //Collect the entry name. This is the filename, including any directory information.
    //Do any validation or processing needed.
    String entry_name = entry.getName().trim();
    //Create a BufferedReader to read in the contents of this file contained within the zip.
    InputStreamReader isr = new InputStreamReader(zis);
    BufferedReader reader = new BufferedReader(isr);
    /**
     * Do something here with the file. Use BufferedReader to read it in, then  
     * process it as necessary.
     */
    //Grab the next entry for processing
    entry = zis.getNextEntry();
}//end while loop going through ZipEntry entries

If the zip file being downloaded is especially large, you may want to add a longer timeout:

con.setConnectTimeout(milliseconds_to_wait);

Remember to add the appropriate import statements:

import java.net.URL;
import java.net.HttpURLConnection;
import java.io.InputStream;
import java.util.zip.*;

Removing EXIF Data With ImageMagick

Recently I needed to find a way to mass-remove EXIF data from multiple images. EXIF – if you didn’t know – is essentially metadata included within images. This metadata can include the name of the camera, the GPS coordinates where the picture was taken, comments, etc.

The easiest way is to remove EXIF data is to download ImageMagick and use the mogrify command line tool:

mogrify -strip /example/directory/*

ImageMagick can be run within a Compute Engine VM to make it available to a web application. Here’s the command to install ImageMagick:

sudo aptitude install imagemagick

Java GET Using java.net

Here’s a simple code snippet showing how to fetch the contents of a URL. The URL to fetch is in the string url_string , and html stores the contents of the fetched file.

URL url = new URL(url_string);
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String html = "";
String line = "";
while ((line = reader.readLine()) != null) {
    html += line;
}
reader.close();

This code may throw a java.io.IOException if an error is encountered while fetching the URL.

This code requires the below imports:

import java.net.URL;
import java.io.InputStreamReader;
import java.io.BufferedReader;

A Simple Backends.XML File For Java Deployments

Here’s a simple example of the XML required to set up a backend:

<backends>
    <backend name="worker">
        <class>B2</class>
        <options>
            <dynamic>true</dynamic>
            <public>true</public>
        </options>
    </backend>
</backends>

This sets up a B2 class backend named worker which can be addressed at the URL worker . APPLICATION-ID . appspot . com . Save this as backends.xml in the /war/WEB-INF/ directory.

Access-Control-Allow-Origin In JSONP Responses

A quick note for today: JSONP responses need to include an Access-Control-Allow-Origin header set to a wildcard. If this header isn’t included, browsers won’t allow JSONP responses to be read in by Javascript.

The header key and value should look like this:

Access-Control-Allow-Origin: *

Here’s an example of this header in Java:

resp.setHeader("Access-Control-Allow-Origin", "*");

The variable resp represents a HttpServletResponse reference. Make sure to add this line before writing the body of the response to the client.

Communicating With Sockets On Compute Engine

Writing custom applications on Compute Engine requires the use of sockets to communicate with clients. Here’s a code example demonstrating how to read and write to sockets in Java.

Assume that client_socket is the socket communicating with the client:

/**
 * Contains the socket we're communicating with.
 */
Socket client_socket;

Create a socket by using a ServerSocket (represented by server_socket ) to listen to and accept incoming connections:

Socket client_socket = server_socket.accept();

Then extract a PrintWriter and a BufferedReader from the socket. The PrintWriter out object sends data to the client, while the BufferedReader in object lets the application read in data sent by the client:

/**
 * Handles sending communications to the client.
 */
PrintWriter out;
/**
 * Handles receiving communications from the client.
 */
BufferedReader in;
try {
    //We can send information to the client by writing to out.
    out = new PrintWriter(client_socket.getOutputStream(), true);
    //We receive information from the client by reading in.
    in = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
    /**
     * Start talking to the other server.
     */
    //Read in data sent to us.
    String in_line = in.readLine();
    //Send back information to the client.
    out.println(send_info);
}//end try
catch (IOException e) {
    //A general problem was encountered while handling client communications.
}

A line of text sent by the client can be read in by calling in.readLine() demonstrated by the in_line string. To send a line of text to the client, call out.println(send_info) where send_info represents a string. If an error occurs during communication, an IOException will be thrown and caught by the above catchstatement.

Remember to add the following imports:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.BufferedReader;

App Engine Default Time & Date

The default time zone for the Java runtime on App Engine is UTC (frequently referred to as GMT). The following code will record the current time and date in UTC:

Date current_date = new Date();
String date = new java.text.SimpleDateFormat("MM-dd-yyyy").format(current_date);
String time = new java.text.SimpleDateFormat("hh:mm:ss aa").format(current_date);

For instance, date would be set to 09-21-2013 (September 21, 2013) and time would be set to 01:40:42 AM . If your application needs to record time in a different time zone, use the setTimeZone method of SimpleDateFormat .

Don’t forget to import the Date class:

import java.util.Date;

HTTP POST URLFetch Using The Low Level Java API

Here’s a code snippet demonstrating how to generate a POST request using the low level urlfetch API.

The variables post_url and post_data represent the request URL and the content of the POST as strings. The response from the urlfetch is stored in response_content . If the request was unsuccessful (the target server returned a non-200 HTTP status code) a RuntimeException will be thrown.

HTTPRequest request = new HTTPRequest(new URL(post_url), HTTPMethod.POST);
request.setHeader(new HTTPHeader("User-Agent", "Example Application"));
request.setPayload(post_data.getBytes("UTF-8"));
HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);
//If the response wasn't successful, throw an exception.
if (response.getResponseCode() != 200) {
    throw new RuntimeException("Response code was not 200: " + response.getResponseCode());
}
String response_content = new String(response.getContent());

Remember to import the URLFetch library:

import com.google.appengine.api.urlfetch.*;