JQuery: Button to cycle through select options

I wanted an html drop-down list to automatically appear as a simple button that changes color on every click as it cycles through the option values of the (hidden) select element.

The code sample is in this jsfiddle. It uses JQuery.

For each relevant select element, it styles the associated label so it looks like a button, hides the select element and handles clicks on the label button by cycling through the select options.

The display text of each option is used as a tooltip (‘title’ attribute) of the button which also serves as a css selector to color the button according to currently selected option.

The beauty of this is that the selected values of the hidden drop-downs can be submitted by regular form submit and that the form is fully functional if JavaScript is turned off.

The button styling requires CSS3, so IE8 is not suitable. I have tested this successfully in Firefox 33 and IE11.

Design and code visualization

As a team lead at work and for my own good, I want to improve how I visualize system architecture, software design and code structure.

There seem to be at least two angles to this:

  • Show ideas
  • Show (software) reality

For me, ideas often develop top-down, starting from overview level, and require putting something I have in mind on paper or whiteboard, often as a mix of bullet points, sketchy diagram fragments, boxes, ad-hoc dividers and increasingly chaotic arrows.

In the past I have used scans of my paper scribblings or photos of whiteboards to capture the results. But of course, those “snapshots” are not very workable nor professional.

So for idea visualization, I need a flexible yet intuitive mindmapping and/or diagram tool. It should be easy to install or require no installation at all, stylistically appealing but clear, and of course be free/libre open source (i.e. no Visio, please).

I looked at tools like Dia, some online services like LucidChart, and other allegedly free alternatives, and have settled on Pencil Project for now. It is very basic, but seems to provide all I need for now. The cross-platform availability is excellent, it can even be installed as a Firefox extension.

On the other hand, depicting the reality of existing systems and code bases usually requires some sort of generation process that analyzes the real structure, e.g. a network layout, the content of a Java package, an Apache Camel route, etc. and turns it into a renderable file.

For Java source code, I found PlantUML quite interesting, with its javadoc integration and quick dependency diagram support.

I might follow up with more detailed posts about how I use the tools mentioned above. One aspect I have not looked into yet, is how I can embed the visualizations within AsciiDoc.

Java Value Types and Generics specialization

It is exciting to see that Brian Goetz and others are working towards Generics over Primitive Types (List<int> et al) and Value Types (structured immutable data types with value semantics and without object overhead) for Java 10.

The motivation for these initiatives comes from the somewhat clunky divide between objects and primitives in Java.

Objects are the only choice in Java when it comes to collections content and generic type instantiation in general. There is no such thing as List<int> in Java right now.

Objects are also the only option for structured data in Java, including simple aggregation. There are no structs, no tuples, etc. And because the primitive types in Java cannot be “primitively” extended, combined or range restricted, even things like complex numbers, unsigned ints, big decimals and the like all require classes and objects to represent the values.

Arrays are the only way to aggregate a bunch of primitives (of the same type) in Java. But Arrays themselves are objects, with reference identity not value identity, and cannot be used as a substitutes for tuples.

Object purists might argue that Java should just get rid of primitives altogether and strictly follow the “everything is an object” paradigm.

But objects bear management overheads in terms of memory and processing time, bring complexity around identity versus equality, require reference checking for garbage collection purposes, cannot live on the stack, lead to array data in non-contiguous memory, etc.

As the Java architects point out, there currently is an unsolvable conflict between object identity and value semantics in Java: Even if objects a1 and a2 of immutable type A have completely identical state, the JVM cannot treat them as identical “values”, because synchronization relies on monitor object identity, and A1 and A2 would represent separate independent locks. Conflating them into one “value object” would break that distinction.

All this suggests that Java needs to be extended to support structured types with value semantics, conceptually somewhere between primitives and objects. Hopefully Java 10 will come with such types and hopefully smart engineers like Brian Goetz will make sure the resulting type system won’t feel like an incoherent Frankenstein monster.

JavaOne 2014 keynote ends awkwardly

Today we watched the JavaOne Technical Keynote at my workplace and the content was fine but a little stale, mostly rehashing last year’s messages, some might even say JavaOne 2014 was “off to a timid start“.

The technical keynote was the final part of a day of keynotes on Sep 28th. Mark Reinhold (Java Platform Architect) looked back at the history of Java, talked about Java 8 and briefly about Project Jigsaw (modules for Java). Then Brian Goetz (Java Language Architect) was finally starting to talk about exciting new initiatives for Java 10 and beyond.

