Git: how to ignore files

When working with Git you will quickly come across several files which are present in the working copy for various reasons but which should not be tracked by Git. The typical examples are logs, compiled binaries or IDE configuration files. Of course, if you don’t add them to the index and letter commit them, they will not appear in the repository.

However, before every commit you will see those files in the output of git status command which not only makes it a bit harder to read but also greatly increases a chance that you add them to the index and commit by mistake. Below is a sample output of git status with such files:

$ git status
On branch master
Changes not staged for commit:

Untracked files:
  (use "git add ..." to include in what will be committed)

        .classpath
        .project
        .settings/
        target/
        faces-config.NavData
        nb-configuration.xml
        (... more files ...)

no changes added to commit (use "git add" and/or "git commit -a")

Ignoring files

Luckily, Git makes it very easy to ignore such files so that they will no longer appear in the output of git status and therefore it will be almost impossible to mistakenly add them to the index and commit.

The most common method is to create .gitignore file in the root directory of your working copy, add there several patterns matching the files or directories to ignore (one per line) and commit it so that these rules will be shared across the entire development team.

The pattern may be either a path to the file which should be ignored:

/.classpath

a path to the directory which should be ignored (including all its contents):

/target/

or a shell pattern matching one of the above:

/*config*

The asterisk means any number of any characters as in shell. There is also possibility to specify two consecutive asterisks in a pattern which matches any number of path components. For example:

/**/server-log*

ignores all server-log* files or directories anywhere in the working copy.

Additionally, if the pattern does not contain slash, Git recursively checks and ignores all files present in the working copy and its subdirectories if their name matches specified shell glob.

Per-directory and global excludes

To make things even more complicated each subdirectory of the working copy (not only the root) may contain its own .gitignore file. This directory specific file applies only to this directory and its subdirectories and has higher level of precedence than the ones in the parent directories (including the root directory of the working copy).

Additionally, it is possible to configure global excludes which are shared across all git working copies on a single workstation. The location of the file with them is pointed by core.excludesfile variable:

$ git config --get  core.excludesfile

and can be also set to the custom path if necessary (or empty):

$ git config --global core.excludesfile /home/robert/.gitignore

The global excludes have the lowest level of precedence. They should be used only in rare cases and should never be a replacement for project specific excludes.

Which files to ignore

There are several kinds of files which should be usually ignored:

  • IDE configuration files
  • build directories
  • compiled binaries
  • generated files
  • build, test or coverage reports
  • logs

Of course, the list is not complete and the exact patterns strongly depend on your project and environment.

And if you are tempted to commit IDE configuration files, please know that everybody configures IDE in its own way which will result in a lot of merge conflicts.

Ignored files and the repository contents

Ignoring the file or directory does not mean it is no longer present in the repository or it will be automatically removed from it. The file may be still in the repository if it was stored there before adding appropriate excludes, it was a result of merge with older branch or somebody messed with excludes.

Conclusion

Ability to ignore specific files or directories is quite easy but very useful feature of Git. GitHub’s gitignore repository provides pretty good list of various git-ignore rules for many operating systems, environments and languages which you may use as a good starting point for your own project. And in case of problems you can always refer to git-ignore manual page.

Posted in Git, Version control | Tagged , , | 1 Comment

Git: how to use stash

Sometimes I have a situation that I am working on some feature on my own branch and suddenly someone comes to me and says that something really important has to be fixed or improved on the main branch. Usually it happens when I am in the middle of very important changes which are not ready to be committed for some reason.

Normally, I would have to save the changes (diff) into some file, switch to the main branch abandoning any changes, apply the fix or improvement and commit it. Then I could switch back to my own branch, apply the changes (patch) from the file and continue the work. While it is not something difficult, it can be done much easier with Git.

Basic stash usage

In Git you can store your uncommitted changes into special buffer (let’s call it stash) and at the same time undo them on the working copy:

$ git stash save [optional_message]
Saved working directory and index state WIP on master: f3b0924 Fixed title of book.
HEAD is now at f3b0924 Fixed title of book.

After this the working copy will be clean and you can easily switch to a different branch and apply the fix. You can make command shorter by omitting optional message and save command because it is assumed by default.

Once you are done with bug fixing, you can switch back to the original branch and apply the saved changes again:

$ git stash pop

It will remove the last saved changes from the stash and apply them back into your working copy. After this you can continue the work as if nothing happened.

That’s all what you will need in most cases but if you want more control read on.

Advanced stash usage

Actually, stash works almost like stack. Whenever you save your changes into stash, they are put at the top of the stack and whenever you pop them, the ones from the top of the stack are removed and applied into your working copy. If you want, you can list the contents of the stack:

$ git stash list
stash@{0}: WIP on master: f3b0924 Fixed title of book.
stash@{1}: WIP on master: f3b0924 Fixed title of book.
stash@{2}: WIP on master: f3b0924 Fixed title of book.

The latest stash entries are at the top of the list. If you forget what given stash entry contains, you can peek its contents:

$ git show 'stash@{0}'

You may also pass -p option to see full diff.

I wrote that stash is almost like a stack. It is because you are not forced to apply only the latest entry but you can apply any entry even if it is in the middle of the stack. You just have to pass its name to apply subcommand:

$ git stash apply 'stash@{1}'

If you apply it this way, it will not be removed from the list and will have to be removed manually:

$ git stash drop 'stash@{1}'

You may also run:

$ git stash pop 'stash@{1}'

which will apply the changes and then immediately drop them.

Finally, it is also possible to remove all the stash entries if you don’t need them any more:

$ git stash clear

Selecting files to stash

Command git stash save (or in short git stash) stores only the modifications made to the files tracked by Git in the stash and leaves untracked files intact. This is usually what you expect but if you want you can also include untracked files into stash by adding -u option:

$ git stash save -u [optional_message]

Creating branch from stash

At some point you may decide that stash is not enough for your needs and you may want to create a new branch from it. It is very easy:

$ git stash branch <new-branch-name> [stash-id]

The command above creates a new branch named new-branch-name, checks it out and applies the changes from specified stash to it. If the stash was not specified, the latest one is used.

As a good rule of thumb, if your stash is older than few hours and you may still need it in the future, you should create a branch from it. It is because the entries in stash are very volatile while the branches are persistent and can be also pushed into remote repository.

Conclusion

Although stash functionality is nothing advanced or complicated, it is very convenient and useful when working on multiple branches and switching between them often. If you need more information, you can always check out git-stash manual page.

Posted in Git, Version control | Tagged , , , | 10 Comments

How to parse XML documents using Streaming API for XML (StAX)

Streaming API for XML provides interface XMLStreamReader which gives a low-level but very efficient cursor-like API for reading XML documents. When using it we iterate over various events in XML document and extract information about these events. Once we are done with the current event, we move to the next one and continue. The events can be for example the start of element, the end of element or characters data.

