Thursday, 31 December 2015


My website has been using Drupal 70 for a while now, ever since I started working with Drupal in my previous job. It seemed like a good idea to get some experience with my first CMS/Webportal/thing by toying with it at home.

I have recently switched over to Liferay1. I was looking for a CMS/Webportal/thingie that is more in tune with the rest of my applications (which are written in Java/Glassfish). I could have chosen Hippo2, but I didn't. Liferay seems to align very good with Vaadin3, which is something I plan on perhaps using in the future.

Installing Liferay on GlassFish 4

Liferay comes with a choice of pre-defined application servers, which is very handy. But I already had a Glassfish server installed, so I wished to use that one, and then things do get a bit more complicated4 5.

What follows are some of the things that I ran up against, and how to do some of the administration that I required.

Global site

Apparently, since version 6, there's a Global6 site that is used for defining resources that are accessible for all other sites. Something I don't need, as I only required a one-site install. But it does show that the product seems defined for many websites of an Enterprisy nature.

Making the site private

Control panel -> Sites -> Configuration -> Site Settings -> Membership Type = Private
There are three settings for the site: open, restricted and private.
Users can become members of the site at any time. Users can join sites from the My Sites portlet.
Users can request site membership but site administrators must approve requests in order for users to become members. Requests can be made from the My Sites portlet.
Users are not allowed to join the site or request site membership. Private sites don’t appear in the My Sites portlet. Site administrators can still manually select users and assign them as site members.
See [11] for more information regarding these settings.
It is also possible to define how new users are registered on the site12


See for changing the favicon7 the (future) blog on "Liferay Themes".

Apple Icons

I got the following warning in my glassfish logs. Apparently I need to get some apple icons in there:
[2015-09-19T17:58:16.236+0000] [glassfish 4.1] [INFO] [] [] [tid: _ThreadID=29 _ThreadName=Thread-8] [timeMillis: 1442685496236] [levelValue: 800] [[
17:58:16,235 WARN [http-listener-1(5)][code_jsp:114] {code="404", msg="Not Found", uri=/apple-touch-icon.png}]]

[2015-09-19T17:58:16.399+0000] [glassfish 4.1] [INFO] [] [] [tid: _ThreadID=28 _ThreadName=Thread-8] [timeMillis: 1442685496399] [levelValue: 800] [[
17:58:16,398 WARN [http-listener-1(4)][code_jsp:114] {code="404", msg="Not Found", uri=/apple-touch-icon-precomposed.png}]]

Unable to change default Display Icon

When attempting to change the display icon prominently displayed in the left-upper corner of the Liferay website, I ran into a little problem.

Changing it can be done using
Control Panel -> Portal Settings -> Display Settings (Under Miscellaneous)
The error message was:
GRIZZLY0039: Request URI is too large.
Apparently, it was necessary to increase the buffer size of the glassfish application server8 9:
Configurations -> cluster-config -> Network Config -> Transports -> tcp -> Buffer Size' to 131072 or more.

Liferay site

You can probably remove the Liferay Inc company site that is available standard in the demo.

Issues with the server.policy file

The server.policy file of Glassfish needs to be adapted for Liferay to work properly10.

