Java-Web:Exercises - Using a factory for creating XML or JSON

From Juneday education
Jump to: navigation, search

Work in progress

This page is still work in progress. We will eventually remove this section when we feel that the chapter is good enough(TM) and the amount of bug reports from our experts, the students, decline.

Introduction

Your task is to add a format for the application from the presentation in the previous chapter "Using a factory for creating XML or JSON.

You should add a format, CSV, to the application so that the user can choose CSV as the output format. You will see that the application will not change other than you're adding of the new formatter class (and a small addition to the settings XML file).

Getting started

Download the following directory [1] and all its contents. You may clone the entire java-web directory from here and copy the java-web/dynamic-factory/presentation-sources directory, or use the service on this web page, using a browser.

Enter the directory and confirm that you can run the application and select either XML or JSON. See the file build-and-run.txt for instructions for how to build and run the application.

Expand using link to the right to see a hint.

$ javac -cp .:org/henrikard/student/resources/javax.json.jar org/henrikard/student/*/*.java && java -cp .:org/henrikard/student/resources/javax.json.jar:org/henrikard/student/resources/sqlite-jdbc-3.8.11.2.jar -DformatsXML=formats.xml org.henrikard.student.main.Main json
Loading formatters...
Loading formats file: formats.xml
xml formatter found, loading class: org.henrikard.student.formats.XMLFormatter
json formatter found, loading class: org.henrikard.student.formats.JsonFormatter
All students as application/json:

{
    "students":[
        {
            "studentName":"Anna Andersson",
            "studentID":1
        },
        {
            "studentName":"Beata Bengtssson",
            "studentID":2
        },
        {
            "studentName":"Cecilia Carlsson",
            "studentID":3
        },
        {
            "studentName":"David Davidsson",
            "studentID":4
        },
        {
            "studentName":"Erik Eskilsson",
            "studentID":5
        },
        {
            "studentName":"Fader Fourah",
            "studentID":6
        }
    ]
}

$ $ javac -cp .:org/henrikard/student/resources/javax.json.jar org/henrikard/student/*/*.java && java -cp .:org/henrikard/student/resources/javax.json.jar:org/henrikard/student/resources/sqlite-jdbc-3.8.11.2.jar -DformatsXML=formats.xml org.henrikard.student.main.Main xml
Loading formatters...
Loading formats file: formats.xml
xml formatter found, loading class: org.henrikard.student.formats.XMLFormatter
json formatter found, loading class: org.henrikard.student.formats.JsonFormatter
All students as application/xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<STUDENTS>
  <STUDENT id="1">
    <NAME>Anna Andersson</NAME>
  </STUDENT>
  <STUDENT id="2">
    <NAME>Beata Bengtssson</NAME>
  </STUDENT>
  <STUDENT id="3">
    <NAME>Cecilia Carlsson</NAME>
  </STUDENT>
  <STUDENT id="4">
    <NAME>David Davidsson</NAME>
  </STUDENT>
  <STUDENT id="5">
    <NAME>Erik Eskilsson</NAME>
  </STUDENT>
  <STUDENT id="6">
    <NAME>Fader Fourah</NAME>
  </STUDENT>
</STUDENTS>

$

Add the formatter for CSV

The idea behind this application architecture, is that you can add formatters by implementing the interface org.henrikard.student.formats.Formatter shown here:

package org.henrikard.student.formats;

import java.util.List;

import org.henrikard.student.domain.Student;

public interface Formatter{
    public void   loadFromList(List<Student> list);
    public String getDocument();
    public String getContentType();
}

Create the class org.henrikard.student.formats.CSVFormatter in the appropriate directory.

You'll need to import org.henrikard.student.domain.Student and java.util.List .

Make sure the class implements the Formatter interface. Implement the three methods. The challenge (it is not hard!) is the loadFromList() method - where you will loop through the list of Student references and build up the CSV (comma-separated values) text and store it in an instance variable document. Look at how the other formatters do it for inspiration.

Expand using link to the right to see a hint.

  public void loadFromList(List<Student> list) {
    // Start with a row with the headers:
    StringBuilder result = new StringBuilder("name,id\n");
    for(Student student : list) {
      result.append(student.name())
        .append(SEPARATOR)
        .append(student.id())
        .append("\n");
    }
    // Store in the document instance variable:
    document = result.toString();
  }

The getDocument() method should simply return the instance variable document. The getContentType() method can return a String with the contents "text/csv".

Add the static block which registers your formatter with the formatter factory

Make a no-arguments constructor for your CSVFormatter class and make it private so that no one can instantiate your class.

Expand using link to the right to see a hint.

  private CSVFormatter() {

  }

Make a private static instance reference of your class and call it instance

Expand using link to the right to see a hint.

  private static CSVFormatter instance;

Next, add a static block to your class, in which you instatiate the static variable instance and register it with FormatterFactory.registerFormatter("csv", instance);.

Expand using link to the right to see a hint.

  static {
        instance = new CSVFormatter();
        FormatterFactory.registerFormatter("csv", instance);
  }

Compile your class.

Add the new formatter to formats.xml

Add an entry like this to the formats.xml file:

<entry key="csv">org.henrikard.student.formats.CSVFormatter</entry>

Run the application and confirm that you can now choose also CSV as format

Compile and run the application:

$ javac -cp .:org/henrikard/student/resources/javax.json.jar org/henrikard/student/*/*.java && java -cp .:org/henrikard/student/resources/javax.json.jar:org/henrikard/student/resources/sqlite-jdbc-3.8.11.2.jar -DformatsXML=formats.xml org.henrikard.student.main.Main csv
Loading formatters...
Loading formats file: formats.xml
csv formatter found, loading class: org.henrikard.student.formats.CSVFormatter
xml formatter found, loading class: org.henrikard.student.formats.XMLFormatter
json formatter found, loading class: org.henrikard.student.formats.JsonFormatter
All students as text/csv:
name,id
Anna Andersson,1
Beata Bengtssson,2
Cecilia Carlsson,3
David Davidsson,4
Erik Eskilsson,5
Fader Fourah,6

$

What we have tried to show you here, is an architecture similar to the one used by JDBC, for adding third party "drivers" (in our case, formatters) which will plug-in fine into an existing application. Note that you didn't change a single line of code in the existing application, you simply added a class and a line in the formats.xml file.

Links

Source code

The solution can be found here in the github repository.

Navigation

Up next: A Servlet serving XML or JSON!

« PreviousBook TOCNext »