ACET




REST tutorial

Handling the POST verb

In the last two sections, we created a way of viewing the contents of our database. So far, so Web 1.0. However, we still don’t have any way of getting data into the database. A good way of doing this is to use the POST verb to send the new data to the URI of the collection that you want the data to be added to.

Thus, in our case, we will accept POST requests to /item, containing data in the same format as our GET service returns – one key-value pair per line, with colons separating the keys and the values.

This is probably the most complex and error-prone part of any REST server, as it requires parsing input data from the outside world. From a security (and reliability) point of view, this is a major problem, as the data could be anything. Our implementation will ignore pretty much all such issues for simplicity.

Recognising the POST verb

We first need to add a small section to the service() method of our servlet, to recognise a POST request to add a new auction item, and despatch it to the right function.

At the end of the function, add a section to the if statement:

		if(verb.equals("GET")) {
			handleGetItem(item_id, response);
		} else if(verb.equals("POST") && item_id == -1) {
			ServletInputStream input = request.getInputStream();
			handlePostItem(input, response);
		}

Note that we’re passing the request data stream into the POST-handler function. This contains the data for the new item. We also only allow POST requests if no item was selected in the URI, with the condition item_id == -1.

POST handler for items

Create an empty function for handling POST requests

	public void handlePostItem(ServletInputStream input,
	   HttpServletResponse response)
		throws IOException, ServletException
	{
		try {
			// The core code of the function goes here
		} catch(SQLException ex) {
			ex.printStackTrace(System.err);
			sendInternalError(response, "SQL Exception");
			return;
		}
	}

Parse the input data

Now we need to parse the input data. Our data format is simply one data item per line, with a tag, followed by a colon, followed by the remainder of the data. This is fairly easy to parse, as long as nothing goes wrong. It won’t handle things like new lines in the middle of text, though.

In the try block, add a hash map to store the values read in from the POST request, and set some default values:

		Map<String, String> parsed_input = new HashMap<String, String>();
		// Set up some default values
		parsed_input.put("title", "Default title");
		parsed_input.put("description", "Default description");
		parsed_input.put("reserve", "0.00");

Now we can parse the input data:

		byte[] buffer = new byte[1024];

		int bytes = input.readLine(buffer, 0, 1023);
		while(bytes >= 0) {
			// Warning: This code doesn't handle lines longer than
			// 1024 bytes very well.
			String line = new String(buffer, 0, bytes);
			String[] parts = line.split(":", 2);

			// Error checking: input line doesn't contain a colon: ignore it
			if(parts.length < 2) {
				continue;
			}

			// Store the results of parsing this line
			parsed_input.put(parts[0].trim(), parts[1].trim());
			// Get the next line of input
			bytes = input.readLine(buffer, 0, 1023);
		}

Add the item to the database

Having parsed the input into the parsed_input hash, we can create a new item in the database.

		// Now post a new item into the database
		String sql = "INSERT INTO item"
			+ " (title, description, reserve, expiry)"
			+ " VALUES (?, ?, ?, ?)";
		PreparedStatement stmt = db_connection.prepareStatement(sql);

		stmt.setString(1, parsed_input.get("title"));
		stmt.setString(2, parsed_input.get("description"));
		double reserve = Double.parseDouble(parsed_input.get("reserve"));
		stmt.setDouble(3, reserve);
		// Finish time is 7 days from now
		Timestamp finish = new Timestamp(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7);
		stmt.setTimestamp(4, finish);

		stmt.execute();

		// Ensure that the update gets sent to the disk
		flush_db.execute();

Recompile your code, in $CATALINA_HOME/webapps/auction/WEB-INF/classes, with:

(In Linux) javac -cp $CATALINA_HOME/lib/servlet-api.jar:../lib/hsqldb.jar AuctionServer.java

(In Windows) javac -cp %CATALINA_HOME%\lib\servlet-api.jar;..\lib\hsqldb.jar AuctionServer.java

You will also need to visit the Tomcat manager page at http://localhost:8080/manager/html/ and reload your servlet. This will update the servlet to the new version of your code.

In the next section, we will teach our client app to use this new server interface, and add new items to the database.

Valid XHTML | Copyright | Last Modified: 1/Apr/2009 |