At that point the keynote ended almost rudely, as Reinhold first told Goetz to speed things up, just to then cut him off a few minutes later, taking the slide clickers from him, quickly skipping through remaining slides in awkward silence and ending it with a curt “Have a good week” to the audience.

How unprofessional! Reinhold could have at least smoothed it over by saying that Goetz was trying to explain cool stuff like Value types and refer to a JavaOne session that will go into the details.

Or allow for 10 extra minutes, but maybe Oracle management was too inflexible for that. What a shame and how ironic that the longer term future of Java technology was not important enough. What was the motto of the conference again? “Create the future”? But don’t talk about it for too long, I guess.

Simple XML processing in Java using XPath

Often I just want to get or set a few values from/on a given XML document. XPath is the standard for specifying locations in an XML document, with a Java XPath API since Java 5.

But the API is a little clunky, resulting in code like this:

DocumentBuilder builder = 
    DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(new File("/widgets.xml"));

XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget";
Node widgetNode = (Node) xpath.evaluate(expression, 
    document, XPathConstants.NODE); 

Wouldn’t it be nice if it was as simple as this:

Xml xml = new Xml(Paths.get("/widgets.xml"));
Xml node = xml.node("/widgets/widget");

This Xml class and some supporting code is in my x-xml github repo. It implements a Tree interface like this:

Interface

package net.doepner.xml;

/**
 * Conveniently extract and change text values
 * and navigate nodes on an XML document
 */
public interface Tree {

    /**
     * @param xpath An XPath expression
     * @return The nodes matching the XPath location
     * @throws XmlException Wrapping any underlying XML API exception
     */
    Iterable<? extends Tree> nodes(String xpath);

    /**
     * @param xpath An XPath expression
     * @return The single node matching the XPath location
     * @throws XmlException Wrapping any underlying XML API exception
     */
    Tree node(String xpath);

    /**
     * @param xpath An XPath expression
     * @return The text value from the unique XPath location
     * @throws XmlException Wrapping any underlying XML API exception
     */
    String get(String xpath);

    /**
     * @param xpath An XPath expression
     * @param value The text value to be set on the unique XPath location
     * @throws XmlException Wrapping any underlying XML API exception
     */
    void set(String xpath, String value);
}

Implementation

Here is the Xml class that implements the Tree interface:

package net.doepner.xml;

import com.doepner.libs.messaging.XmlException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * Allows node navigation and getting and setting of xpath values
 */
public class Xml implements Tree {

    private final TransformerFactory tf = TransformerFactory.newInstance();
    private final XPath xp = XPathFactory.newInstance().newXPath();
    private final QNames qNames = new QNames();

    private final Node root;

    public Xml(Path path) {
        this(new InputSource(path.toFile().toURI().toASCIIString()));
    }

    public Xml(String payload) {
        this(new InputSource(new StringReader(payload)));
    }

    public Xml(InputSource inputSource) {
        this(parse(inputSource));
    }

    private Xml(Node root) {
        this.root = root;
    }

    private static Document parse(InputSource inputSource) {
        try {
            return DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder().parse(inputSource);
        } catch (ParserConfigurationException 
                | SAXException | IOException e) {
            throw new XmlException(e);
        }
    }

    @Override
    public Iterable<Xml> nodes(String xpath) {
        final Collection<Xml> result = new LinkedList<>();
        for (Node node : new IterableNodes(eval(xpath, NodeList.class))) {
            result.add(new Xml(node));
        }
        return result;
    }

    @Override
    public Xml node(String xpath) {
        return new Xml(eval(xpath, Node.class));
    }

    @Override
    public String get(String xpath) {
        return eval(xpath, String.class);
    }

    @Override
    public void set(String xpath, String value) {
        eval(xpath, Node.class).setTextContent(value);
    }

    private final Map<String, XPathExpression> cache = new HashMap<>();

    private <T> T eval(String xpath, Class<T> resultType) {
        return resultType.cast(evaluate(resultType, getCompiled(xpath)));
    }

    private XPathExpression getCompiled(String xpath) {
        final XPathExpression cachedExpression = cache.get(xpath);
        if (cachedExpression != null) {
            return cachedExpression;
        } else {
            final XPathExpression expr = compile(xpath);
            cache.put(xpath, expr);
            return expr;
        }
    }

    private Object evaluate(Class<?> resultType, XPathExpression expr) {
        try {
            return expr.evaluate(root, qNames.get(resultType));
        } catch (XPathExpressionException e) {
            throw new XmlException(e);
        }
    }

    private XPathExpression compile(String xpath) {
        try {
            return xp.compile(xpath);
        } catch (XPathExpressionException e) {
            throw new XmlException(e);
        }
    }