Interface XMLStreamReader provides PULL API (compared to SAX which provides PUSH API). It means that the programmer explicitly decides when to extract next event from the XML document and can get prepared to it beforehand. In my opinion PULL interface is more straightforward to use and leads to smaller and more readable code responsible for handling of events.

Well-formedness and validation

XMLStreamReader takes care of most tasks related with parsing of XML documents like expanding entity references, unescaping special characters or handling XML namespaces. It also checks whether XML document is well-formed and raises exception when it is not the case. Unfortunately, it does not validate XML document against XML Schema so it has to be done in some other way.

General XMLStreamReader workflow

To start reading document we have to first create instance of XMLStreamReader using XMLInputFactory:

XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLStreamReader reader = inputFactory.createXMLStreamReader(inputStream);

Once we have the reader we can start iterating over events:

while (reader.hasNext()) {
  int eventType = reader.next();
  switch (eventType) {
    case XMLStreamReader.START_ELEMENT:
      // handle start element
    case XMLStreamReader.ATTRIBUTE:
      // handle attribute
    ...
}

Method hasNext checks whether there is still any event to process. If yes, we move to it using next method and we check the type of the event. All possible event types are:

  • START_ELEMENT
  • ATTRIBUTE
  • NAMESPACE
  • END_ELEMENT
  • CHARACTERS
  • CDATA
  • COMMENT
  • SPACE
  • END_DOCUMENT
  • PROCESSING_INSTRUCTION
  • ENTITY_REFERENCE
  • DTD

Depending on the type of the event we can execute different methods of XMLStreamReader interface to retrieve information about the event. For example for START_ELEMENT we can execute getName, getLocalName, hasName, getPrefix, isAttributeSpecified, getElementText and various getAttributeXXX and getNamespaceXXX methods. For event END_ELEMENT the list is less impressive because we cannot access information about attributes and in case of CHARACTERS or CDATA we can only call getTextXXX methods.

When there are no more events to process, we should close the reader to release any resources used by it:

reader.close();

Closing the reader will not close the underlying file or stream so it has to be done manually.

Example

To fully understand the flexibility of this approach let’s look at the simple XML document (which was created in my previous post):

<?xml version="1.0" encoding="UTF-8"?>
<!--Describes list of books-->
<books xmlns="http://example.com/books">
  <book language="English">
    <authors>
      <author>Mark Twain</author>
    </authors>
    <title><![CDATA[The Adventures of Tom Sawyer]]></title>
    <category>FICTION</category>
    <year>1876</year>
  </book>
  <book language="English">
    <authors>
      <author>Niklaus Wirth</author>
    </authors>
    <title><![CDATA[The Programming Language Pascal]]></title>
    <category>PASCAL</category>
    <year>1971</year>
  </book>
  <book language="English">
    <authors>
      <author>O.-J. Dahl</author>
      <author>E. W. Dijkstra</author>
      <author>C. A. R. Hoare</author>
    </authors>
    <title><![CDATA[Structured Programming]]></title>
    <category>PROGRAMMING</category>
    <year>1972</year>
  </book>
</books>

and the code which will try to parse it and will return a list of books:

package com.example.staxread;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

public class BooksReader {

    public List<Book> readFromXML(InputStream is) throws XMLStreamException {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        XMLStreamReader reader = null;
        try {
            reader = inputFactory.createXMLStreamReader(is);
            return readDocument(reader);
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    private List<Book> readDocument(XMLStreamReader reader) throws XMLStreamException {
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = reader.getLocalName();
                    if (elementName.equals("books"))
                        return readBooks(reader);
                    break;
                case XMLStreamReader.END_ELEMENT:
                    break;
            }
        }
        throw new XMLStreamException("Premature end of file");
    }

    private List<Book> readBooks(XMLStreamReader reader) throws XMLStreamException {
        List<Book> books = new ArrayList<>();
        
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = reader.getLocalName();
                    if (elementName.equals("book"))
                        books.add(readBook(reader));
                    break;
                case XMLStreamReader.END_ELEMENT:
                    return books;
            }
        }
        throw new XMLStreamException("Premature end of file");
    }

    private Book readBook(XMLStreamReader reader) throws XMLStreamException {
        Book book = new Book("", "", null, "", 0);
        book.setLanguage(reader.getAttributeValue(null, "language"));
        
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = reader.getLocalName();
                    if (elementName.equals("authors"))
                        book.setAuthors(readAuthors(reader));
                    else if (elementName.equals("title"))
                        book.setTitle(readCharacters(reader));
                    else if (elementName.equals("category"))
                        book.setCategory(readCategory(reader));
                    else if (elementName.equals("year"))
                        book.setYear(readInt(reader));
                    break;
                case XMLStreamReader.END_ELEMENT:
                    return book;
            }
        }
        throw new XMLStreamException("Premature end of file");
    }

    private List<String> readAuthors(XMLStreamReader reader) throws XMLStreamException {
        List<String> authors = new ArrayList<>();
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamReader.START_ELEMENT:
                    String elementName = reader.getLocalName();
                    if (elementName.equals("author"))
                        authors.add(readCharacters(reader));
                    break;
                case XMLStreamReader.END_ELEMENT:
                    return authors;
            }
        }
        throw new XMLStreamException("Premature end of file");

    }
    
    private String readCharacters(XMLStreamReader reader) throws XMLStreamException {
        StringBuilder result = new StringBuilder();
        while (reader.hasNext()) {
            int eventType = reader.next();
            switch (eventType) {
                case XMLStreamReader.CHARACTERS:
                case XMLStreamReader.CDATA:
                    result.append(reader.getText());
                    break;
                case XMLStreamReader.END_ELEMENT:
                    return result.toString();
            }
        }
        throw new XMLStreamException("Premature end of file");
    }
    
    private Category readCategory(XMLStreamReader reader) throws XMLStreamException {
        String characters = readCharacters(reader);
        try {
            return Category.valueOf(characters);
        } catch(IllegalArgumentException e) {
            throw new XMLStreamException("Invalid category " + characters);
        }
    }
    
    private int readInt(XMLStreamReader reader) throws XMLStreamException {
        String characters = readCharacters(reader);
        try {
            return Integer.valueOf(characters);
        } catch (NumberFormatException e) {
            throw new XMLStreamException("Invalid integer " + characters);
        }
    }
}

The most important thing is that we create several methods for reading various XML elements and we call one method from another depending on the name of the element which has just started. It clearly resembles the hierarchical structure of XML documents.

When we are reading a book in readBook method we also extract attribute language before we start iterating over events. Of course, we could iterate over events and appropriately handle ATTRIBUTE event but this approach was much easier.

Additionally, the parser can emit several CHARACTERS or CDATA events in a row so we have to concatenate their text in readCharacters method. It is possible to force the parser to emit only one such event with concatenated text by setting javax.xml.stream.isCoalescing property on XMLInputFactory before instantiating the reader. The factory also supports several other properties which you may find useful.

