Tag Archives: Java

Logback is wonderful (Part 2)

My second post about Logback presents a truly wonderful feature: it can reconfigure itself automatically when the configuration file changes. This means that your application do not have to be restarted when you modify logback.xml.

The following configuration file demonstrates how to use this feature:

<configuration debug="true" scan="true" scanPeriod="5 seconds">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ALL</level>
        </filter>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="ALL">
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

If the value of the scan attribute on the configuration element is true, Logback will scan for changes in the configuration file periodically.

The value of the scanPeriod attribute on the configuration element determines how often Logback will look for changes in the configuration. Values can be specified in units of milliseconds, seconds, minutes or hours. For example, the following are all valid values for the scanPeriod attribute: 1500 milliseconds, 1 second, 0.5 minute, 2 hours, 1 day.

Each time the configuration file changes the logging system will automatically re-configure itself accordingly.

To play with this handy feature download this project. (Building the project requires Apache Maven.) Run the my.Main class that will bring up a window in which the logback.xml file can be edited. The program writes log messages to the console in an infinite loop using a timer.

Modify and save the configuration to see the effects immediately. For example, change the content of the level element to OFF in line 5 to completely disable logging on the console. To log messages at or above the WARN level use the value WARN instead.

Toy example that demonstrates automatic re-configuration


Logback is wonderful, isn’t it?

Advertisements
Tagged

Logback is wonderful (Part 1)

Logback is a wonderful logging framework written in Java and distributed under the GNU Lesser General Public License v2.1 and the Eclipse Public License v1.0.

Its functionality can be accessed via the SLF4J API that Logback implements natively. The following toy example demonstrates how to use Logback:

package my;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {

    private static Logger logger = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        logger.error("This is an ERROR message");
        logger.warn("This is a WARNING message");
        logger.info("This is an INFO message");
        logger.debug("This is a DEBUG message");
        logger.trace("This is a TRACE message");
        logger.info("User's name is {}", System.getProperty("user.name"));
    }

}

In order to compile and execute the program logback-core-1.0.3.jar and logback-classic-1.0.3.jar must be in the classpath. (They can be found in the distribution archive.) The JARs are also available from the Maven Central Repository. Simply add the following dependencies to your Apache Maven project that uses Logback:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.0.3</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.0.3</version>
</dependency>

Logging can be configured via an XML configuration file named logback.xml. To play with the example program use this logback.xml:

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ALL</level>
        </filter>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="ALL">
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

Logback will look for it automatically in the classpath.

Logback has great features. It provides a number of appenders to publish log messages. For example, it can deliver log messages in email. You can also write your own appender. Moreover, logging can be fully configured from the XML configuration file.

The next installments of this blog post series will introduce some of its most exciting features.

You can download the above example from here (a more advanced configuration file is included). Building the project requires Apache Maven.

Tagged

Readline style command line editing with JLine

JLine 2.x is a free and open source console I/O library written in Java and distributed under the Modified BSD License

It offers line-editing and history capabilities for console applications, that are similar to the functions provided by the GNU readline library. For a complete list of its main features see the wiki page of the project.

Since JLine is available from the Maven Central Repository, the easiest way to get it is to add the following dependency to your project’s POM:

<dependency>
    <groupId>jline</groupId>
    <artifactId>jline</artifactId>
    <version>2.6</version>
    <scope>compile</scope>
</dependency>

The following is a simple example that demonstrates how to use the library:

import java.io.IOException;

import jline.TerminalFactory;
import jline.console.ConsoleReader;

public class ConsoleDemo {

