Wednesday, January 27, 2010

Autoboxing "Pitfall"?!

Just recently somebody kicked off a discussion about the strangest language feature.

Naturally, as expected, somebody came up with this example in Java:

Integer foo = 1000;
Integer bar = 1000;

foo == bar; // false

and calls it "Fun with auto boxing and the integer cache in Java."

Browsing the web, it seems that this "feat" has been blogged about in other occasions as well (e.g. Autoboxing pitfalls when comparing numbers with “==”, ).

Despite the fact that it may be "odd" for some observers, there are two facts that disturb me about the way its presented:

1) it is perfectly specified behavior that will most likely not change; and
2) there is no autoboxing involved at all.

Here is what really happens:
foo==bar;
is an equality operator expression, as specified in the Java Language Specification, 15.21 Equality Operators.

The specification in 15.21.1 Numerical Equality Operators == and != clearly states:

If the operands of an equality operator are both of numeric type,
or one is of numeric type and the other is convertible (§5.1.8) to numeric type,
binary numeric promotion is performed on the operands (§5.6.2).
If the promoted type of the operands is int or long, then an integer equality test is performed;
if the promoted type is float or double, then a floating-point equality test is performed.

Note that binary numeric promotion performs value set conversion (§5.1.13) and unboxing
conversion (§5.1.8). Comparison is carried out accurately on floating-point values,
no matter what value sets their representing values were drawn from.


Now, the key part here is are both of numeric type, or one is of numeric type and the other is convertible.

Integer is NOT a numeric type (see 4.1 The Kinds of Types and Values), but rather a reference type, and the section 15.21.3 Reference Equality Operators == and != applies.

Summing up, if it is a pitfall at all, then it is the fact that the equality operand applies equivalence according to the types of the operands. However, specially in Java this has been known since quite a long while: remember String equality?

Maybe it is rather an expected result.

Objects in Java should always be compared with the equals method and primitive type wrappers ARE Objects.

As a side note on the surprise about implementations caching primitive type objects, well, all of these primitive wrappers and Strings are immutable (i.e. objects whose state cannot change after construction), so there can't be any "real" surprise if one and the same instance is shared.

Just always remember, for reference types, reference equality applies, so for cached instances, the reference equality operation may return true:

Integer foo = 42;
Integer bar = 42;

foo == bar; // may be true

Wednesday, January 13, 2010

Enhanced RADIUS Authenticator for Confluence

Recently I was looking into authenticating against a RADIUS server from Confluence, and luckily I found some previous work to build on.

While it may soon be deprecated, and I don't yet understand how this can be integrated as a plugin, it still does the job, except that I needed some extras:

  • An authentication cache

  • User creation at the first login

  • Default initial group assignment when a user is being created


I have implemented these features on top of the existing sources, and made it configurable

<init-param>
<param-name>radiusauth.cachesize</param-name>
<param-value>SIZE you need (int, e.g. 100)</param-value>
</init-param>
<init-param>
<param-name>radiusauth.initialgroups</param-name>
<param-value>Initial groups (comma separated list e.g. confluence-users,staff-users)</param-value>
</init-param>

Maybe this is useful to somebody, so I make it available here.

Enjoy...

Saturday, January 02, 2010

Visuals from Tecajetes, Xalapa, Veracruz










see more photos from a trip to Veracruz at Flickr.