Conclusion

Streaming API for XML provides very good but still low-level parser for reading XML documents. This is perfect when you want to have great control over parsing or want to process only few parts of the XML document. Additionally, it is much easier to use than SAX parser and does not require building DOM tree but instead it is possible to read data directly into your own data structures.

The source code for this example you can find at GitHub.

Posted in Java, XML | Tagged , , | 1 Comment

Why I prefer Java over C++

C++ is a language I used for almost 2 years at work, for all my university projects except when there was an explicit requirement to use a different programming language and at home for very different tasks. The language alone is really powerful and well designed although the designers had to keep it compatible with C. Like every programming language, C++ has its own difficulties and problems:

  • Pointers They are one of the strongest points of C++ but are also the most difficult concept for beginners. With some experience one can get used to them and find them obvious and natural but the biggest problem is that it is very easy to overuse them and do really tricky things using pointer arithmetic. If used wrongly, they can result in an unexpected behaviour and bugs
  • Multiple inheritance The idea is simple but once you start thinking about this you can find many cases where it is not obvious what given statement or construction will do. It becomes even more complicated when inheriting from 2 or more base classes which in turn inherit from the same class. There are of course methods to resolve this ambiguity but they are not widely known and understood.
  • Templates They are ultra powerful and you can do pretty impressive things with them but it comes at very high cost. If you make a mistake when using template class or method, the compiler will often generate one or more screens full of error messages which are hard to read and does not describe root cause of the problem.
  • Handling of programming errors When accessing invalid memory location (including null pointer) or when throwing exception which is not caught anywhere, the program will abort without any good hint what was the root cause. If it happens in development environment, you can attach to the running process using debugger or analyse the backtrace. But if it happens in production, you are generally left with very little information.
  • Slow compilation Whenever I compiled larger programs in C++, I was always surprised why it takes so much time although the number of includes was minimal. The worst thing was that similar code in Java would compile much faster. I know that its not a fault of the language but rather of compiler but I think that other compilers than GCC are not much better. Slow compilation of source code generally slows down your work with all its consequences.
  • Manual memory management In C++ programmers have to manually track when the object or memory block is no longer used and have to explicitly free it. Java automates memory management which is a big step forward but still there are some problems with it.

Don’t get me wrong – I really like C++. I got used to the issues mentioned above and they are not big impediments for me. They just slow me down. I like pointers (the references in Java are very similar concept), I have no bad experience with multiple inheritance and I like templates. I fully understand why the handling of programming errors is not much better, why the compilation is slow and why memory management is done this way.

But there is still one and the biggest reason why I don’t want to use C++ at work: very poor libraries. Of course, you can say that we have famous STL and Boost in C++ but to me they are just a bunch of weird macros, even weirder templates and unnecessary inheritance. Just ask yourself whether you can easily understand how to use given Boost class by just looking at its header and how hard is to understand the compilation errors when using them wrong.

There are of course good and easy to use libraries but many of them are under GPL or other license which disqualifies them from using in commercial projects or it is necessary to pay for using them. I don’t blame these licenses because everyone is allowed to choose the best suiting license for its own software but even largest companies don’t want to pay royalties for using the licensed libraries although it could speed up the development and increase quality of software.

If you write open source software you usually have several good libraries to choose from but in commercial products you have almost no choice. To sum up we just waste our time on writing code which was written already many times before.

If you take a look at Java standard library, you will see how many features it provides. In Java SE there are classes for collections, compression, IO, networking, GUI, XML processing, security, accessing databases, sound processing just to name a few. But there is also Java EE, Spring and much more just waiting to be used and many of them on very liberal licenses. Of course, I am not saying that these libraries are perfect and Java is perfect because they are not.

But isn’t it just better to concentrate on developing your application instead of constantly reinventing the wheel?

Posted in C++, Java | Tagged , , | 3 Comments

How to write XML documents using Streaming API for XML (StAX)

Nowadays XML became a de-facto standard for storing and exchanging documents over Internet. And because it was designed to be extensible, it can be easily adapted to almost every need. In this post I would like to describe how to create and write your own XML documents using Streaming API for XML (StAX).

Need for XML writer

Of course it is possible to write XML documents using a combination of print, println or printf methods but the amount of work and the number of details to take care of would be quite large. For example when writing documents manually it is very easy to forget about escaping special characters like < or " or prepending tag with namespace prefix. Therefore, it is better to leave these cumbersome tasks to the XML writer and concentrate on the general document layout.

XMLStreamWriter

Streaming API for XML introduced in Java 6 provides quite handy interface XMLStreamWriter which can be used for writing XML files. The good thing about this API is that it does not require building any specific object structure like in DOM and does not require doing any intermediate tasks.

Additionally, XMLStreamWriter supports namespaces by default which is very useful in more advanced situations.

General XMLStreamWriter workflow

To start writing document we have to create instance of XMLStreamWriter using XMLOutputFactory:

XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
XMLStreamWriter writer = outputFactory.createXMLStreamWriter(outputStream);

Once we have the instance of XMLStreamWriter we must write header of the XML document:

writer.writeStartDocument("utf-8", "1.0");

Then we can proceed to writing elements:

writer.writeStartElement("books");

Once we have element started we can add attributes to it, write some character data or CDATA section:

writer.writeAttribute("id", "10");
writer.writeCharacters("text data");
writer.writeCData("more text data");

We can also start some other nested elements and so on.

To close opened elements we should call:

writer.writeEndElement();

It is also possible to write empty elements:

writer.writeEmptyElement("used & new");

or write comments:

writer.writeComment("Some comment");

When we are done with writing, we should finish the document and close the writer:

writer.writeEndDocument();
writer.close();

which will automatically close all opened elements and will release resources used by the writer.

Closing the writer will not close the underlying file so it has to be done manually.

Issues with XMLStreamWriter

XMLStreamWriter is not perfect so it is still possible to create not well-formed XML documents which for example contain more than one root element or miss namespace definition.

Additionally, XMLStreamWriter does not indent its output so it may be a bit hard to read using plain text editor. Therefore, for reading I suggest to open it in a web browser most of which have user-friendly interface to view structure of XML documents.

Writing XML document without namespaces

Below I would like to show a simple example how to write your own data structure into XML document. In our case it will be a list of books and a single book will be represented like this:

package com.example.staxwrite;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Book {
    private List<String> authors;
    private String title;
    private Category category;
    private String language;
    private int year;

    public Book(List<String> authors, String title, Category category, String language, int year) {
        this.authors = new ArrayList<>(authors);
        this.title = title;
        this.category = category;
        this.language = language;
        this.year = year;
    }

    public Book(String author, String title, Category category, String language, int year) {
        this (Collections.singletonList(author), title, category, language, year);
    }

    public List<String> getAuthors() {
        return Collections.unmodifiableList(authors);
    }

    public void addAuthor(String author) {
        authors.add(author);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }
    
}