I added the following which seemed to do the trick:
grant codeBase "file:${com.sun.aas.instanceRoot}/applications/-" {

grant codeBase "file:${com.sun.aas.instanceRoot}/generated/-" {

What version?

You can see the version of the Liferay instance you are running, by going to:
Control panel -> Configuration -> Server Administration
There you will find
Liferay Portal Community Edition 6.2 CE GA4 (Newton / Build 6203 / April 16, 2015)
Uptime: 3 Days, 14:53:03


[0] Drupal
[1] Liferay
[2] Hippo
[3] Vaadin
[4] Liferay Documentation - Installing Liferay on GlassFish 4
[5] Liferay Dev - Installing Liferay on GlassFish 4
[6] Liferay Wiki - Global Scope
[7] Liferay Wiki - How to change the favorites icon
[8] Stackoverflow - Glassfish 3.1 maximum uri length
[9] Iliachemodanov Blog - Configuration of long URLs in GlassFish
[10] Liferay Forums - Deployment problem on Liferay6.2 Glassfish4
[11] Leveraging Liferay’s Multi-site Capabilities
[12] Time for action – disabling the Register option for a guest user

Thursday, 24 December 2015

Client and Server - Waves of the Past

Pardon me for the esoteric title. Just a small note from me to indicate what kind of movements we have had in the past, when it comes to client and server, or frontend and backend, or browser and server or what have you.

-Mainframes1960susers provide punchcards to system admins (batch-processing)
Dum terminalsMainframes1970stime-sharing, server does all the work1
Personal Computers-
1980sPCs in network sharing files/printers and do all the work
Personal ComputersServer
1990sPC is fat client and can do all the work, the start of client-server
Thin clientServer
1993Thin client does a little bit of work, but a lot is done on the server side
Internet BrowserServer1994Server does all the work, pushes HTML pages to client
PDAServer2000Basically the same concept as Thinclient, but discontinued.
Single Page Application in your Internet BrowserServer2005Browser does all the work, but queries servers.
Tablets and Mobile phonesMany Servers2010Basically the same concept as Thinclient, but distributed computing starts.

So, my question is always, what next? Will we see things of the Past come round again, where people come to the conclusion that Fat Clients are awesome?

The answer is probably that there will be cases where either fat or thin clients make sense. Especially in the plethora of new devices available nowadays.


[1] Wikipedia - Centralized computing

Thursday, 17 December 2015

Trailing Commas

This post might seem trivial, but I decided to go ahead with it.

I recently found out that the following code compiles.
 * The Seasons.
 * @author mr.bear

public enum Seasons
I was a little surprised, that the last comma was not a problem. The same can be seen in the following array initializer:
int[] b = {1, 2, 3, 4, 5, 6,};

Apparently, to my surprise, it's written in the JLS.

According to [1], if you look at the Grammar defined for Enums:
{ [EnumConstantList] [,] [EnumBodyDeclarations] }
For arrays the same rule applies2.
“A trailing comma may appear after the last expression in an array initializer and is ignored.”
I was a little surprised that it has been part of the spec for a very long time3.


[1] JLS 8.0 Section 8.9.1 Enum Constants
[2] JLS 8.0 Section 10.6
[3] JSL 1.0
StackOverflow - Arrays with trailing commas inside an array initializer in java

Thursday, 10 December 2015

true vs. Boolean.TRUE

I saw the following code below at my work, and it got me thoroughly confused. I found the statement above to be unnecessarily complicated.

private boolean useAsReferenceModel = Boolean.FALSE;

Boolean.FALSE returns a Boolean, which is a wrapper2 around the boolean primitive types.

So, in the example above, the Boolean wrapper is auto-unboxed3 to the primitive type false.

So, I changed the code to the simple and straightforward:
private boolean useAsReferenceModel = false;
Let us not make the world more complicated than it really is.


[1] StackOverflow - Java what is the difference between false and Boolean.FALSE
[2] Wikipedia - Primitive Wrapper Classes
[3] Oracle JavaDoc - Autoboxing and unboxing

Thursday, 3 December 2015

Richardson Maturity Model

The Richardson Maturity Model1 gives a very clear idea of how far you are in following the REST software architectural style.

Unfortunately, I seem, personally, in my home projects, to have serious problems reaching the HATEOAS level (level 3). Is that even a problem2?

Does anyone else have the same issue?

Is the last level actually in common use, except for those frameworks that already have it built in, or not?


[1] Martin Fowler - Richardson Maturity Model

[2] The timeless repository - Haters gonna HATEOAS

Thursday, 26 November 2015

Code Kata at the Dojo

At my work, the software architect asked if people were interested in getting together at work of an evening and doing a Kata1.

“Kata2 (型 or 形 literally: "form"), a Japanese word, are the detailed choreographed patterns of movements practised either solo or in pairs. The term form is used for the corresponding concept in non-Japanese martial arts in general.”

Well, I'd never done one of those, so I signed up enthusiastically.

We spent a couple of hours in pairs, (xtreme programming, yay!) to do the Kata. In this case it was regarding Bowling Scores4 5 provided by Uncle Bob8.

It is very interesting, and I decided to spend a little more time in my limited spare time to see what I could come up with. I do notice almost immediately that I always try and capture the domain (in this case, scores, rolls, frames, spares and strikes) into Objects/Classes. It's a challenge to not immediately grab to my standard toolbox. It's also great to get some tests done, before diving into coding.

It is also a challenge to properly read requirements.

I retrieved the git repo from [6] and forked it over in my own github [7] to work on. There's nothing there yet, but that will change once I have something that looks half decent.


[1] Wikipedia - Kata (programming)
[2] Wikipedia - Kata
[3] Wikipedia - Procedural memory
[4] ArticleS. UncleBob. TheBowlingGameKata
[5] CodingDojo - KataBowling
[8] Wikipedia - Robert Cecil Martin

Thursday, 19 November 2015

Linux Commandline Password Manager

Recently I was looking for a good Password Manager, as the number of passwords I need to maintain is growing steadily (I'm sure everyone knows how it is).

The one I found ("pass2 - the standard unix password manager"), the one I am talking about, exemplifies the Unix philosophy0. Which is:
Do One Thing and Do It Well.
Write programs to work together.
Write programs to handle text streams, because that is a universal interface.
The password manager actually basically doesn't do anything itself, but delegates to other parts of the Linux system, namely the filesystem, and GPG for encryption, pwgen for the generation of random passwords, xclip for interfacing with the clipboard and (optionally) Git for version control.

It does mean that you have to setup Gnu Private Guard properly, before you can start using "pass", hence the next chapter.

Gnu Private Guard

“GnuPG1 is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP).”

Creating a key

All keys are stored in .gnupg.
bash-4.3$ gpg2 --full-gen-key
gpg (GnuPG) 2.1.7; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory '/home/mrbear/.gnupg' created
gpg: new configuration file '/home/mrbear/.gnupg/gpg.conf' created
gpg: WARNING: options in '/home/mrbear/.gnupg/gpg.conf' are not yet active during this run
gpg: keybox '/home/mrbear/.gnupg/pubring.kbx' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 2
I have decided to follow the advice of the website1 and take 2.
DSA keys may be between 1024 and 3072 bits long.
What keysize do you want? (2048)
I take 2048, it seems fairly default.
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
= key expires in n days
w = key expires in n weeks
m = key expires in n months
y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) Y

GnuPG needs to construct a user ID to identify your key.

Real name: mrbear
Email address:
Comment: mrbear
You selected this USER-ID:
"mrbear (mrbear) "

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
And away we go!
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: WARNING: some OpenPGP programs can't handle a DSA key with this digest size
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/mrbear/.gnupg/trustdb.gpg: trustdb created
gpg: key 3A4CFDFE marked as ultimately trusted
gpg: directory '/home/mrbear/.gnupg/openpgp-revocs.d' created
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub dsa2048/3A4CFDFE 2015-10-14
Key fingerprint = 7FCC 07FA A6BE 32DE A971 2281 587B D827 3A4C FDFE
uid [ultimate] mrbear (mrbear)
sub elg2048/0B94C819 2015-10-14
So, just to check:
bash-4.3$ gpg2 --list-keys
pub dsa2048/3A4CFDFE 2015-10-14
uid [ultimate] mrbear (mrbear)
sub elg2048/0B94C819 2015-10-14

Password store

Apparently, initialising the store needs to be done with the name of the key generated above.
bash-4.3$ sudo dnf install pass
bash-4.3$ pass init "3A4CFDFE"
mkdir: created directory ‘/home/mrbear/.password-store/’
Password store initialized for 3A4CFDFE
And I wish to use Git, because I'm that kinda guy.
bash-4.3$ pass git init
Initialized empty Git repository in /home/mrbear/.password-store/.git/
[master (root-commit) 77cc085] Add current contents of password store.
1 file changed, 1 insertion(+)
create mode 100644 .gpg-id
[master 6655058] Configure git repository for gpg file diff.
1 file changed, 1 insertion(+)
create mode 100644 .gitattributes

Adding my passwords

For example, my email:
bash-4.3$ pass insert Email/
mkdir: created directory ‘/home/mrbear/.password-store/Email’
Enter password for Email/
Retype password for Email/
[master 40d6094] Add given password for Email/ to store.
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 Email/
Adding parameter --multiline makes it possible to not only add your password but other stuff as well. Handy if the userid/username is not standard my email address.

Showing passwords

bash-4.3$ pass
Password Store
└── Email

Generating passwords

bash-4.3$ pass generate Internet/ 16
mkdir: created directory ‘/home/mrbear/.password-store/Internet’
[master 9b966af] Add generated password for Internet/
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 Internet/
The generated password for Internet/ is:
Some websites do not accept "odd" characters (< > ! @ # $ % ^ & * _) when it comes to passwords. When adding the "[--no-symbols,-n]" option you get a generated password containing only letters, capitals and digits.

Showing passwords and copying to clipboard

bash-4.3$ pass -c Email/
Copied Email/ to clipboard. Will clear in 45 seconds.

Getting your stuff back

As basically this awesome password manager stored the passwords as a bunch of GPG2 encrypted files in .password-store, we should be able to decrypt the files directly.

This would work as follows:
bash-4.3$ gpg2 --decrypt .password-store/Email/
gpg: encrypted with 2048-bit ELG key, ID 0B94C819, created 2015-10-14
"mrbear (mrbear) "

Syncing the git

As I wish to manage my passwords from multiple computers, there's a need to sync/merge the git repositories5 from time to time.

First is, of course, the copying of the GPG keys by copying the .gnupg directory.
scp -r .gnupg mrbear@toby:/home/mrbear
From the second machine, from my homedirectory:
git clone ssh://mrbear@sherlock/home/mrbear/.password-store
Cloning into '.password-store'...
After that it is nothing more but a "git pull" or "git push" whenever I need it.


[0] Wikipedia - Unix philosophy
[1] GnuPG
[2] Password store
[3] Linux Crypto: Passwords
[4] StackExchange Unix - I try to add passwords to the pass password managers but my attempts fail
[5] Git - Git Basics Working with Remotes
Fedora Magazine - GPG: a Fedora primer
Fedora Magazine - GPG key management, part 1

Thursday, 12 November 2015

GUID Partition Table

MBR (Master Boot Record) is an old relic that is still in much use as the standard Partition Table format. It is still the standard when it comes to USB sticks and things like that. GPT (GUID Partition Table) is much better and already exists for the past 5 years3.

Apparently Linux (Fedora2 since version 8) supports GPT for a long time. For more information on GPT, see [1], which has some nice diagrams.

Unfortunately, every time I order a new harddrive for one of my computers, it comes equipped standard with the MBR Partition table, and it always takes me a while to figure out why I cannot allocate more than 2 terabytes or assign more than 4 partitions without having to jump through some hoops.

Oh, well.


[1] FedoraProject - MBR vs GPT which is better for Fedora
[2] FedoraProject - Features - GUID Partition Table
[3] Wikipedia - GUID Partition Table
[4] - Using the new guild partition table in linux

Thursday, 5 November 2015

J-Fall 2015

“Once you stop learning, you start dying.”
- Albert Einstein

I just got back from J-Fall 20151.

Seeing as the location had been changed from Nijkerk to Ede, I was unable to attend the Early Bird sessions, much to my dismay. I did manage to hitch a ride with a colleague of mine, but in the future, I will try and get a train. The connection seems to be quite good and once more there is a shuttle bus riding between the location (Cinemec) and the trainstation.

What with traffic (congestion) and my colleague sleeping late, I did miss the first keynote (The Experimental Enterprise - Keynote ING), only arriving at the destination at around 09:45.

The list of sessions I witnessed:

Pushing the limits of Continuous Delivery - Keynote Quintor

Provided by Rene Boere and Pascal Snippen

A fascinating view on what Quintor uses to provide Continuous Delivery (CD) using Docker, Apache Mesos, Marathon and Consul combined with HAProxy. The use of container ships to emphasise Docker was inspired and probably is starting to be overused by now. The microservices landscape is large and you can no longer see the forest for the trees, test environments are hard to set up, deployments are complex and timeconsuming.

Automation of Continuous Delivery is the answer.

Microservices for Mortals

Provided by Bert Ertman

This lecture could be construed as a big, huge, warning if you wish to use Microservices. It had a metaphore comparing coding practices with Italian food. The old way of coding compares to Spaghetti. Then SOA (Service Oriented Architecture) was introduced and those layered coding practices compare to Lasagna. Now the new Microservices compare more to Ravioli (tight independent containers of code bundled together) with sauce. The main idea behind microservices seems to be the ability to easy adapt to change. There is no hard definition on what microservices are. Apparently, microservices are small enough to just replace them with a completely new implementation, or just run 10 instances of one easily. They do away with a lot of items we are software developers have gotten used to:
  • synchronous programming models
  • ACID
  • code reuse
  • using abstractions
Instead, because of the characteristics of Microservices, you get:
  • asynchronous programming models
  • any constraints need to be taken care of at the application level
  • code duplication, each micro service is independent of the others, so code reuse between microservices doesn't make sense
  • separate data storages (one data storage per microservice)
  • passing data using websockets or binary protocols or messaging (REST is too much overhead, I don't want to even mention XML. It's all fine for a public API though.)
  • prefer conventions over abstractions (see code reuse)
If you have not been doing Devops, you cannot get started using Microservices without getting into a world of hurt.

Code for failure. Microservices are brittle, the distributed asynchronous models make them so. Design for this! Use fail early, use resilience patterns, use redundancy, etc.

10 Awesome Tips for Enterprise Javascript - Oracle

Provided by Geertjan Wielenga

This lecture provided an excellent overview of the current JavaScript landscape. I especially liked the fact that he mentioned that at the end of the lecture the landscape will probably already have changed. The JavaScript ecosystem is in that much flux.

Nowadays we have multiple devices, all with different screensizes requiring responsive design. One common factor in all these devices, is that all of them possess a browser. And the Single Page Application (SPA) is becoming the internet-enabled "application" of choice. Page navigation is irrelevant when it comes to Single Page Applications, yet for most Java-based Web Frameworks, page navigation is still an important part of their programming model.

Also, resist the hype. Apparently most managers make bad architecture decision based on hype. And you, as a developer, shouldn't want that.

For some applications, Javascript actually doesn't make any sense. The example provided was air traffic controllers. But different architectures can play different roles, even in those applications where Javascript doesn't make any sense. for example:
mobile apps
web apps
reporting to (upper) management
application itself
what users actually need and use in day-to-day work

NetBeans provided really nice point-and-click programming of the new HTML 5 components. The new HTML 5 components look very snazzy. Apparently, every new HTML 5 component is itself composed of sub-html-components, called the Shadow DOM and can therefore be styled appropriately. CSS has been split up into approximately 50 CSS modules. JavaScript can be used to avoid having to hide HTML using CSS, because hiding certain HTML components still makes the browser get the linked resources contained in those HTML components. Especially on mobiles this can make a huge difference.

In the Java world, the acronym WORA (Write Once Run Anywhere) is very well known. In the JavaScript world its WONTA (Write Once, Never Touch Again). The projects are so small, and the evolution of the Javascript ecosystem is so quick, it makes more sense to re-design and re-write everything from scratch when required.

Oracle has defined a Javascript framework, which is basically a bundling of common javascript libraries, into what is called the "Oracle Javascript Extention Toolkit"2.

“Javascript is the assembly language of the web.”

Then there's, if you really do not want to touch JavaScript with a ten-foot pole, the transpilers:
write Java, but also HTML and CSS. Combine those.
provides a Java backend similar to the Swing toolkit, and translates your code into HTML,CSS and JavaScript for the frontend.
separate programming language for the web/mobile/desktop.
provides static typing to javascript, a sort of superset of JavaScript following ECMA recommendations that is transpiled to JavaScript
programming language that translates to javascript

The Java renaissance continues - Keynote Oracle

Provided by Sharat Chander

A motivating speech on the fact that Java is still a success primarily because of the community. And a personal appeal to every person there to connect to at least two in the audience during the conference.

Devops - Are you walking or still talking? - Keynote Capgemini

Provided by Remko Reinders

A lecture on Devops, more importantly, what it takes for an organisation to become a success at Devops and what you can do to help your organisation and yourself to become a success as well.

“Most people will talk the talk. Few will walk the walk. Be amongst those few.”
- Steve Maraboli

“Software is eating up the world.”
- Marc Andreessen, Wall Street Journal

Building Asynchronous and Non-Blocking HTTP Applications with Ratpack

Provided by Hubert Klein Ikkink

My first introduction to Ratpack3, which I had never heard of before. It is a small webserver, that can be programmed using Java 8 and Groovy. It uses Netty for the HTTP IO, has a very small footprint, is very fast and is asynchronous. Does not provide JEE, does not follow the Servlet API and can be started by running a Jar file. Spock is used for testing.

If you want a quick webserver to dish out some REST stuff in a distributed environment, this is it. Check his webblog4 for more information.

Java modularity, life after Java 9 - Luminis

Provided by Sander Mak & Paul Bakker

“Good fences make good neighbours.”
- Proverb

An excellent talk about the upcoming Jigsaw in Java 9. It provides a faster startup and a smaller footprint, essential for small devices. It compared what little information there is about Jigsaw to the existing implementation of OSGI. Modules are allowed to talk to other modules only by the service contract each module provides. Modules are defined in a file. The segregation is looked after by the VM itself and cannot be circumvented. Layers are used to prevent different versions of the same module interfering with each other. Versioning isn't really built into the new system. There is a linking tool called jlink and module maker tool called jmod. Jdebs can provide your program with which modules it needs. Identification of a module is done using a newly defined namespace specific for modules.

Classpath scanning for annotations is going to be a problem. It is going to have to be service-oriented in the future.

Especially application servers are going to need a major overhaul, as well as several annotation-crosscutting concerns frameworks as REST and JPA implementations.

See for more information.


[1] NLJUG - J-Fall 2015
[2] Oracle JavaScript Extention Toolkit
[3] Ratpack
[4] Mr Haki's Webblog

Monday, 2 November 2015

J-Fall 2015 Incoming!

The NLJUG[1] is once again organizing J-Fall[2]. Edition 2015 obviously.

It takes place in a new location, as the old location apparently has grown too limiting in number of people allowed. It will be held in CineMec, 150 Laan der Verenigde Naties, Ede on Thursday, the 5th of November 2015. No longer on a Wednesday, that's a change!

Once again I am looking forward to it, to see what I can learn. I shall write up a report on what sessions I visited and found interesting.


[1] NLJUG - Nederlandse Java Users Group
[2] J-Fall 2015

Thursday, 29 October 2015

Making Mistakes In JPQL

Well, crap. My boss mentioned that I introduced a Bug in my JPQL, whilst fixing a Bug.

I think it's a Bug that is easy to create, and is therefore worth a little blogpost.

In Java the || and && operators are short-circuiting operators. This means the expression on the right of the operator will not be evaluated if the expression on the left already makes the entire expression true1.

When using Hibernate (or any other ORM) I do tend to program JPQL in the same way as I program in Java. As this is translated into JPQL, the translation is sometimes not what you would expect.

The class diagram looked something like the following. Bear in mind that each Class represents a table in the database, as is usual in an ORM.

The problem

The following JPQL had an issue:
String queryStr = "SELECT person " +
                  "FROM Person person " +
                  "JOIN FETCH person.function " +
                  "WHERE person.lastname = :lastname " +
                  "AND person.fired = false " +
                  "AND (person.address is null OR person.address.deleted = false) ";
The idea here is to provide us with a list of all Persons with a specific last name, who are both not fired and may or may not have an existing address.

It will be translated by Hibernate (in our case) into the following SQL statement:
select * -- a lot of fields here
from Person person0_ inner join Function function1_ on person0_.FUNCTIONID=function1_.FUNCTIONID, Address address2_ 
where person0_.ADDRESSID=address2_.ADDRESSID 
and person0_.LASTNAME=? 
and person0_.FIRED='N' 
and (person0_.ADDRESSID is null or address2_.DELETED='N')
Can you spot the problem?

The Solution

The problem above, apparently, is that besides the explicit inner join (inner join Function) there is an implicit inner join upon the Address table (from Address address2_ where person0_.ADDRESSID=address2_.ADDRESSID). This means that only persons will be shown that have an existing address. The condition in the where at the bottom regarding "person0_.ADDRESSID is null" is ignored.

The following, slightly more complicated, JPQL solves this problem:
String queryStr = "SELECT person " +
                  "FROM Person person " +
                  "JOIN FETCH person.function " +
                  "LEFT JOIN person.address address " +
                  "WHERE person.lastname = :lastname " +
                  "AND person.fired = false " +
                  "AND (address is null OR address.deleted = false) ";
This will be translated appropriately by Hibernate into the following SQL Query:
SELECT * -- a lot of fields here
FROM Person person0_
      ON person0_.FUNCTIONID=function1_.FUNCTIONID
   LEFT OUTER JOIN Address address2_
      ON person0_.ADDRESSID     =address2_.ADDRESSID
WHERE person0_.LASTNAME   =?
AND person0_.FIRED        ='N'
AND (address2_.ADDRESSID IS NULL OR address2_.DELETED      ='N')


Of course, I would not have made such a crappy mistake, if I did my tests properly. Apparently, testing is hard, and it is easy to miss to test all eventualities.

In this case it is obvious I forgot to test for the Address==null case.

Well, we live and learn.


The JavaTM Tutorials - Equality, Relational, and Conditional Operators
StackOverflow - Explicit vs Implicit SQL Joins

Thursday, 22 October 2015

Running Glassfish on port 80

Well, in short. Linux does not allow non-root programs to listen/occupy ports below 1024. It is a security feature.

So what can I do to make a server that is non-root (because of security) able to receive/send messages through a privileged port? Luckily the question has already been asked multiple times on the Internet.

To summarize:
  • Run the program as root anyway
  • Have a root daemon run the program as root, then change the rootrights automatically to something less
  • Kernel param CAP_NET_BIND_SERVICE
  • Run a proxy server in front of it
  • Software that performs what you want
  • Port-forwarding using IPTables

For the matter of this blog, I am going to assume that I wish to make my Glassfish instance available via both port 80 (the default web port) and port 443 (the default ssl web port). For that is the use case I was faced with.

Run the program as root anyway

Well, that should work, but is a huge security risk in most cases.

We would just need to change the ports of the HTTP Listeners in Glassfish administration console. It can be found in the default-config option.

Have a root daemon run the program as root, then change the rootrights automatically to something less

This seems to be one of the functions of the inetd daemon.


sudo setcap cap_net_bind_service=ep some-binary
In Linux, the things root can do have been broken up into a set of capabilities. CAP_NET_BIND_SERVICE is the ability to bind to ports <= 1024.

Unfortunately, we would need to set the binary to "java". This automatically means that any java program will have the ability to access any ports. This is not what we want.

Run a proxy server in front of it

That's what I did initially. There are lots of web servers that are perfectly capable of redirecting traffic to another port. For example the Apache HTTP server and Nginx. I choose Nginx, as it seems to be quite easy to setup and doesn't come with a lot of extras, extras I do not need.

The excellent part of this solution is that we can use Nginx to serve static webpages/images/files and not bother the Glassfish with it.

Tricky is that I need the original originating IP address of the client, and that is lost without some magic configuration.

The bad part is that a proxy server is another link in the chain that needs to be supported and maintained etc.

Software that performs what you want

For example authbind seems mentioned a lot.

Port-forwarding using IPTables

This is the solution I went for eventually.
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -p udp -m udp --dport 80 -j REDIRECT --to-ports 8080 

# Do the same thing for ssl:
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8181
iptables -t nat -A PREROUTING -p udp -m udp --dport 443 -j REDIRECT --to-ports 8181
Removing all the rules can be done with:
echo "Stopping firewall and allowing everyone..."

iptables -F

iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
To save the configuration, you can use iptables-save and iptables-restore. Or try something like:
]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]


