Hello.
I'm currently evaluating the Reslet API in order to implement web
services for our site. However, I've encountered a frustrating hurdle
from the very start. First of all, considering the vast majority of
web services output XML, i find it surprising that i can't find ANY
examples of the RESTlet api that use anything other than plain text.
Perhaps this issue is the reason?
As you can see in the code below, I have made a simple xhtml document
using JDom and RESTlets. It's pretty standard. The problem is, even
with this simple example, the xml does not validate! There are two
errors:
1. the doc type is rendered incorrectly - without a space between the
public and system ids - so the xml is not well formed.
2. Somewhere along the path the mysterious <META http-equiv="Content-
Type" content="text/html; charset=UTF-8"> got inserted - and it's not
properly closed, which results in a mismatched tag parsing error.
Attempting to debug this I've printed out both the jdom Document and
printed the elements of the org.w3c.dom.Document and neither has this
mysterious meta line, so where does it get inserted? Is it some
configuration parameter I've overlooked in Tomcat? A problem with
JDom? Or is it a problem within RESTlet itself? The results seem to
point to the latter.
Here's the code:
##### /api/RestApplication.java ###########################
package api;
import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Router;
import org.restlet.Restlet;
public class RestApplication extends Application
{
public RestApplication(Context context)
{
super(context);
}
@Override
public synchronized Restlet createRoot()
{
Router router = new Router(getContext());
// Defines only one route
router.attachDefault(XmlResource.class);
return router;
}
}
##### /api/XmlResource.java ###########################
package api;
import org.restlet.Context;
import org.restlet.resource.*;
import org.restlet.data.*;
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.DocType;
import org.jdom.output.DOMOutputter;
import org.jdom.output.XMLOutputter;
import org.jdom.output.Format;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import java.io.IOException;
public class XmlResource extends Resource
{
static Logger logger = Logger.getLogger(XmlResource.class);
public XmlResource(Context context, Request request, Response response)
{
super(context, request, response);
getVariants().add(new Variant(MediaType.APPLICATION_XHTML_XML));
}
@Override
public Representation getRepresentation(Variant variant)
{
if
(variant.getMediaType().equals(MediaType.APPLICATION_XHTML_XML))
{
try
{
DomRepresentation rep = new
DomRepresentation(MediaType.APPLICATION_XHTML_XML);
Element root = new Element("html");
Element head = new Element("head");
head.addContent(new Element("title").addContent("My
Title"));
root.addContent(head);
Element body = new Element("body");
body.addContent("My text");
root.addContent(body);
Document doc = new Document(root);
doc.setDocType(new DocType(
"html",
"-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"));
DOMOutputter out = new DOMOutputter();
rep.setDocument(out.output(doc));
System.out.println("jdom doc: ");
print(doc);
System.out.println("w3c doc: ");
print(rep.getDocument());
return rep;
}
catch (IOException e)
{
logger.error(e.getMessage(), e);
}
catch (JDOMException e)
{
logger.error(e.getMessage(), e);
}
}
else
{
logger.error("Couldn't serve this:
"+variant.getMediaType().getDescription());
}
return null;
}
protected static void print(Document doc)
{
try
{
XMLOutputter xout;
Format f = Format.getPrettyFormat();
f.setEncoding("UTF-8");
xout = new XMLOutputter(f);
xout.output(doc, System.out);
}
catch (IOException e)
{
logger.error(e.getMessage(), e);
}
}
protected static void print(org.w3c.dom.Document doc)
{
System.out.println(print(doc.getDocumentElement()));
}
protected static String print(org.w3c.dom.Node elem)
{
if(elem.hasChildNodes())
{
NodeList children = elem.getChildNodes();
StringBuffer result = new StringBuffer();
result.append("<").append(elem.getNodeName()).append(">");
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
result.append(print(node));
}
result.append("</").append(elem.getNodeName()).append(">\n");
return result.toString();
}
else
return elem.getTextContent();
}
}
##### /WEB-INF/web.xml ###########################
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>rest app</display-name>
<context-param>
<param-name>org.restlet.application</param-name>
<param-value>api.RestApplication</param-value>
</context-param>
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>
com.noelios.restlet.ext.servlet.ServerServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
##### System.out ###########################
jdom doc:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
">
<html>
<head>
<title>My Title</title>
</head>
<body>My text</body>
</html>
w3c doc:
<html><head><title>My Title</title>
</head>
<body>My text</body>
</html>
##### Browser result ###########################
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>My Title</title>
</head>
<body>My text</body>
</html>
######################################
I'm using Tomcat/6.0.14 for the container and JDom1.1. I tried this
with both the 1.08 and 1.1m2 RESTlet releases, and they both give
exactly the same result!
Can anyone tell me how to get around this?! It seems like a good api.
It would be a shame to be forced to abandon it for such a trivial issue.
--
-Elliot Long
email: [EMAIL PROTECTED]
www: http://www.hypnotoad.co.uk
skype: thehypnotoad