The code which handles writing XML document is following:

package com.example.staxwrite;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

public class NoNSWriter {

    public void writeToXml(Path path, List<Book> books) throws IOException, XMLStreamException {
        try (OutputStream os = Files.newOutputStream(path)) {
            XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
            XMLStreamWriter writer = null;
            try {
                writer = outputFactory.createXMLStreamWriter(os, "utf-8");
                writeBooksElem(writer, books);
            } finally {
                if (writer != null)
                    writer.close();
            }
        }
    }

    private void writeBooksElem(XMLStreamWriter writer, List<Book> books) throws XMLStreamException {
        writer.writeStartDocument("utf-8", "1.0");
        writer.writeComment("Describes list of books");
        
        writer.writeStartElement("books");
        for (Book book : books)
            writeBookElem(writer, book);
        writer.writeEndElement();

        writer.writeEndDocument();
    }

    private void writeBookElem(XMLStreamWriter writer, Book book) throws XMLStreamException {
        writer.writeStartElement("book");
        writer.writeAttribute("language", book.getLanguage());

        writeAuthorsElem(writer, book.getAuthors());

        writer.writeStartElement("title");
        writer.writeCData(book.getTitle());
        writer.writeEndElement();

        writer.writeStartElement("category");
        writer.writeCharacters(book.getCategory().name());
        writer.writeEndElement();

        writer.writeStartElement("year");
        writer.writeCharacters(Integer.toString(book.getYear()));
        writer.writeEndElement();

        writer.writeEndElement();
    }

    private void writeAuthorsElem(XMLStreamWriter writer, List<String> authors) throws XMLStreamException {
        writer.writeStartElement("authors");
        for (String author : authors) {
            writer.writeStartElement("author");
            writer.writeCharacters(author);
            writer.writeEndElement();
        }
        writer.writeEndElement();
    }
}

In writeToXml method we create the output stream and the writer and ensure that they will be closed properly. Then we call writeBooksElem which will start the document, write comment, emit the list of books and will finish the document.

Most properties of a book are written as separate subelements except language which is written as an attribute. The resultant XML document should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<!--Describes list of books-->
<books>
  <book language="English">
    <authors>
      <author>Mark Twain</author>
    </authors>
    <title><![CDATA[The Adventures of Tom Sawyer]]></title>
    <category>FICTION</category>
    <year>1876</year>
  </book>
  <book language="English">
    <authors>
      <author>Niklaus Wirth</author>
    </authors>
    <title><![CDATA[The Programming Language Pascal]]></title>
    <category>PASCAL</category>
    <year>1971</year>
  </book>
  <book language="English">
    <authors>
      <author>O.-J. Dahl</author>
      <author>E. W. Dijkstra</author>
      <author>C. A. R. Hoare</author>
    </authors>
    <title><![CDATA[The Programming Language Pascal]]></title>
    <category>PROGRAMMING</category>
    <year>1972</year>
  </book>
</books>

Writing XML document with namespaces

The XML document created using code above does not contain any references to namespaces. While it may be convenient in simple cases, more advanced XML documents will refer to one or more XML namespaces.

To create document with namespace support we have to first define the prefix of the namespace we want to use:

writer.setPrefix("b", "http://example.com/books");

and emit the element with URI of this namespace:

writer.writeStartElement("http://example.com/books", "books");
writer.writeNamespace("b", "http://example.com/books");

Once we do so, we can write elements and attributes from this namespace by adding the namepace URI as the first argument of writeStartElement and writeAttribute methods. Here is the full code:

package com.example.staxwrite;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

public class NSWriter {

    private static final String NS = "http://example.com/books";
    
    public void writeToXml(Path path, List<Book> books) throws IOException, XMLStreamException {
        try (OutputStream os = Files.newOutputStream(path)) {
            XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
            XMLStreamWriter writer = null;
            try {
                writer = outputFactory.createXMLStreamWriter(os, "utf-8");
                writeBooksElem(writer, books);
            } finally {
                if (writer != null)
                    writer.close();
            }
        }
    }

    private void writeBooksElem(XMLStreamWriter writer, List<Book> books) throws XMLStreamException {
        writer.writeStartDocument("utf-8", "1.0");
        writer.writeComment("Describes list of books");
        
        writer.setPrefix("b", NS);
        writer.writeStartElement(NS, "books");
        writer.writeNamespace("b", NS);
        for (Book book : books)
            writeBookElem(writer, book);
        writer.writeEndElement();

        writer.writeEndDocument();
    }

    private void writeBookElem(XMLStreamWriter writer, Book book) throws XMLStreamException {
        writer.writeStartElement(NS, "book");
        writer.writeAttribute(NS, "language", book.getLanguage());

        writeAuthorsElem(writer, book.getAuthors());

        writer.writeStartElement(NS, "title");
        writer.writeCData(book.getTitle());
        writer.writeEndElement();

        writer.writeStartElement(NS, "category");
        writer.writeCharacters(book.getCategory().name());
        writer.writeEndElement();

        writer.writeStartElement(NS, "year");
        writer.writeCharacters(Integer.toString(book.getYear()));
        writer.writeEndElement();

        writer.writeEndElement();
    }

    private void writeAuthorsElem(XMLStreamWriter writer, List<String> authors) throws XMLStreamException {
        writer.writeStartElement(NS, "authors");
        for (String author : authors) {
            writer.writeStartElement(NS, "author");
            writer.writeCharacters(author);
            writer.writeEndElement();
        }
        writer.writeEndElement();
    }
}

and the created XML document:

<?xml version="1.0" encoding="UTF-8"?>
<!--Describes list of books-->
<b:books xmlns:b="http://example.com/books">
  <b:book b:language="English">
    <b:authors>
      <b:author>Mark Twain</b:author>
    </b:authors>
    <b:title><![CDATA[The Adventures of Tom Sawyer]]></b:title>
    <b:category>FICTION</b:category>
    <b:year>1876</b:year>
  </b:book>
  <b:book b:language="English">
    <b:authors>
      <b:author>Niklaus Wirth</b:author>
    </b:authors>
    <b:title><![CDATA[The Programming Language Pascal]]></b:title>
    <b:category>PASCAL</b:category>
    <b:year>1971</b:year>
  </b:book>
  <b:book b:language="English">
    <b:authors>
      <b:author>O.-J. Dahl</b:author>
      <b:author>E. W. Dijkstra</b:author>
      <b:author>C. A. R. Hoare</b:author>
    </b:authors>
    <b:title><![CDATA[The Programming Language Pascal]]></b:title>
    <b:category>PROGRAMMING</b:category>
    <b:year>1972</b:year>
  </b:book>
</b:books>

Write XML document with default namespace

XML also supports the idea of default namespace which increases readability and limits the typing. Using it is very similar to using namespace with explicit prefix but we have to use setDefaultNamespace and writeDefaultNamespace instead of setPrefix and writeNamespace:

package com.example.staxwrite;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

public class DefaultNSWriter {

    private static final String NS = "http://example.com/books";
    
    public void writeToXml(Path path, List<Book> books) throws IOException, XMLStreamException {
        try (OutputStream os = Files.newOutputStream(path)) {
            XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
            XMLStreamWriter writer = null;
            try {
                writer = outputFactory.createXMLStreamWriter(os, "utf-8");
                writeBooksElem(writer, books);
            } finally {
                if (writer != null)
                    writer.close();
            }
        }
    }

    private void writeBooksElem(XMLStreamWriter writer, List<Book> books) throws XMLStreamException {
        writer.writeStartDocument("utf-8", "1.0");
        writer.writeComment("Describes list of books");
        
        writer.setDefaultNamespace(NS);
        writer.writeStartElement(NS, "books");
        writer.writeDefaultNamespace(NS);
        for (Book book : books)
            writeBookElem(writer, book);
        writer.writeEndElement();

        writer.writeEndDocument();
    }

    private void writeBookElem(XMLStreamWriter writer, Book book) throws XMLStreamException {
        writer.writeStartElement(NS, "book");
        writer.writeAttribute(NS, "language", book.getLanguage());

        writeAuthorsElem(writer, book.getAuthors());

        writer.writeStartElement(NS, "title");
        writer.writeCData(book.getTitle());
        writer.writeEndElement();

        writer.writeStartElement(NS, "category");
        writer.writeCharacters(book.getCategory().name());
        writer.writeEndElement();

        writer.writeStartElement(NS, "year");
        writer.writeCharacters(Integer.toString(book.getYear()));
        writer.writeEndElement();

        writer.writeEndElement();
    }

    private void writeAuthorsElem(XMLStreamWriter writer, List<String> authors) throws XMLStreamException {
        writer.writeStartElement(NS, "authors");
        for (String author : authors) {
            writer.writeStartElement(NS, "author");
            writer.writeCharacters(author);
            writer.writeEndElement();
        }
        writer.writeEndElement();
    }
}

The created XML document refers to the namespace but there is no prefix used:

<?xml version="1.0" encoding="UTF-8"?>
<!--Describes list of books-->
<books xmlns="http://example.com/books">
  <book language="English">
    <authors>
      <author>Mark Twain</author>
    </authors>
    <title><![CDATA[The Adventures of Tom Sawyer]]></title>
    <category>FICTION</category>
    <year>1876</year>
  </book>
  <book language="English">
    <authors>
      <author>Niklaus Wirth</author>
    </authors>
    <title><![CDATA[The Programming Language Pascal]]></title>
    <category>PASCAL</category>
    <year>1971</year>
  </book>
  <book language="English">
    <authors>
      <author>O.-J. Dahl</author>
      <author>E. W. Dijkstra</author>
      <author>C. A. R. Hoare</author>
    </authors>
    <title><![CDATA[The Programming Language Pascal]]></title>
    <category>PROGRAMMING</category>
    <year>1972</year>
  </book>
</books>

Conclusion

Streaming API for XML provides very convenient, fast and memory efficient way to write XML documents without worrying about details and escaping of special characters. It is a great alternative to DOM especially when you don’t need to keep and manage DOM tree in memory for any reason.

The source code for example is available at GitHub.

Posted in Java, XML | Tagged , , | 2 Comments

Definition of Done: or why it is very risky to say that something is done

General meaning of word done may seem obvious to everybody but once you start thinking about this, it becomes clear that done may have different meanings depending on the situation and personal point of view. In this article I would like to explore this issue in scope of software development.

Meaning of done from customer/stakeholder point of view

To understand the problem with word done let’s take a quick look at a simple situation when customer politely asks whether given feature is done. If we as a project manager (or product owner in Scrum) answer yes, the customer will immediately assume that it is all ready for deployment into the production system and will ask us to do so.

What if we used the feature in the test system and we are satisfied with it but we are still in the middle of QA process or still working on such things like documentation or translations? We would have to revert our statement and this would leave us in very bad light.

The problem here is that for project manager code is ready to be shipped and this is what he carelessly called done. However, the definition of done from the customer point of view is totally different because he expects the feature to be fully ready for deployment including complete testing, documentation, translations to name few.

Meaning of done from project manager point of view

Software developers, when asked by managers whether given feature is done, often answer yes while they have just finished implementation or are in the middle of testing, ensuring code coverage or documenting. To tell the truth I have caught myself doing this many times. However, the managers assume that all these tasks were finished when they hear word done.

Need for definition of done

Misunderstandings caused by different meanings of word done can be resolved by introducing explicit definition of done which will be shared by everyone involved into the project. This definition is usually a check-list of all things which should be successfully finished before we could call the feature or task done.

Checklist

The example check-list may look like this:

  • Source code is commited to SCM
  • Source code is refactored
  • Source code has right formatting
  • Source code is documented (e.g. Javadoc)
  • Source code is reviewed
  • All units tests are passing
  • All integration tests are passing
  • All regression tests are passing
  • All load tests are passing
  • Source code coverage is high
  • Documentation is updated
  • Graphics are updated
  • Translations are updated
  • Plan how to demonstrate it to the customer is ready

Although the list may seem overwhelming, you don’t have to put them all into your own definition of done. Depending on your project, technologies, customer and other factors you may safely omit many things from this list (e.g. formatting of source code, load testing or translations). Your definition of done may also evolve over time and you may add new items to the check-list when needed. Also keep in mind that definition of done should contain reasonable minimum of things to check – don’t try to overdo this.

Conclusion

Explicit definition of done greatly reduce the chance of misunderstandings between development team, project manager and customer. Additionally, it increases code quality and also limits rework needed by ensuring that nothing important was missed.

At the end I would like to add that the same problem as with word done also happens for its synonyms (e.g. ready, finished, completed). Please, be careful when using them.

Posted in Agile, Software development practices | Tagged , | 2 Comments

JSF Facelets: templates

Facelets were introduced in JSF 2.0 to resolve common inefficiencies in JSF when creating large-scale sites. Two most useful additions provided by facelets were the ability to reuse the code through templating and to create custom composite components conveniently.

In this article I would like to describe how we can use facelets to create templates and reuse them to create multiple web pages.

Creating template

Templates encourage reuse of existing layouts and greatly reduce the potential cost necessary to modify some common parts of the web site. With templates the layout needs to be changed only in one place and the changes will be visible on multiple pages.

A template in facelets is a normal XHTML document which contains additional facelets tags. These tags are defined in namespace http://xmlns.jcp.org/jsf/facelets and by convention use prefix ui.

The most important one ui:insert is a kind of place-holder which marks the parts of the template that can be redefined by the clients of this template. Each such ui:insert tag should contain unique name so that clients can easily refer to it and can optionally have default contents to use when clients don’t want to redefine it.