StackOverflow - Is there a way for non-root processes to bind to “privileged” ports (<1024) on Linux?
Debian Administration - Running network services as a non-root user
Ubuntu Help - Iptables HowTo
Oracle Blogs - Byron's Pointless Ramblings - Run GlassFish V3 as a non-root Service on Linux Ubuntu/Debian
The JavaDude Weblog - Glassfish and https running secure applications

Thursday, 15 October 2015

SSL Certificates in Glassfish

There are two files in glassfish1, to wit:
  • ./glassfish/domains/domain1/config/keystore.jks
  • ./glassfish/domains/domain1/config/cacerts.jks
The way I read it, it means your private keys are stored in the keystore.jks, and the root certificates and intermediate certificates of Certificate Authorities (CA) are stored in cacerts.jks. When configured correctly, these two files should contain all the certificates needed to create a necessary chain of trust.

Checking out the keystore, can be done using the following commandline:
keytool -list -v -keystore keystore.jks
The default keystore password is "changeit".
You get the following:
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

Alias name: glassfish-instance
Creation date: May 15, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Owner: CN=localhost-instance, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Issuer: CN=localhost-instance, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Serial number: 43ce5f77
Valid from: Wed May 15 07:33:41 CEST 2013 until: Sat May 13 07:33:41 CEST 2023
Certificate fingerprints:
MD5: C0:FA:88:64:36:7A:1B:62:1B:F1:BD:8F:5A:7A:9A:E7
SHA1: B1:FA:A8:2B:7C:83:18:A8:9B:C6:46:50:41:EC:FC:7C:DF:69:B3:33
SHA256: 52:AB:1F:37:75:68:92:8F:3D:02:49:D7:3C:8E:BC:53:76:9B:68:E2:B8:83:AF:ED:4C:39:99:FE:45:F1:F1:67
Signature algorithm name: SHA256withRSA
Version: 3


