Tag

Posts tagged with ‘programming’

Remember to synchronize when iterating streams from a synchronized Collection

kinow @ Dec 03, 2017 23:56:13

When iterating collections created via Collections.synchronizedList for instance, you are required to obtain a lock on the actual list before doing so. So you normally end up with code similar to:

List list = Collections.synchronizedList(new ArrayList());
synchronized (list) {
  Iterator i = list.iterator(); // Must be in synchronized block
  while (i.hasNext())
      foo(i.next());
}

This requirement is documented in the javadocs.

Since lambdas and streams are being more widely used, it is important to remind that when iterating via a stream we also need to obtain a lock on the synchronized collection created.

List list = Collections.synchronizedList(new ArrayList());
synchronized (list) {
  list.stream()
    .anyMatch(...)
}

Here’s an example from Zalando Nakadi Event Broker.

Happy hacking!

Watch out for Locales when using NumberFormat with currencies

kinow @ Dec 02, 2017 22:51:00

In Java you have the NumberFormatException to help you formatting and parsing numbers for any locale. Said that, here’s some code.

BigDecimal negative = new BigDecimal("-1234.56");

DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.UK);
String formattedNegative = nf.format(negative);

System.out.println(formattedNegative);

The output for this code is -£1,234.56. That’s expected, as the locale is set to UK, so the currency symbol used is for British Pounds. And as the number is negative, you get that minus sign as a prefix. For Japanese locale you’d get -¥1,235, and for Brazilian locale you’d get -R$ 1.234,56.

So far so good.

What about the following code, with nothing different except for the locale set to US.

BigDecimal negative = new BigDecimal("-1234.56");

DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US); // <--- US now
String formattedNegative = nf.format(negative);

System.out.println(formattedNegative);

Some could intuitively expect -$1,234.56. However, the output is actually ($1,234.56).

There are different prefixes and suffixes. But in some locales the prefix can be empty, or, as in the case of the US locale, it can be quite different than what you could expect.

Learned about this peculiarity from NumberFormat while working on VALIDATOR-433 for Apache Commons Validator.

Happy hacking!

What Are Identification Keys

kinow @ Dec 01, 2017 23:26:09

In biology, an identification key is a printed or computer-aided device that aids the identification of biological entities, such as plants, animals, fossils, microorganisms, and pollen grains. Identification keys are also used in many other scientific and technical fields to identify various kinds of entities, such as diseases, soil types, minerals, or archaeological and anthropological artifacts

When you work writing software, it is common that at one point or another of the product development you will work with a SME, or subject-matter expert. This person is someone experienced in a field such as telecom billing, insurance, taxes, or even nature and environment.

Questions too specific, that land away from the knowledge area of software engineers, are normally addressed by the SME. Sometimes the knowledge from a SME can be spread in a team after they have worked together for a while.

Most of my time in New Zealand I have been working with environmental sciences. In one project, I remember hearing other developers mention ID’s, Keys, and Identification Keys. I had not worked with environmental sciences before, and only learned about its Portuguese translation (“Chave”, or “Chave de Identificação”, or “Chave Dicotêmica”) recently.

They are mechanisms, digital or physical, that help you identify plants, animals, fossils, etc. And I found out later that there are many identification key software written for the Web, desktop, and also other medias like PDF’s, and even printed version.

And also in New Zealand I found how fun identifying species can be with the iNaturalist app and community. If you are like me before, and had not heard about it before, search around more about it. It is a very simple concept, common to biologists, people who work with taxonomy, marine life, birds.

If you are in New Zealand, or just interested about it, here are some links to get you started identifying the local species.

Have fun!

Using formatter exclusions with Eclipse

kinow @ Nov 06, 2017 21:56:56

Sometimes when you are formatting your code in Eclipse, you may want to prevent some parts of the code from being formatted. Especially when using Java 8 lambdas and optionals.

Here’s some code before being formatted by Eclipse’s default formatter rules.

Code adapted from: blog post Java d’eau ‐ Java 8: Streams in Hibernate and Beyond

session.createQuery("SELECT h FROM Hare h", Hare.class)
    .stream()
    .filter(h -> h.getId() == 1)
    .map(Hare::getName)
    .forEach(System.out::println);

