So what would a RESTFul Service require:
- It needs to talk HTTP, which means it should at least be able to handle GET requests.
- Dynamic resources are required. They are generated dependent on the request parameters those the client passes to the server. The resources must be mapped to URL-s.
- A basic authentication should work. So it's only possible to access a specifc resource if a previous authentication was successful.
So a very simple HTTP server was developed. One advantage of it is that you do not need a Servlet Container in order to host the service (Yes, we could have used the Endpoint classes of Java ...). It's now possible to provide several services on several ports, even if you deploy the jCoreDB core to a servlet container like Tomcat. So the services are Servlet Container independent. Back to the HTTP Server: My HTTPServer class implements the IServer interface. This means that it has a 'start', 'stop' and 'status' method. The primarily method is named 'doGet'. It has 3 parameters 'getHeader', 'authHeader' and 'out'. The first one is used to pass the GET request information. The second one contains the basic HTTP authentication information. 'out' is a printstream which is used to return the result to the client. The next part of this lightweighted REST framework is an abstract class (implements IResource) with the name AResource. Such a resource gets constrcuted by passing a Hashmap of parameters and the target output stream. AResource has one abstract method which is named 'create'. This method is used to create the dynamic resource on demand. Such a resource needs to be annotated in order to map it to an URL. Therefore the annotation interface WebResourceURL was created. Then Java's reflection mechanisms are used to find the resource which is mapped to a specific URL. Here the source code to create the resource as part of the HTTP server's doGET method:
Class c = HTTPResourceFinder.getClassByURL(urlprefix);
if (c != null) {
Constructor ctx = c.getConstructor(new Class[] {
PrintStream.class,
new HashMap<string, string="">().getClass() });
Object[] args = new Object[] { out, getParams(url) };
IHTTPResource resource = (IHTTPResource) ctx.newInstance(args);
resource.create();
}
The annotation interface looks quite simple:
@Retention(RetentionPolicy.RUNTIME)
public @interface WebResourceURL {
String value();
}
To get the list of available containers a ContainerListResouce was created. Here its code:
@WebResourceURL(value = "/listcontainers")
public class ContainerListResource extends AHTTPResource {
public ContainerListResource(PrintStream out, HashMap<String, String> params) {
super(out, params);
}
@Override
public void create() {
IFileSystem fs = FileSystemRegistry.get(Configs.getFSConfig().getRootDir());
IContainer[] cs = fs.getContainers();
out.println("{");
out.println("\"containers\":" + "[");
for (int i = 0; i < cs.length; i++)
{
IContainer c = cs[i];
if (i < cs.length-1) out.println("{\"id\":" + c.getId() + "}" + ",");
else out.println("{\"id\":" + c.getId() + "}");
}
out.println("]");
out.println("}");
}
}
Another resource is the one to get a specific container details:
@WebResourceURL(value="/container")
public class ContainerResource extends AHTTPResource{
/**
* The container's id
*/
int id;
/**
* The resource constructor
* @param out
*/
public ContainerResource(PrintStream out, HashMap<String,String> params) {
super(out, params);
this.id = Integer.parseInt(params.get("id"));
}
@Override
public void create() {
IFileSystem fs = FileSystemRegistry.get(Configs.getFSConfig().getRootDir());
IContainer c = fs.getContainer(id);
if (c!=null)
{
out.println("{");
out.println("\"id\":" + c.getId() + ",");
out.println("\"parentpath\":" + "\"" + c.getParentPath() + "\"" + ",");
out.println("\"numofsegs\":" + c.getNumOfSegs() + ",");
out.println("\"segments\":" + "[");
for (int i = 0; i < c.getSegments().length; i++)
{
ISegment s = c.getSegments()[i];
if (i < c.getSegments().length-1) out.println("{\"id\":" + s.getId() + "}" + ",");
else out.println("{\"id\":" + s.getId() + "}");
}
out.println("]");
out.println("}");
}
else
{
out.println("{");
out.println("}");
}
}
...
}
I will soon publish the source code of the above mentioned components. So maybe you like this lightweighted RESTFul Web Service framework ( only a few classes: HTTPServer, HTTPConstants, HTTPResourceFinder, IResource, AResource, WebResourceURL) which exists now in the context of jCoreDB.
No comments:
Post a Comment