#1: ObjectId: Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 56 50 2C 8F D9 A2 55 80 18 8F 3D 90 AC 77 28 C3 VP,...U...=..w(.
0010: FE A0 55 F6 ..U.
Alias name: s1as
Creation date: May 15, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Owner: CN=localhost, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Issuer: CN=localhost, OU=GlassFish, O=Oracle Corporation, L=Santa Clara, ST=California, C=US
Serial number: 4a9972f
Valid from: Wed May 15 07:33:38 CEST 2013 until: Sat May 13 07:33:38 CEST 2023
Certificate fingerprints:
MD5: 79:0D:FC:CF:99:32:2B:BE:77:36:40:4A:14:E1:2D:91
SHA1: 4A:57:58:F5:92:79:E8:2F:2A:91:3C:83:CA:65:8D:69:64:57:5A:72
SHA256: AB:48:B2:E6:C4:4C:50:86:7F:B3:70:30:83:F1:CE:E8:06:F4:B5:75:F0:E3:AD:5B:23:38:10:02:A8:85:F5:56
Signature algorithm name: SHA256withRSA
Version: 3


#1: ObjectId: Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 4C 05 82 BD 8C 02 B8 05 00 04 14 0A FB 29 AA F7 L............)..
0010: 48 6C CB 86 Hl..