    @Override
    public String toString() {
        try (final StringWriter writer = new StringWriter()) {
            tf.newTransformer().transform(new DOMSource(root),
                    new StreamResult(writer));
            return writer.getBuffer().toString();
        } catch (TransformerException | IOException e) {
            throw new XmlException(e);
        }
    }
}

Supporting classes

Custom exception wrapper class
package net.doepner.xml;
 
/**
 * An XML exception
 */
public class XmlException extends RuntimeException {
 
    public XmlException(Throwable cause) {
        super(cause);
    }
}
The mapping from Java types to QNames
package net.doepner.xml;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.Map;

import static javax.xml.xpath.XPathConstants.NODE;
import static javax.xml.xpath.XPathConstants.NODESET;
import static javax.xml.xpath.XPathConstants.STRING;

/**
 * Mapping from Java type to QName
 */
public class QNames {

    private final Map<Class<?>, QName> qNames = new HashMap<>();

    {
        qNames.put(String.class, STRING);
        qNames.put(Node.class, NODE);
        qNames.put(NodeList.class, NODESET);
    }

    public QName get(Class<?> resultType) {
        return qNames.get(resultType);
    }
}
Convenient iteration of XML node lists
package net.doepner.xml;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Convenient iteration of XML node lists
 */
public class IterableNodes implements Iterable<Node> {

    private final NodeList nodeList;

    public IterableNodes(NodeList nodeList) {
        this.nodeList = nodeList;
    }