The template in our example (/templates/main.xhtml) looks like this:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title><ui:insert name="title" /></title>
        <h:outputStylesheet library="default" name="css/styles.css" />
    </h:head>
    <h:body>
        <div class="header">
            <ui:insert name="header">
                <ui:include src="/sections/default-header.xhtml" />
            </ui:insert>
        </div>
        <hr/>

        <div class="data">
            <ui:insert name="data" />
        </div>

        <hr/>
        <div class="footer">
            <ui:insert name="footer">
                <ui:include src="/sections/default-footer.xhtml" />
            </ui:insert>
        </div>
    </h:body>
</html>

In this example the template defines 4 place-holders: title, header, data and footer. The header and the footer have default contents defined and this contents will be included from specified XHTML files using ui:include tags. The title and the data will be by default empty.

Header (/sections/default-header.xhtml) looks like this:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h1>
        <h:outputText value="#{msgs.nothingViewing}" />
    </h1>
</ui:composition>

and the footer (/sections/default-footer.xhtml) like this:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:graphicImage library="default" name="images/logo.png" />
    <h:outputLink value="http://en.wikipedia.org/wiki/List_of_Presidents_of_the_United_States">Check on Wikipedia</h:outputLink>
</ui:composition>

We use new tag ui:composition without any attribute (especially template attribute which will be mentioned later) to represent a sequence of elements that can be put somewhere in XHTML document. Additionally, this tag allows us to create well-formed XML document and to define XML namespaces. Note also that we are not using html, head or body tags because it might result in invalid HTML document with multiple nested html tags.

Using the template

Now once we have the template we can use it to create a simple application with two screens. First screen shows a list of few USA presidents and allows to switch to the other screen containing details about selected president.

To create a concrete web page (the client of the template) we put ui:composition element at the root of the document with attribute template pointing to the template which we want to use. Inside this element we can refer to ui:insert tags from template and replace their default contents by the contents defined inside ui:define tag.

The code for the first screen /index.xhtml is like this:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition template="/templates/main.xhtml"
             xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
             xmlns:h="http://xmlns.jcp.org/jsf/html"
             xmlns:f="http://xmlns.jcp.org/jsf/core">
    
    <ui:define name="title">
        #{msgs.presidents}
    </ui:define>
    
    <ui:define name="data" >
        <h:form>
            <h:panelGrid columns="1">
                <h:selectOneListbox value="#{presidents.selectedIndex}">
                    <f:selectItems value="#{presidents.allItems}" />
                </h:selectOneListbox>
                <h:commandButton value="#{msgs.details}" action="details" />
            </h:panelGrid>
        </h:form>
    </ui:define>
</ui:composition>

In this case the header and footer are not redefined so they will have their default contents as defined in the template.

Replacing parts of template

The seconds screen of the application is quite similar to the first one but it additionally replaces the default contents of the header, which was specified in the template, with its own contents.

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition template="/templates/main.xhtml"
             xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
             xmlns:h="http://xmlns.jcp.org/jsf/html">
    
    <ui:define name="title">
        #{msgs.presidents}: #{presidents.name}
    </ui:define>
    
    <ui:define name="header">
        <ui:param name="presidentName" value="#{presidents.name}" />
        <ui:include src="/sections/selected-header.xhtml" />
    </ui:define>

    <ui:define name="data" >
        <h:form>
            <h:panelGrid columns="1">
                <h:outputText style="text-align: center; font-size: x-large" value="#{presidents.name}" />
                #{presidents.description}
                <h:commandButton value="#{msgs.back}" action="index" />
            </h:panelGrid>
        </h:form>
    </ui:define>
</ui:composition>

The default contents of the header from the template will be discarded and the new contents of the header will be included from /sections/selected-header.xhtml file:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h1>
        <h:outputFormat value="#{msgs.currentlyViewing}">
            <f:param value="#{presidentName}" />
        </h:outputFormat>
    </h1>
</ui:composition>

Passing parameters

If you take a close look, you will notice that the included header uses parameter presidentName. This parameter is extracted from managed bean and passed to the included header using ui:param tag before the actual ui:include tag. This is the way how you can make the templates parametrizable.

It is also possible to specify ui:param elements as children of ui:include element to limit their scope.

Conclusion

Facelets are a great tool for creating and reusing templates. If used correctly, they speed up development, reduce duplication and reduce the cost of future modifications.

The source code for example is available at GitHub.

Posted in Java, Java EE, JSF | Tagged , , , | Leave a comment

Create temporary files and directories using Java NIO2

Temporary files and directories are very useful in many situations. One typical case is that you are writing some (usually large) file and you don’t want anybody to accidentally access and mess with it until is completely written and closed. Once it is ready, you just move it to the final location.

Another case is to use temporary file for processing large amounts of data in order to keep the usage of RAM in reasonable limit. This is what SQL databases do when executing queries accessing thousands or millions of rows.

Additionally, you may also use temporary files for storing intermediate results of some longer operations or storing data for undo operations or whatever you imagine.

Temporary files in Java 6 and before

If you are still using Java 6 or earlier, or you are interacting with older code, you may use the following static method of File class:

    public static File createTempFile(String prefix, String suffix) throws IOException;

This method creates empty temporary file in system-dependant default temporary-file directory (the one specified by java.io.tmpdir system property). The name of created file starts with given prefix and ends with given suffix. It also contains several randomly chosen characters in between. Prefix must be at least 3 characters long and if you pass null for second argument, default suffix of .tmp is used.