There's also a keystore that comes bundled with your java installation, usually it can be found somewhere in the security directory.
You can view all the certificates in there using:
keytool -list -keystore /usr/lib/jvm/java-1.8.0-openjdk-

Backup your keystore.jks

Just a simple copy will do.
cp keystore.jks keystore.jks.backup

Delete the default self-signed certificate

keytool -delete -alias s1as -keystore keystore.jks -storepass

Generating a certificate request

This request we are about to generate, is submitted to the Certificate Signing Authority. See for more information chapter "To Sign a Certificate by Using keytool" in [1]. Using RSA, gives a default keysize of 2048.
[glassfish@vps386 config]$ keytool -genkeypair -keyalg RSA -keystore keystore.jks -validity 365 -alias s1as
Enter keystore password:
What is your first and last name?
What is the name of your organizational unit?
What is the name of your organization?
What is the name of your City or Locality?
What is the name of your State or Province?
What is the two-letter country code for this unit?
Is, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]: yes

Enter key password for
(RETURN if same as keystore password):
[glassfish@vps386 config]$
The CSR (Certificate Signing Request) can then be generated into the file s1as.csr:
keytool -certreq -alias s1as -file s1as.csr -keystore keystore.jks -storepass changeit
Viewing the generated file should look something like the following:

Submit the CSR to a Certificate Authority