    public static void main(String[] args) {
        try {
            ConsoleReader console = new ConsoleReader();
            console.setPrompt("prompt> ");
            String line = null;
            while ((line = console.readLine()) != null) {
                console.println(line);
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                TerminalFactory.get().restore();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

}

The program uses the ConsoleReader class to read lines from the console until end-of-file is encountered (press control-D to signal end-of-file). The lines read are simply echoed back to the console. Command line history is enabled by default, you can recall and edit lines that have been previously entered.

JLine supports command line completion that is bound to the TAB key by default. For example, to enable automatic file name completion simply add a FileNameCompleter instance to the console object with the following line of code:

console.addCompleter(new FileNameCompleter());

You can add more completers, such as a StringsCompleter with a collection of strings:

console.addCompleter(
    new StringsCompleter(
        IOUtils.readLines(new GZIPInputStream(ConsoleDemo.class.getResourceAsStream("wordlist.txt.gz")))
    )
);

Here we use a compressed wordlist from the file wordlist.txt.gz that is loaded by the IOUtils class from the Commons IO library.

Command line editing with JLine

Command line editing with JLine

The TerminalFactory.get().restore() call in the finally block does some cleanup and restores the original terminal configuration. This cleanup is performed automatically, if the jline.shutdownhook system property is set to true.

It’s a bit odd that the API documentation is not available online, however, you can grab the javadoc in a JAR from Maven Central. It should also be noted that the API documentation could be better. (Some of the methods are completely undocumented.) Despite these minor shortcomings, it is an excellent library that deserves attention.

You can download the above example program from here.

Tagged

File Type Detection with Apache Tika

Apache Tika is a free and open source Java framework for content analysis developed under the umbrella of the Apache Software Foundation. Like other Apache projects, it is distributed under the Apache License, Version 2.0.

Tika’s main function is to extract metadata and structured text content from various documents. (The list of supported document formats can be found here.) It’s implementation heavily relies on external parser libraries, for example, it uses Apache PDFBox for parsing PDF files.

Tika also provides file type detection functionality similar to that of the file utility available in Unix-like systems. The Detector interface represents file type detection capability. This interface has several different implementations. Fortunately, you do not have to worry about the details. The Tika class in the API provides convenient access to Tika’s functionality hiding technical details of the underlying implementation.

File type detection methods are all named detect(). The methods examine the filename extension (if available) and consume the content of the document in order to determine the file type, that is returned as an Internet media type string (eg. "image/jpeg").

The following code snippet demonstrates how to determine the file type of a resource identified by an URL:

import java.io.IOException;
import java.net.URL;

import org.apache.tika.Tika;

public class TikaDemo {

    public static void main(String[] args) {
        Tika tika = new Tika();
        try {
            String mediaType = tika.detect(new URL("http://tika.apache.org/tika.png"));
            System.out.println(mediaType);
        } catch(IOException e) {
            System.err.println(e.getMessage());
        }
    }

}

The above code will print image/png to the standard output. To compile and run the program download tika-app-1.0.jar from here and add it to the classpath. Alternatively, if your project is a Maven project, simply add the following dependency to the POM:

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>1.0</version>
    <scope>compile</scope>
</dependency>

Note that the detect method() that takes an InputStream as a parameter consumes the content of the stream to determine the file type. If the stream supports the mark() and reset() methods then the current position is marked before the content of the stream is read. In this case, the method automatically repositions the stream to the marked position after the file type is determined.

However, if the stream does not support this feature, the entire content of the stream will not be available for further processing. It may be an undesired side effect. Remember, you can always wrap an InputStream in a BufferedInputStream to guarantee that the markSupported() method returns true. That is, replace a tika.detect(stream) method call with the following:

stream = new BufferedInputStream(stream);
tika.detect(stream)

tika-app-1.0.jar also provides both a command line and a graphical user interface to access Tika’s functionality. (See the TikaCLI and the TikaGUI classes.) For more information on running Tika execute the following command:

java -jar tika-app-1.0.jar --help

For example, the following command will return the file type of the specified resource:

java -jar tika-app-1.0.jar --detect http://tika.apache.org/tika.png

It should be noted that the tika-core Maven artifact does not contain the command line and graphical user interfaces. If you need them in your Maven project use the tika-app artifact instead.

Tagged

Auto-generation of UML Class Diagrams in Maven Projects

The yWorks UML Doclet is a handy Javadoc extension that automatically creates good-looking UML diagrams from Java classes and embeds them into the generated API documentation.

Although the tool is not free sofware, it’s Community Edition is available for free of charge under the following conditions:

The Community Edition of the Software is licensed to you free of charge. It comes without support and warranties of any kind. The Community Edition of the Software inserts a web link into your output files that points to the yWorks website. You may not change that link or prevent either display of the link or the intended use as means of navigation to get to the yWorks website in any way.

These terms are quite reasonable and you don’t have to pay a high price for such a great tool.

The functionality offered by the product is also available in Apache Maven projects via the Maven Javadoc Plugin. The following is a minimal POM that demonstrates how to use the doclet in Maven projects:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>my</groupId>
  <artifactId>project</artifactId>
  <packaging>jar</packaging>
  <version>1.0</version>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <reportPlugins>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-project-info-reports-plugin</artifactId>
            </plugin>
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-javadoc-plugin</artifactId>
              <version>2.8.1</version>
              <configuration>
                <doclet>ydoc.doclets.YStandard</doclet>
                <docletPath>${yDoc.path}/lib/ydoc.jar:${yDoc.path}/lib/styleed.jar:${yDoc.path}/resources</docletPath>
                <additionalparam>-umlautogen</additionalparam>
              </configuration>
            </plugin>
          </reportPlugins>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Can’t wait to try it? Download and unpack the archive of the Community Edition, then run Maven with mvn site -DyDoc.path=PATH where PATH is the path of the directory that contains your yDoc installation. Alternatively, the path can also be given in the properties element of the POM:

<properties>
  <yDoc.path>PATH</yDoc.path>
</properties>

The screenshot below shows the appearance of the enhanced API documentation.

API documentation with auto-generated UML class diagram

Thanks to László Aszalós for recommending this excellent tool.

Tagged ,