Below is a simple method creating such temporary file and writing 2 lines into it:

    private void createTempFileOldWay() throws IOException {
        File tempFile = File.createTempFile("tempfile-old", ".tmp");
        PrintWriter writer = null;
        try {
            writer = new PrintWriter(new FileWriter(tempFile));
            writer.println("Line1");
            writer.println("Line2");
        } finally {
            if (writer != null)
                writer.close();
        }
        
        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Temporary directories in Java 6 and before

Here we have to face the truth that Java 6 and earlier does not provide any convenient method to create temporary directory. Therefore, you need to manually write one based on the value of java.io.tmpdir system property.

Here is one sample way to create and write a temporary file into temporary directory. Note that this time we use version of createTempFile() method which also accepts directory where temporary file will be placed.

    private void createTempFileWithDirOldWay() throws IOException {
        File tempDir = new File(System.getProperty("java.io.tmpdir", null), "tempdir-old");
        if (!tempDir.exists() && !tempDir.mkdir())
            throw new IIOException("Failed to create temporary directory " + tempDir);
        
        File tempFile = File.createTempFile("tempfile-old", ".tmp", tempDir);
        PrintWriter writer = null;
        try {
            writer = new PrintWriter(new FileWriter(tempFile));
            writer.println("Line1");
            writer.println("Line2");
        } finally {
            if (writer != null)
                writer.close();
        }
        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Issues with temporary files and directories in Java 6 and before

Apart from lack of method for creating temporary directories, there is one additional problem. The temporary files created using methods above have very unrestricted file permissions so that (at least on my system) anybody can read it. If you are writing security-sensitive application (e.g. for encrypting data), it may be a serious issue.

New additions in Java 7

Java 7 introduced few new classes for managing files as part of NIO2. Two most interesting are Path and Files. The first one is very similar to File class but its name better describes its functionality. The second one is a simple utility class with only static methods which perform several very common operations on files.

Creating temporary files in Java 7

To create temporary file in system-dependant default temporary-directory you may use following method from Files class:

public static Path createTempFile(String prefix, String suffix, FileAttribute<?>... attrs) throws IOException;

This seems very similar to how it was done before but there are few differences. Prefix and suffix are optional and may be null. Also attributes are optional and you don’t have to pass any.

From the security point of view the most important thing is that the created temporary file have very restrictive permissions which should be acceptable for security-sensitive applications.

Here is the typical usage:

    private void createTempFile() throws IOException {
        Path tempFile = Files.createTempFile("tempfiles", ".tmp");
        List<String> lines = Arrays.asList("Line1", "Line2");
        Files.write(tempFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE);
        
        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Creating temporary directories in Java 7

The good thing is that Java 7 introduced very convenient way to create temporary directory. It is completely enough to call createTempDirectory() method of Files class with specified prefix (or with null if you don’t care about prefix) and optional attributes. That’s all. Here is an example:

    private void createTempFileWithDir() throws IOException {
        Path tempDir = Files.createTempDirectory("tempfiles");
        
        Path tempFile = Files.createTempFile(tempDir, "tempfiles", ".tmp");
        List<String> lines = Arrays.asList("Line1", "Line2");
        Files.write(tempFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE);
        
        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Deleting temporary files and directories

If you execute methods above, you will quickly notice that created temporary files are not automatically deleted and stay on the file-system long after the application finished. In reality the files may stay there for weeks or even months depending on your operating system.

The best solution is to call delete() method to delete the temporary file or directory when it is no longer needed but there three alternatives which may be useful in certain situations.

Deleting temporary file with shutdown hook

Java runtime allows to register several shutdown hooks which are the actions that will be executed once the application finishes normally. You can utilize this feature and register your own hook which will delete the file:

    private void createTempFileShutdownHook() throws IOException {
        final Path tempFile = Files.createTempFile("tempfiles-shutdown-hook", ".tmp");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                try {
                    Files.delete(tempFile);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
                
        List<String> lines = Arrays.asList("Line1", "Line2");
        Files.write(tempFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE);
        
        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Deleting temporary files using delete-on-exit

Class File from Java 6 provides method deleteOnExit() which schedules the file for deletion once the application finishes normally. The mechanism is very similar to shutdown hooks but is easier to use.

In case you have Path to the temporary file, you can easily convert it to File and call deleteOnExit() on it:

    private void createTempFileDeleteOnExit() throws IOException {
        Path tempFile = Files.createTempFile("tempfiles-delete-on-exit", ".tmp");
        tempFile.toFile().deleteOnExit();
        List<String> lines = Arrays.asList("Line1", "Line2");
        Files.write(tempFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE);

        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Deleting temporary files on close

The last alternative is to open the file with DELETE_ON_CLOSE open option. This option ensures that once you close the file, it will be automatically deleted from file-system and won’t be accessible any more. Here is an example:

    private void createTempFileDeleteOnClose() throws IOException {
        Path tempFile = Files.createTempFile("tempfiles-delete-on-close", ".tmp");
        List<String> lines = Arrays.asList("Line1", "Line2");
        Files.write(tempFile, lines, Charset.defaultCharset(), StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE);

        System.out.printf("Wrote text to temporary file %s%n", tempFile.toString());
    }

Issues with shutdown hooks and delete-on-exit

Shutdown hooks and delete-on-exit may seem like a good idea because there is no need to worry about when to delete the file. However, you should be very careful with them when building long-running applications like servers.

The first reason is that JVM has to somehow store and keep information about which files to delete which in turn increases memory usage. If you create a lot of temporary files, memory usage may become very high.

The second is that temporary files take some disc space and if they are not deleted regularly they may fill up the file-system and prevent creation of other temporary files in this and other applications. From user point of view this results in system and applications instability.

Issue with DELETE_ON_CLOSE

Open option DELETE_ON_CLOSE is also not perfect because if JVM fails to delete the file on close, it will schedule it for deletion on exit. This will in turn result in the same issues as described above.

Conclusion

Temporary files are very useful and common in many applications and Java 7 provides very convenient interface to manipulate them. The most difficult part is to properly monitor life-cycle of temporary files and delete them when they are no longer needed. It is especially important when the temporary files are large and the application runs for a long time.

Source code for examples is available as usual at GitHub.

Posted in Java | Tagged , | 2 Comments

Using JUnit, JaCoCo and Maven for code coverage

JaCoCo is quite a new tool for measuring and reporting code coverage with full support for Java 7. Currently it supports instruction, branch, line, method and class coverage which is pretty anything you can expect from this kind of tool. Additionally, it can measure and report cyclomatic complexity for methods and summarize the complexity for classes and packages.

Project setup

The steps necessary to use JaCoCo are very simple. First you need to add few unit tests to an existing project if there are none. In our simple project we have following Rectangle class:

package com.example.jacoco;

public class Rectangle {
    private int x;
    private int y;
    private int width;
    private int height;
    
    public Rectangle(int x, int y, int width, int height) {
        if (width <= 0 || height <= 0)
            throw new IllegalArgumentException("Dimensions are not positive");
        
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    
    public boolean intersects(Rectangle other) {
        if (x + width <= other.x)
            return false;
        if (x >= other.x + other.width)
            return false;
        return (y + height > other.y && y < other.y + other.height);
    }
}

and few tests for this class which should cover all possible cases:

package com.example.jacoco;

import org.junit.Test;
import static org.junit.Assert.*;

public class RectangleTestCase {
    
    @Test
    public void testCorner1() {
        Rectangle rect1 = new Rectangle(0, 0, 5, 5);
        Rectangle rect2 = new Rectangle(-2, -2, 3, 3);
        assertTrue(rect1.intersects(rect2));
        assertTrue(rect2.intersects(rect1));
    }

    @Test
    public void testCorner2() {
        Rectangle rect1 = new Rectangle(0, 0, 5, 5);
        Rectangle rect2 = new Rectangle(3, -2, 4, 4);
        assertTrue(rect1.intersects(rect2));
        assertTrue(rect2.intersects(rect1));
    }

    @Test
    public void testOutside1() {
        Rectangle rect1 = new Rectangle(0, 0, 5, 5);
        Rectangle rect2 = new Rectangle(5, 5, 4, 4);
        assertFalse(rect1.intersects(rect2));
        assertFalse(rect2.intersects(rect1));
    }

    @Test
    public void testOutside2() {
        Rectangle rect1 = new Rectangle(0, 0, 5, 5);
        Rectangle rect2 = new Rectangle(3, -2, 3, 2);
        assertFalse(rect1.intersects(rect2));
        assertFalse(rect2.intersects(rect1));
    }

    @Test
    public void testInside1() {
        Rectangle rect1 = new Rectangle(0, 0, 5, 5);
        Rectangle rect2 = new Rectangle(0, 2, 2, 2);
        assertTrue(rect1.intersects(rect2));
        assertTrue(rect2.intersects(rect1));
    }

}

The next step is to add jacoco-maven-plugin to our POM:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

This will trigger the measurement of code coverage every time unit tests are run. The results will be saved by default into target/jacoco.exec binary file.

Reporting

Manually reading the binary file is almost impossible so it is better to convert it to a more user-friendly version using command:

[robert@epsilon jacoco]$ mvn jacoco:report

Once this command finishes, the report can be found in target/site/jacoco directory in three different formats (CSV, XML and HTML). The HTML version of this report looks like this:
jacoco

Analysis

The green lines represent parts of the code which were fully covered by tests. The yellow line means that given branch was not fully covered because its condition never evaluated to true. Additionally, the next line is red because this line was never executed by our tests.
Rest of the lines are white because they do not represent any instruction.

Integration with IDE

If you use IDE, it is very likely that it provides its own support for measuring and reporting code coverage.

In Eclipse you have to install EclEmma plugin first according to official instructions. Once it is done, you can measure code coverage and see the report by clicking Coverage button on the toolbar. For details please see EclEmma user guide.

In NetBeans 7.1 or later there is no need to install plugin because it is included by default. Therefore, to measure code coverage and see the report you can select Code Coverage -> Show Report from project context-menu. The details are available at official wiki.

Integration with CI server

Jenkins provides a nice plugin for JaCoCo which can publish the report on CI server site. This way everybody can monitor code coverage without actually building and testing the software on its own machine.

The plugin also lets you define the minimum allowed values for metrics. If the actual metrics are lower than configured minimum, Jenkins will report an error during build.

For details on how to configure it please see official JaCoCo plugin page.

Conclusion

The whole idea of code coverage is to measure how good our tests are. If the metrics provided by code coverage tool are high and satisfactory, there is nothing more to do. However, if they are low, we should consider writing few more tests based on the report generated by the tool.

In our case JaCoCo showed that we should still write a unit test for situation when width or height of the rectangle is not positive.

The source code for this example can be found at GitHub.

Posted in Code coverage, Java, Maven, Software development practices | Tagged , , , , , | 3 Comments

Monitoring AJAX request lifecycle in JSF

Sometimes when working with AJAX in JSF you may find it useful to able to perform some actions before the request is sent to server, after the response is received and when some error occurs. The common case is to inform the user that some operation is in progress and may take few seconds or that the communication with server failed for some reason.

Event listeners

JSF provides optional attribute onevent for <f:ajax> tag which can point to JavaScript function that will be called at certain points of the execution of AJAX request. The prototype of the function looks like this:

function myEventListener(data) {
...
}

Argument data contains the following attributes:

  • status – Current phase of the execution of the AJAX request. Either begin, complete or success
  • type – Either event or status
  • source – The element that is the source of the AJAX request
  • responseXML – The response for the AJAX request
  • responseText – The response for the AJAX request in text format
  • responseCode – The numerical response code for the AJAX request

The begin status means that the request is about to be sent to the server, complete that the response was received and the web page is about to the rendered and success that the request was completed successfully including rendering. Note that complete does not mean that everything went fine and may also appear in case of error during rendering.
For obvious reasons responseXML, responseText and responseCode are not available when status of the AJAX request is begin.

Error listeners

JSF also provides optional attribute onerror which is quite similar to onevent but it points to the JavaScript function that will be called when error occurs during processing of AJAX request. The function also accepts only one argument data which has the same attributes. However, the possible values of status attribute are:

  • httpError – HTTP status
  • emptyResponse – Empty response was received
  • malformedXML – The response from server is not valid XML document
  • serverError – The server failed during execution of the request

Complete example

To show these 2 attributes in action, let’s take a look at a simple application that calculates and prints the value of constant pi after clicking button.

JavaScript function calculatePiListener specified by attribute onevent will be called three times at different phases of execution of AJAX request. In case of error it will be called maximum 2 times but additionally function specified by attribute calculatePiError will be called with details of the error. In either case the current status of the AJAX request will be printed at the bottom of the page.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>#{msgs.ajaxEvents}</title>
        <h:outputScript library="default" name="js/scripts.js" />
    </h:head>
    <h:body>
        <h:form prependId="false">
            <h:panelGrid columns="2">
                <h:commandButton value="#{msgs.calculatePi}" action="#{valueCalculator.calculatePi}">
                    <f:ajax event="action" execute="@this" render="piValueText"
                            onevent="calculatePiListener" onerror="calculatePiError" />
                </h:commandButton>
                <h:outputText id="piValueText" value="#{valueCalculator.hasPiValue ? valueCalculator.piValue : ''}" />
            </h:panelGrid> <br/>
            
            <h:outputText id="status" style="font-style: italic;"/>
        </h:form>
    </h:body>
</html>

Both JavaScript functions are defined in resources/default/js/scripts.js file as follows:

function calculatePiListener(data) {
    var statusElement = document.getElementById("status");
    if (data.status === "begin")
        statusElement.innerHTML = "Sent request. Waiting for response...";
    else if (data.status === "complete")
        statusElement.innerHTML = "Response received";
    else if (data.status === "success")
        statusElement.innerHTML = "Rendered successfully";
}

function calculatePiError(data) {
    var statusElement = document.getElementById("status");
    statusElement.innerHTML = "<b>Error</b> <i>" + data.status + " "
            + data.description + "</i>";
}

Because typically AJAX requests are very fast, the intermediate statuses would not normally be visible. To change it we ensure that calculatePi will execute for few seconds using the worst possible algorithm with very large number of iterations:

package com.example.ajaxevents;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class ValueCalculator implements Serializable {

    private static final long serialVersionUID = 23487237489324L;
    private Double pi = null;

    public String calculatePi() throws InterruptedException {
        double sum = 0;
        double mul = 1;
        for (int i = 1; i < 100000000; i++) {
            sum += mul / (2 * i - 1);
            mul = -mul;
        }
        
        pi = 4 * sum;
        return null;
    }

    public Double getPiValue() {
        return pi != null ? pi : 0;
    }

    public boolean getHasPiValue() {
        return pi != null;
    }
}

Conclusion

Monitoring life-cycle of AJAX requests is a very useful technique because they let you inform the user that a time-consuming action is in progress. You have also possibility to inform the user that some request failed to execute.

Complete code for this example was tested on Glassfish and is available at GitHub.

Posted in AJAX, Java, Java EE, JSF | Tagged , , , , | 1 Comment