I did this using GoDaddy.Com. Most CAs have a web interface that provides this functionality.

Download the CA certificates and any intermediate CA certificates

This is where it gets a little problematic. I keep hearing that a lot of CAs do not provide all or the proper certificates in the download, and you are forced to check out their public repository for the right files.

Then there are all the possible formats in which the certificates can be stored.

Downloading the zip file from, gave me the following files:
the root and intermediate certificates of your CA
your private certificate that should be kept private

Check out the CA certificates

keytool -printcert -v -file gd_bundle-g2-g1.crt

Import the CA certificate and any intermediate CA certificates

keytool -import -v -trustcacerts -alias godaddy -file /home/glassfish/junk/gd_bundle-g2-g1.crt -keystore cacerts.jks -storepass changeit
Certificate was added to keystore
[Storing cacerts.jks]

Replace the original self-signed certificate with the certificate you obtained from the CA

keytool -import -v -trustcacerts -alias s1as -file /home/glassfish/junk/b9683876305fc322.crt -keystore keystore.jks -storepass changeit

Verify the certificate chain

Unfortunately, not providing all the required certificates, to build up the chain will cause an exception when adding your private key4.

openssl s_client -connect
Shows the following Certificate chain:
Certificate chain
0 s:/OU=Domain Control Validated/
i:/C=US/ST=Arizona/L=Scottsdale/, Inc./OU= Daddy Secure Certificate Authority - G2
1 s:/C=US/ST=Arizona/L=Scottsdale/, Inc./OU= Daddy Secure Certificate Authority - G2
i:/C=US/ST=Arizona/L=Scottsdale/, Inc./CN=Go Daddy Root Certificate Authority - G2
2 s:/C=US/ST=Arizona/L=Scottsdale/, Inc./CN=Go Daddy Root Certificate Authority - G2
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
Another way to verify the chain, is by using Microsoft Windows:
In Linux, I find the Keystore-Explorer5 to fulfill my needs:


[1] GlassFish Server Open Source Edition Security Guide Release 4.0
[2] GlassFish Server Open Source Edition Administration Guide Release 4.0
[3] Java Dude Blog - Glassfish V3.1.2 and SSL
[4] StackOverflow - Keytool error java lang exception failed to establish chain from reply
[5] SourceForge - Keystore-Explorer

Wednesday, 7 October 2015

An Evening with Java Champion Martijn Verburg

I managed to attend a lecture of Martijn Verburg1 at the Supernova conference room in the Jaarbeurs in Utrecht yesterevening. Courtesy of Blue4IT.

Martijn Verburg, a.k.a. The Diabolical Developer, provided two interactive sessions. The first was "The Diabolical Developer's guide to Performance tuning" The second was "The Habits of Highly Effective Teams".

"The Diabolical Developer's guide to Performance tuning"

Martijn Verburg is the CEO of JClarity1, a company that does Performance analysis of Cloud applications. JClarity introduced the “Performance Diagnostic Methodology” (PDM) to quickly get to the root of the problem.

