Take the 2-minute tour ×

Background: I have a webservice that previously only received requests for xml, but now needs to return html for browser access. I have a Java class that is mapped to XML with the XmlRootElement annotation.

I am using Freemarker to generate HTML based on this Java class, but cannot find a way to do so directly.

At the moment I use NodeModel.parse to parse the xml to a freemarker datamodel, but since the NodeModel.parse takes a File, I first write the Java object to a file. That is obviously an inefficient way to do it, but it does the job.

Does anyone know a way to go get a freemarker datamodel out of a this Java class without first writing it to an XML file?

The following is my code:

The Java-to-Schema mapped class:

@XmlRootElement(name = "report")
public class Report {
    private String id;  
    private String time;    

    public Report() {}

    public String getTime() {return time;}
    public void setTime(String time) {this.time = time;}

    public String getId() {return this.id;}    
    public void setId(String id) {this.id = id;}    

Merging the data with the template:

public String getReportsAsHtml(@QueryParam("lastUpdate") String lastUpdate){
    MySQLAccess dao = new MySQLAccess();
    List<Report> reports = dao.readReports(lastUpdate);
Template  temp = TemplateConfiguration.getInstance().getTemplateConfiguration().getTemplate("list_template.ftl");
    **HashMap<String, NodeModel> root = new HashMap<String, NodeModel>();**
    **root.put("doc", NodeModel.parse(Java2XML.getXMLFromJava(reports)));**
    StringWriter output = new StringWriter();
    temp.process(root, output);
    return output.toString();
share|improve this question
Since you already had the XML, you could use XSLT to output HTML or just about anything. –  Viruzzo Jan 13 '12 at 15:17
I don't already have the XML. I have a list of objects annotated with Schema-to-Java annotation. –  Videre Jan 16 '12 at 7:59
I meant that you already have the generation code for that part. –  Viruzzo Jan 16 '12 at 8:50
add comment

2 Answers

up vote 1 down vote accepted

NodeModel has a wrap(org.w3c.dom.Node) method, so you surely don't have to create an XML file. All you need is a tree of org.w3c.dom.Node objects, and FreeMarker doesn't care where it comes from. Actually, if you are using the default object-wrapper of FreeMarker, you don't even need to deal with NodeModel, just drop the org.w3c.dom.Node into the data model as any other POJO, and FreeMarker will recognize it as XML.

Also note that FreeMarker has this ObjectWrapper abstraction. It separates the actual objects from how they are seen from the templates. So you possibly doesn't even need to make a tree of Node-s from those objects, just make an ObjectWrapper implementation that directly understands those annotated object. See how DefaultObjectWrapper extends BeansWrapper, automatically wrapping Node-s, Jython object, etc. You can follow the same pattern. But of course writing your own ObjectWrapper is extra work, especially if you need XPath support too (hint: Jaxen doesn't need Node-s).

share|improve this answer
Thanks. The point is that I already have a tree structure in the form of a POJO annotated with Java-to-Schema annotations, and I was hoping that FreeMarker would be able to recognize this structure. In lack of that, would you expand on how I get a tree of Node objects to drop into the data model? –  Videre Jan 16 '12 at 7:55
FreeMarker doesn't recognize those annotations out-of-the-box, but, as I said, it's extendable to do that. So, how you get a tree of Node-s from those POJO-s also falls outside FreeMarker's out-of-the-box functionality. The thing that creates XML files from them can't return a tree of Node-s instead? –  ddekany Jan 16 '12 at 13:52
add comment

I have used the following code to generate a Node tree from a Java-to-Schema annotated class:

public static Node getNodeFromReport(Object report){
    JAXBContext context = JAXBContext.newInstance(report.getClass());
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

    DocumentBuilderFactory docFac = DocumentBuilderFactory.newInstance();
    Document result = docFac.newDocumentBuilder().newDocument();

    marshaller.marshal(report, result);

    return result;
share|improve this answer
add comment

Your Answer