    @Override
    public Iterator<Node> iterator() {

        return new Iterator<Node>() {

            int index = 0;

            @Override
            public boolean hasNext() {
                return index < nodeList.getLength();
            }

            @Override
            public Node next() {
                if (hasNext()) {
                    return nodeList.item(index++);
                } else {
                    throw new NoSuchElementException();
                }
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}

Get java version string via shell commands

Determine the pure java version string from any Unix/Linux shell (including Cygwin):

java -version 2>&1 | head -n 1 | cut -d'"' -f2

This requires only the very commonly available and lightweight “head” and “cut” commands.

I originally found the one-liner on stackoverflow. Thanks to the friendly folks who shared it.

To get only the major version part (e.g. 8 for Java 1.8.x, 11 for 11.x), use this:

java -version 2>&1 \
  | head -1 \
  | cut -d'"' -f2 \
  | sed 's/^1\.//' \
  | cut -d'.' -f1

Note: The sed step is required for versions up to Java 8 that start with the “1.” prefix.

Example: Ensure Java 11 or higher:

#!/bin/bash

version=$(java -version 2>&1 \
  | head -1 \
  | cut -d'"' -f2 \
  | sed 's/^1\.//' \
  | cut -d'.' -f1 
)

if [ $version -lt "11" ]; then
  echo "Java 11 or higher is required."
  exit 1
fi

Reconfigure log4j 1.x without restart

Disclaimer: This blog post is about log4j 1.x. which is by now a dormant project and not recommended for new projects. Logback and log4j 2.x support dynamic configuration changes at runtime via a simple attribute in their respective config files (see related log4j 2.x and logback docs). Please consider upgrading your logging backend to one of those libraries and use them in combination with the slf4j logging facade API.

Support for dynamic logging config changes at runtime is useful when you want to debug an application without restarting it: You can change settings in your logging config file, like log levels, appenders, log output formats, etc. and the logging framework automatically notices the change and reconfigures itself after a certain delay.

Good old log4j 1.x supports this, but you have to programatically set it up, typically somewhere in the start-up code of your Java application, using

  • DOMConfigurator.configureAndWatch(..) if you use log4j.xml
  • PropertyConfigurator.configureAndWatch(..) if you use log4j.properties

Please note that the log4j 1.x FAQ does not recommend doing this in a JEE container:

“Because the configureAndWatch launches a separate watchdog thread, and because there is no way to stop this thread in log4j 1.2, the configureAndWatch method is unsafe for use in J2EE environments where applications are recycled.”

The following example code works both for log4j.xml or log4j.properties files, as long as they are in the classpath as file resources, i.e. not packaged inside a jar:

    public static enum ConfigFileType {
         xml, properties
    }

    public void configureLogging(ConfigFileType configFileType) {
        final URL configFile = getClass().getResource("/log4j." + configFileType);

        if (configFile != null && "file".equals(configFile.getProtocol())) {
            final int scanDelayMinutes = getSystemProperty("log4j.config.rescan.delay.minutes", 2);
            final long scanDelayMillis = scanDelayMinutes * 60 * 1000;

            switch (configFileType) {
                case xml:
                    DOMConfigurator.configureAndWatch(configFile.getPath(), scanDelayMillis);
                    break;
                case properties:
                    PropertyConfigurator.configureAndWatch(configFile.getPath(), scanDelayMillis);
                    break;
            }
        }
    }

    private static int getSystemProperty(String name, int defaultValue) {
        try {
            return Integer.parseInt(System.getProperty(name));
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

You can override the default rescan delay as a system property option in your java command, for example:

java -Dlog4j.config.rescan.delay.minutes=5 [..]

The period is in minutes to prevent too much rescanning. Log4j uses a “FileWatchdog” class that repeatedly checks File#lastModified(). On some filesystems – like ReiserFS on Linux – scan delays of less than a minute can cause problems (thanks to Rod Oliveira for pointing this out).

AsciiDoc – A friendly authoring format

I recently learned about AsciiDoc, a powerful yet intuitive, human readable and writable format for authoring books and similar kinds of structured documents:

  • Solid technology, first created in 2002
  • Plain-text format, requires no special editor
  • Cleanly separates document structure from layout details
  • Available for the JVM community since 2013
  • Simple and intuitive like Markdown
  • As powerful as DocBook, without the XML clutter
  • Syntax highlighting in vim and other editors
  • Generates DocBook, HTML, epub, PDF, …
  • AsciiDoctor toolkit generates HTML 5, DocBook 4.5
  • Renders inline on github (like markdown)
  • Maven and Gradle plugins for automation
  • Support for creating diagrams using plain-text
  • Happily used by teams at Redhat, Git, Spring, …

For example, the whole documentation for the JEE standard CDI is maintained in AsciiDoc and hosted on github as maven buildable projects.

Dan Allen, a known name in the JEE community and AsciiDoctor lead developer, says that AsciiDoc supports “the creation of reusable, human-readable, semantic content” so that we can better adapt to adaptive content and address the challenges of an electronic multi-device, multi-format world that is redefining what “book” means.

An authoring revolution?

As an author-friendly plain-text format AsciiDoc might become a catalyst in an ongoing electronic authoring revolution that treats book writing like software development with authors working directly on the book’s “source code” in git repositories, while rendering into various target formats is done using build automation tools and fast scriptable converters like AsciiDoctor.

The tech-savvy publishing house O’Reilly seems to be on the forefront of this trend and

Use xtrlock via XFCE 4.8 lock button

I currently use XFCE 4.8 on Debian Wheezy as my desktop system. Its panel supports so-called “action buttons” for hibernate, lock, shutdown, etc.

I use one of those buttons to lock the screen but I don’t like xscreensaver (too ugly, don’t need the screensaver stuff), gnome-screensaver (too many dependencies), xlock and its successor xlockmore (too ugly) or slock (just a black blank screen always confuses me).

Good thing is that I found xtrlock which does what I want: It just shows a lock symbol instead of the mouse cursor, all screen content is still visible but user interaction is blocked until the current user password has been typed in.

This is just enough to prevent my 2 and 5 year old children from messing around with my laptop. So I installed it:

sudo apt-get install xtrlock

Problem was that the XFCE lock button calls xflock4 which is a simple shell script that has hardcoded support for the afore-mentioned set of lock programs, but not for xtrlock.

My simple solution was to take advantage of /usr/local/bin being usually before /usr/bin in the PATH and create a script /usr/local/bin/xflock4 with this content:

#!/bin/sh
xtrlock

Make it executable with

sudo chmod a+x /usr/local/bin/xflock4

Now I can use the XFCE lock button and get what I want.

Alternatively, there are a couple of other light-weight lock programs for Linux:

Java software engineering – reference resources

Official Java and JEE

Java Technology Reference

Java Standard Edition (JSE)

Java Enterprise Edition (JEE)

The official Java tutorials

The official JEE 7 tutorial

JEE 7 Technologies index

Java language spec and JVM spec

Java community

Oracle Java community

OpenJDK

Java Community Process (JCP)

Apache Commons

Apache.org Java projects

JBoss.org

Spring

Google Guava

Trending Java projects on github

JEE and Java web servers

Apache Tomcat

JBoss Wildfly

Glassfish

Build and test automation

Sonatype Maven books

Jenkins documentation (wiki)

JUnit reference documentation

Source and version control

The SVN reference book

Git reference documentation

Java IDEs

Intellij IDEA documentation

Eclipse documentation

Netbeans knowledge base

Vim configuration for Java coding