The points to aid in analysing performance issues were in the following order:
  1. What is your Cloud made of?
  2. Draw diagrams
  3. Measure each Architectural Layer
  4. What is the CPU doing? Overworked or Bored?
  5. Linux commandline tools are pure awesomeness
  6. Garbage collection logs
  7. Oracle micro benchmarks
  8. Visualvm, Netbeans
The talk had a focus sometimes on the Cloud. He seemed critical of it.

The Cloud, or virtualisation in general, seems to be 20 to 25% slower than the old situation of dedicated hardware. It seems a lot of the time virtualised resources are overcommitted on existing hardware. Apparently with virtualisation it is possible that your performance goes down because of "noisy neighbours", i.e. someone else gets a lot of traffic/cpu/stuff to deal with and the others on the same node suffer.

One of the things he noticed in the field, is that performance issues were seldom the cause of some badly programmed application. The issue was usually located a lot lower in the stack, somewhere between the hardware and the JVM.

When analysing performance, start at the bottom and work your way up. So, check the hardware and the Operating System. What is it doing?

Keep your methods small. Java is better able to optimise small methods during Runtime.


Some tools mentioned:
  • JMeter
  • Gatling
  • there seems to be a JDBC driver, that is nothing more than a wrapper around an existing JDBC driver to analyse the traffic
  • vmstat
  • jcviewer
  • visualvm
  • javap -c
  • Netbeans
  • Protobuf
  • Jitwatch

"The Habits of Highly Effective Teams"

I managed to find the slides at [3].

The points in order were:
  1. Social interaction
  2. Strong leadership
  3. Empowerment over Control
  4. Shared goals
  5. Respect and Trust
  6. Common culture
  7. Automation and tools
  8. Encourage debate
  9. Embrace diversity
He mentioned Dunbar's number, on average people can sustain about 150 relationships.

He mentioned the Peter principle, which was interesting as I had never heard of it.

He did mention that where a lot of managers say that you have to earn respect and trust, that simply does not and will never work. It's better to assume total respect and trust, until you are proven wrong by the person you respect and trust.

When debating a technological something, as we engineers often do, the only thing that has any value in a debate are hard facts and empirical data (and not opinions, assumptions, emotions and the like). If you have an inkling that some decision is wrong, prototype it and verify it. Martijn Verburg and his team use the Matt Raible method, where they draw up a Matrix of all the technologically important stuff and give points for a certain framework where it excels or falls short. Then they start prototyping with the three frameworks with the highest scores.

Make the shared goals SMART (Specific, Measurable, Attainable, Relevant, Time-bound).


Martijn Verburg seems highly quotable. Here are some that stuck in my mind.
“Virtualisation is ruining it for everyone.”
“Seagull managers fly in, make a lot of noise, dump on everyone, then fly out.”
“Having to use swap when running out of memory, is like getting your beer from Pluto instead of the other side of the pub.”
“Don't optimize. Java is way smarter than you are.”
“Lead, follow or get out of the way.”
P.S. the picture at the top of the article is the ceiling of the conference room in the Jaarbeurs in Utrecht. They have some very interesting architecture. Seemed like we were sitting right under a rocketengine.


[1] Blue4IT - Kennisavond met Java Champion Martijn Verburg
[2] JClarity
[3] Slideshare Slides - Habits of Highly Effective Teams

Thursday, 1 October 2015

Calling super constructors

So, a constructor in a subclass, if it needs to call the constructor in the super class, is required to do this in the first line of the body of the constructor1.

If it does not, Java will insert a call to the default super constructor. If it does not exist, you get a compile time error.

So, what if you need to do things, before the super call takes place?

As the object is in the process of being constructed (that's why it's called a constructor), the object is in a non-valid state. This likely explains why the language designers felt that a call to another constructor should be the first part of the body of a constructor.

Well, apparently the only solution is to do everything you need inside the expressions that take the place of the super constructor arguments.

I was forced to do just that in my MudWebException.

So, there's an easy workaround, but it feels clumsy.

Take care not to access any of the methods or properties of the object that is being constructed, as it is in a non-valid state. As a matter of fact, I think it's a really bad idea to call methods in the object from within your constructor.


[1] JLS 8.0 Section 8.8.7. Constructor Body
StackOverflow - Why does this and super have to be the first statement in a constructor?

Thursday, 24 September 2015

Weak Diffie-Hellman and the Logjam Attack

I got the following message when attempting to contact my Glassfish admin console1:
Secure Connection Failed

An error occurred during a connection to SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message. (Error code: ssl_error_weak_server_ephemeral_dh_key)

    The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
    Please contact the website owners to inform them of this problem.
Apparently it is related to a possible LogJam attack6.


Of course, there is a workaround for Firefox2, but that is not what we should do. But for completeness, I'll provide it here:

Workaround for Firefox 39 and above:
  1. In FireFox, enter "about:config" in the URL field and press enter.
  2. Accept the "This might void your warranty!" warning :)
  3. In the search field at the top, enter "security.ssl3.dhe_rsa_aes"
  4. Double click each result (128 and 256) to toggle the Value to "false"


The reason I got this message, was that the server and the client (browser) could not agree on a sufficiently good cipher for the SSL connection. The new version of Glassfish has this solved, because of the extra ciphers it has added3.

If you look at the Appendix below, you immediately notice that the new ciphers all make use of Elliptic-Curve Diffie-Hellman Key Exchange, instead of normal Diffie-Hellman. It seems to be a great deal more secure and doesn't suffer from the Logjam weakness6.

Although it seems unnecessary, you could remove the weak ciphers from GlassFish, to prevent a loophole.5.

Appendix A. Available Ciphers

Glassfish 4.0 (build 89)Glassfish 4.1 (build 13)


[1] StackOverflow - GF4 how to config security protocol to work with firefox v 39x
[2] Mozilla - Questions & Answers
[3] GlassFish Server Open Source Edition Security Guide Release 4.0
[4] GlassFish Server Open Source Edition Administration Guide Release 4.0
[5] ServerFault - Disable support for LOW encryption ciphers for glassfish port no 3920
[6] Weak Diffie-Hellman and the Logjam Attack

Thursday, 17 September 2015