Then after formatting.

session.createQuery("SELECT h FROM Hare h", Hare.class).stream().filter(h -> h.getId() == 1).map(Hare::getName)
                .forEach(System.out::println);

Which doesn’t look very appealing, ay? You can change this behaviour at least in two ways. The first by telling the formatter to ignore this block, through a special formatter tag in your code.

First you need to enable this feature in Eclipse, as it is disabled by default. This setting is found in the preferences JavaCode StyleFormatterEditOff/On Tags.

A screen shot of Eclipse formatter settings
Enabling formatter tags in Eclipse

Then formatting the following code won’t change a thing in the block surrounded by the formatter tags.

/* @Formatter:off */
session.createQuery("SELECT h FROM Hare h", Hare.class)
    .stream()
    .filter(h -> h.getId() == 1)
    .map(Hare::getName)
    .forEach(System.out::println);
/* @Formatter:on */

But having to type these tags can become annoying, and cause more commits and pull requests to be unnecessarily created. So an alternative approach can be to change the formatter behaviour globally.

This can be done in Eclipse in another option under the formatter options, JavaCode StyleFormatterEditLine WrappingFunction CallsQualified invocations.

You will have to choose “Wrap all elements, except first element if not necessary” under Line wrapping policy. And also check “Force split, even if line shorter than maximum line width”.

A screen shot of Eclipse formatter settings
Enabling custom formatter behaviour globally

Once it is done, your code will look like the following no matter what.

session.createQuery("SELECT h FROM Hare h", Hare.class)
    .stream()
    .filter(h -> h.getId() == 1)
    .map(Hare::getName)
    .forEach(System.out::println);

Happy coding!

♥ Open Source

Quickly Verifying jar Signatures For ASF Releases

kinow @ Oct 14, 2017 00:24:54

The release process within the Apache Software Foundation includes a series of steps. Amongst these steps is the voting process. In Apache Commons, the release instructions includes a note on artefact signatures.

During the course of the VOTE, make sure that one or more of the reviewers have verified the signatures and hash files included with the release artifacts. If no one specifically mentions having done that during the VOTE, ask on the dev list and make sure someone does this before you proceed with the release.

Tired of always having to manually check several artefacts, or having to come up with the correct shell commands to iterate through a list of files, the other day I wrote a simple script to download the KEYS file, import it, download all the artefacts, then iterate through them and verify the signature.

Here’s the script. Licensed under the GPL licence.

#!/usr/bin/env bash

url=""

# From: https://blog.mafr.de/2007/08/05/cmdline-options-in-shell-scripts/
USAGE="Usage: `basename $0` [-hv] https://repository.apache.org/.../commons/commons-configuration/2.2/"

# Parse command line options.
while getopts hv: OPT; do
    case "$OPT" in
        h)
            echo $USAGE
            exit 0
            ;;
        v)
            echo "`basename $0` version 0.0.1"
            exit 0
            ;;
        \?)
            # getopts issues an error message
            echo $USAGE >;
    esac
done

# Remove the switches we parsed above.
shift `expr $OPTIND - 1`

# We want at least one non-option argument. 
# Remove this block if you don't need it.
if [ $# -eq 0 ]; then
    echo $USAGE >&2
    exit 1
fi

# Access additional arguments as usual through 
# variables $@, $*, $1, $2, etc. or using this loop:
URL=$1

echo "url: ${URL}"

# Use a local temporary directory
BUILD_DIR=$(mktemp -d)
pushd "$BUILD_DIR"

echo "build dir: ${BUILD_DIR}"

# Download KEYS file
KEYS_URL=https://www.apache.org/dist/commons/KEYS

echo "importing KEYS from: ${KEYS_URL}"

wget "$KEYS_URL"
gpg --import KEYS

# Download JARs and signature files
echo "downloading all jars and signature files..."

wget -r -nd -np -e robots=off --wait 1 -R "index.html*" "${URL}"

# Check the files
for x in *.jar; do gpg --verify "${x}".asc; done

# EOF

The script can be found at GitHub too: https://github.com/kinow/dork-scripts/tree/3c519a74f28c08310ce2e65f8e860d61fd0c5c07/gpg/asf-sigs