Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 6
The reference implementation offers a simple example of how an OTP framework can be applied to an existing client/service collaboration with minimal coding, and extended to use alternate sequence algorithms and stricter client-identifier validation. You can download the RI source code anytime.
Before securing a client/service pair with an OTP scheme, interactions might flow fairly simply: the client obtains a handle to a known service and issues requests. Our sample service here provides four end points (which are of limited use but adequate for demonstration purposes):
echo returns the set of parameters provided by the client back to the client.
replace writes data into a specified file resource. It creates the file if it doesn't already exist and replaces the file if it does.
append appends data into a specified file resource. It creates the file if it doesn't already exist and appends to the file if it
does.
get obtains the contents of a specified file resource.
The client sends a sequence of clearly defined requests to a service. The requests pass or fail on the merits of completing the related work, and a response is returned, as illustrated in Figure 1.
The class model shown in Figure 2 implements the service flow shown in Figure 1.
In Figure 2's class model:
TestDriver simulates the action of the service client. It creates usable instances of SampleClient and SampleService and triggers a workflow on the SampleClient.
SampleClient is an example service-client component that issues a series of requests to an instance of SampleService (which is not secured through an OTP scheme).
SampleService is a simply modeled notional service that provides trivial echo, file-manipulation, and file-retrieval service end points.
ServiceException extends the base Java Exception, providing a single wrapper for all lower-level exceptions and meaningful exception codes and messages.
The core of the SampleClient is implemented in Listing 1.
public void doSomeWork(SampleService someService) {
try {
setup(someService);
sendRequests(someService);
cleanup(someService);
}
catch(ServiceException ex) {
SimpleLogger.error(getClass().getName() + ": " + ex);
}
}
protected void sendRequests(SampleService someService) throws ServiceException {
String scratch = "";
scratch = someService.processRequest( "echo", "Hello,", "JavaWorld" );
SimpleLogger.info("echo: " + scratch);
someService.processRequest( "replace", "/tmp/JavaWorld", "Added this note on .... " + new Date());
someService.processRequest( "append", "/tmp/JavaWorld", "Added another note on .... " + new Date());
scratch = someService.processRequest( "get", "/tmp/JavaWorld");
SimpleLogger.info(" \"get\" retrieved the following:\n" + scratch);
}
Launching the TestDriver class produces the output in Listing 2, which includes some process logging and service-resident file content.
SampleService echoing: Hello,...
echo: Hello, JavaWorld
SampleService replacing: /tmp/JavaWorld
SampleService appending: /tmp/JavaWorld
SampleService getting: /tmp/JavaWorld
"get" retrieved the following:
Added this note on .... Sun Feb 22 11:05:07 EST 2009
Added another note on .... Sun Feb 22 11:05:07 EST 2009
Listing 3 shows the main SampleService code.
package com.opensolutionspace.appl;
import java.io.*;
import com.opensolutionspace.common.*;
import com.opensolutionspace.otp.lib.OtpService;
/**
* 02/01/2009 - Simply modeled notional service ...
* provides trivial "echo", and file creation and retrieval service points
* @author lji
*
*/
public class SampleService {
protected String serviceName;
public SampleService() {
init();
}
protected void init() {
serviceName = Utility.shortClassName(this);
}
public String processRequest(String request, String... args )
throws ServiceException {
String rs = "";
try {
if("get".equalsIgnoreCase(request) ) {
rs = get(args);
}
else if("append".equalsIgnoreCase(request) ) {
append(args);
}
else if("replace".equalsIgnoreCase(request) ) {
replace(args);
}
else if("echo".equalsIgnoreCase(request) ) {
rs = echo(args);
}
else {
throw new ServiceException(ServiceException.Code.INVALID_SERVICE);
}
}
catch(Exception ex) {
throw new ServiceException(ServiceException.Code.PLATFORM_EXCEPTION, ex);
}
return rs;
}
/////////////////////////////////////////////////
// Specific service point Implementation methods
// echo(), get(), put(), replace()
/**
* echo back the provided args ...
* @param args
* @return
*/
protected String echo(String...args) {
SimpleLogger.info(" " + serviceName + " echoing: " + args[0].toString() + "..." );
StringBuffer buffer = new StringBuffer(args.length * 25);
for(String arg : args) {
if(buffer.length() > 0 )
buffer.append(" ");
buffer.append(arg);
}
buffer.append("\n");
return buffer.toString();
}
/**
* return the contents of a given file
* @param args
* @return
*/
protected String get(String...args)throws Exception {
SimpleLogger.info(" " + serviceName + " getting: " + args[0].toString() );
String file = args[0];
return Utility.fileContents(file);
}
/**
* create, or append to the file if it already exists.
* @param args
* @throws Exception
*/
protected void append(String...args) throws Exception {
put(true, args);
}
/**
* create, or append to the file if it already exists.
* @param args
* @throws Exception
*/
protected void replace(String...args) throws Exception {
put(false, args);
}
/**
* Write content to a file
* @param fileFlag
* @param args
* @throws Exception
*/
private void put(boolean fileFlag, String...args) throws Exception {
String operation = "appending";
if(fileFlag == false )
operation = "replacing";
SimpleLogger.info(" " + serviceName + " " + operation + ": " + args[0].toString() );
String file = args[0];
String log = args[1];
Utility.writeToFile(file, log, fileFlag);
}
public String getServiceName() {
return serviceName;
}
}