Logic in Epimenides Paradox

The Epimenides paradox reveals a problem with self-reference in logic1.

Epimenides was a Cretan who made one immortal statement:
“All Cretans are liars.”
Now then, there are two statements that are part of the paradox:
  • Epimenides was a Cretan.
  • All Cretans are liars.

If we assume that Epimenides said "All Cretans are liars.", there are exactly four possible outcomes:
Epimenides was a CretanAll Cretans are liars
The Paradox is only visible if both statements be true. In all other cases, there is no paradox, and things go merrily on their way.

Thomas Fowler (1869) made a major mistake in determining the logic negation of the statement "All Cretans are liars.".

He assumed that the opposite of "All Cretans are liars." is "All Cretans speak the truth.". We, hardcore software designers, of course, do not fall for this trap.

The logical negation of "All Cretans are liars." is "Not all Cretans are liars." This, consequently, can be rewritten as "There is at least one Cretan who speaks the truth."


[1] Wikipedia - Epimenides Paradox

Thursday, 10 September 2015

Uncanny Valley

A colleague of mine mentioned that Guildwars 2 became free to play on August 29th 20151. So there is nothing that can withhold me from playing.

In the past, as I am used to World of Warcraft and their cartoony look-and-feel, I had serious problems with accepting the realistic look-and-feel of other games that came out. I found those games creepy. As a matter of fact, I still have this problem in current games.

The same happened to certain films, like "The Polar Express" and "Final Fantasy: The Spirits Within".

When explaining this to my colleague, he mentioned that this is because of the "Uncanny Valley". As I've never heard of it, I decided to look it up2.


[1] Guildwars 2 - Play for free today!
[2] Wikipedia - Uncanny Valley
Wikipedia - Guildwars 2

Saturday, 5 September 2015

LEFT JOIN FETCH returns double results

I recently got a Bugreport from my manager that she was seeing double rows in one of our screens. After a little research I found the culprit to be the following (paraphrased) HQL query.

SELECT order from Order order LEFT JOIN FETCH order.items

The resultset returned from the database will look like this:
As you can see, the order appears twice, once for each order item.

What we want to get from Hibernate is:

What we get from hibernate is:
However, this is by design. As you can see you get two Orders, but they both refer to the same instance. Things are as it should be.

To fix this, see the great answer by Gavin King1 or on StackOverflow2.

When changing the result into:
SELECT DISTINCT order from Order order LEFT JOIN FETCH order.items
The double rows disappears, however the distinct does go through to the database (where it does nothing, as the rows are already distinct) however, it also adds the ResultTransformer implicitly, causing me to get the one row as designed.

Talked about it with the Architect, he doesn't like the use of 'distinct' in HQL queries, because:
  • it is unclear how it will be processed (locally or in the database)
  • may be a cause for performance issues if the distinct is forwarded to your database
  • In general, if you need a 'distinct' in your query to defeat double data, chances are that the query could use some improvements
With an explicit ResultTransformer, the code looks like the following:
List result = session.createQuery("select o from Order o left join fetch o.items"
And the problem is fixed.


[1] JBoss - Hibernate FAQ
[2] StackOverflow - Hibernate Criteria returns children multiple times with FetchType.EAGER

Friday, 28 August 2015

Testing for Exceptions

The old way

There are a few ways of testing for exceptions. The old way was to just catch the exception and then do any asserts that you need. See below:

  • you can do anything you like
  • boilerplate takes up a large part
  • errorprone, for example forgetting to add the fail, means the testcase will pass if there's no exception.


TestNG provides an extention to the @Test annotation that checks for exceptions. In the example below, it is even possible to check that the appropriate exception message is returned (using a regular expression).

  • it is immediately clear that the test tests an error case
  • not possible to do any checks or asserts after the exception is thrown
I did have a discussion with a colleague of mine, regarding the fact that I wished to verify data as well as exceptions.

His argument is, if your test is both verifying data as well as exceptions, you could pull these two apart into two separate tests. One test that tests for the exception, and one test that verifies the data. I countered that, as in his case, both tests verify the exact same behaviour in the SUT (System Under Test), it should be one test. Let me know what your opinions are.


JUnit, in the new version (since 4.7), has an additional solution based on mocking stuff:

  • asserts after the exception is thrown become possible
  • you can do anything you like
  • a little boilerplate
  • not immediately clear that it's an exceptional testcase
  • I don't much like mocking


StackOverflow - JUnit Testing Exceptions
StackOverflow - JUnit test analysing expected exceptions

Saturday, 22 August 2015


We have recently switched over to using Flyway to manage our database scripts at work.

The old way

A network share with a bunch of database scripts, each one dedicated to a specific version of our software product.

This used to work okay, but was a major hassle to keep all these database scripts properly administered.

Never mind the issues with attempting Continuous Delivery.

The new way

Then we finally got 'developer databases', i.e. each developer got her/his own database to fiddle around in.

It was a royal pain every time I recreated my developer database from scratch, to find and locate all the database scripts to get my database up to the correct version for my software.

Now I can just use Maven with a specific Flyway target to migrate my standard database to the version I need. And the database scripts evolve along with the software, so the correct version is always available.

Life just got simpler.



Thursday, 13 August 2015


I recently encountered the following annotation in the source code at work:
It is one I had not seen before. Below is an example of what it looked like.
void updateTaxation(TaxationData data) 
The annotation is part of the package.

It turns out that it is a Marker annotation, simply to communicate to (other) software designers that the access level modifier has been relaxed, to make the code more easy to test.

In the example above, the access level modifier is "default", while it should/could have been "private".

I am still not convinced this is a good thing, because you changed production code to fix a testing problem.

We could work around this issue by using Reflection to access private methods/members, but Reflection is very brittle, especially when dealing with living code. So, that doesn't appeal to me either.

The best way, is to either:
  • test the private method, by using the public api that uses it
  • if this not enough, you can move the private method into a Strategy object1, and test the Strategy object in isolation


[1] Wikipedia - Strategy Pattern
[2] StackOverflow -annotation to make a private method public only for test classes