October 31, 2010

Google Guava v07 examples

We have something called Weekly Technology Workshops at TouK, that is, every Friday at 16:00 somebody has a presentation for everyone willing to come. We present stuff we learn and work on at home, but we also have a bulletin board with topics that people would like to listen about. Last week Maciej Próchniak had a talk about Clojure, this time a few folks asked for an introduction to Google Guava libraries.

Since this was a dead simple task, I was happy to deliver.

WTF is Guava?

It's a set of very simple, basic classes, that you end up writing yourself anyway. Think in terms of Apache commons, just by Google. Just to make your life a little bit easier.

There is an early (v04) presentation and there was a different one (in Polish) at Javarsowia 2010 by Wiktor Gworek.

At the time of writing this, the latest version is v07, it's been mavenized and is available at a public maven repo.

Here's a quick review of a few interesting things. Don't expect anything fancy though, Guava is very BASIC.

@VisibleForTesting


A simple annotation that tells you why a particular property access restriction has been relaxed.

A common trick to use in testing is to relax access restrictions to default for a particular property, so that you can use it in a unit test, which resides in the same package (though in different catalog). Whether you thing it's good or bad, remember to give a hint about that to the developer.

Consider:

public class User {
    private Long id;
    private String firstName;
    private String lastName;
    String login; 
 Why is login package scoped?

public class User {
    private Long id;
    private String firstName;
    private String lastName;
    @VisibleForTesting String login;
Ah, that's why.

Preconditions


Guava has a few preconditions for defensive programming (Design By Contract), but they are not quite as good as what Apache Commons / Spring framework has. One thing interesting is that Guava solution returns the object, so could be inlined. Consider:

Using hand written preconditions:
public User(Long id, String firstName, String lastName, String login) {
        validateParameters(id, firstName, lastName, login);
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.login = login.toLowerCase();
    }

    private void validateParameters(Long id, String firstName, String lastName, String login) {
        if(id == null ) {
            throw new IllegalArgumentException("id cannot be null");
        }

        if(firstName == null || firstName.length() == 0) {
            throw new IllegalArgumentException("firstName cannot be empty");
        }

        if(lastName == null || lastName.length() == 0) {
            throw new IllegalArgumentException("lastName cannot be empty");
        }

        if(login == null || login.length() == 0) {
            throw new IllegalArgumentException("login cannot be empty");
        }
    } 

Using guava preconditions:
public void fullyImplementedGuavaConstructorWouldBe(Long id, String firstName, String lastName, String login) {
        this.id = checkNotNull(id);
        this.firstName = checkNotNull(firstName);
        this.lastName = checkNotNull(lastName);
        this.login = checkNotNull(login);

        checkArgument(firstName.length() > 0);
        checkArgument(lastName.length() > 0);
        checkArgument(login.length() > 0);
    }
(Thanks Yom for noticing that checkNotNull must go before checkArgument, though it makes it a bit unintuitive)

Using spring or apache commons preconditions (the use looks exactly the same for both libraries):
public void springConstructorWouldBe(Long id, String firstName, String lastName, String login) {
        notNull(id); hasText(firstName); hasText(lastName); hasText(login);
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.login = login;
    } 


CharMatcher

For people who hate regexp or just want a simple and good looking object style pattern matching solution.

Examples:

And/or ease of use

        String input = "This invoice has an id of 192/10/10";
        CharMatcher charMatcher = CharMatcher.DIGIT.or(CharMatcher.is('/'));
        String output = charMatcher.retainFrom(input);
 output is: 192/10/10

Negation:
        String input = "DO NOT scream at me!";
        CharMatcher charMatcher = CharMatcher.JAVA_LOWER_CASE.or(CharMatcher.WHITESPACE).negate();
        String output = charMatcher.retainFrom(input);
 output is: DONOT!

Ranges:
        String input = "DO NOT scream at me!";
        CharMatcher charMatcher = CharMatcher.inRange('m', 's').or(CharMatcher.is('a').or(CharMatcher.WHITESPACE));
        String output = charMatcher.retainFrom(input);
output is: sram a m

Joiner / Splitter

As the names suggest, it's string joining/splitting done the right way, although I find the inversion of calls a bit... oh well, it's java.
        String[] fantasyGenres = {"Space Opera", "Horror", "Magic realism", "Religion"};
        String joined = Joiner.on(", ").join(fantasyGenres);
Output: Space Opera, Horror, Magic realism, Religion

You can skip nulls:
        String[] fantasyGenres = {"Space Opera", null, "Horror", "Magic realism", null, "Religion"};
        String joined = Joiner.on(", ").skipNulls().join(fantasyGenres);
Output: Space Opera, Horror, Magic realism, Religion

You can fill nulls:
        String[] fantasyGenres = {"Space Opera", null, "Horror", "Magic realism", null, "Religion"};
        String joined = Joiner.on(", ").useForNull("NULL!!!").join(fantasyGenres);
Output: Space Opera, NULL!!!, Horror, Magic realism, NULL!!!, Religion

You can join maps
        Map<Integer, String> map = newHashMap();
        map.put(1, "Space Opera");
        map.put(2, "Horror");
        map.put(3, "Magic realism");
        String joined = Joiner.on(", ").withKeyValueSeparator(" -> ").join(map);
Output: 1 → Space Opera, 2 → Horror, 3 → Magic realism

Split returns Iterable instead of JDK arrays:
        String input = "Some very stupid data with ids of invoces like 121432, 3436534 and 8989898 inside";
        Iterable<String> splitted = Splitter.on(" ").split(input);
Split does fixed length splitting, although you cannot give a different length for each “column” which makes it's use a bit limited while parsing some badly exported excels.
        String input =
                "A  1  1  1  1\n" +
                "B  1  2  2  2\n" +
                "C  1  2  3  3\n" +
                "D  1  2  5  3\n" +
                "E  3  2  5  4\n" +
                "F  3  3  7  5\n" +
                "G  3  3  7  5\n" +
                "H  3  3  9  7";
        Iterable<String> splitted = Splitter.fixedLength(3).trimResults().split(input);
You can use CharMatcher while splitting
        String input = "Some very stupid data with ids of invoces like 123231/fv/10/2010, 123231/fv/10/2010 and 123231/fv/10/2010";
        Iterable<String> splitted = Splitter.on(CharMatcher.DIGIT.negate())
                                            .trimResults()
                                            .omitEmptyStrings()
                                            .split(input);


Predicates / Functions

Predicates alone are not much, it's just an interface with a method that returns true, but if you combine predicates with functions and Collections2 (a guava class that simplifies working on collections), you get a nice tool in your toolbox.

But let's start with basic predicate use. Imagine we want to find whether there are users who have logins with digits inside. The inocation would be (returns boolean):
Predicates.in(users).apply(shouldNotHaveDigitsInLoginPredicate);
And the predicate looks like that
public class ShouldNotHaveDigitsInLoginPredicate implements Predicate<User> {
    @Override
    public boolean apply(User user) {
        checkNotNull(user);
        return CharMatcher.DIGIT.retainFrom(user.login).length() == 0;
    }    
}       
Now lets add a function that will transform a user to his full name:
public class FullNameFunction implements Function<User, String> {
    @Override
    public String apply(User user) {
        checkNotNull(user);
        return user.getFirstName() + " " + user.getLastName();
    }    
}
You can invoke it using static method transform:
List<User> users = newArrayList(new User(1L, "sylwek", "stall", "rambo"),
  new User(2L, "arnold", "schwartz", "commando"));

List<String> fullNames = transform(users, new FullNameFunction()); 
And now lets combine predicates with functions to print names of users that have logins which do not contain digits:
List<User> users = newArrayList(new User(1L, "sylwek", "stall", "rambo"), 
  new User(2L, "arnold", "schwartz", "commando"), 
  new User(3L, "hans", "kloss", "jw23"));

Collection<User> usersWithoutDigitsInLogin = filter(users, new ShouldNotHaveDigitsInLoginPredicate());
String names = Joiner.on("\n").join( transform(usersWithoutDigitsInLogin, new FullNameFunction()) );

What we do not get: fold (reduce) and tuples. Oh well, you'd probably turn to Java Functional Library anyway, if you wanted functions in Java, right?

CaseFormat

Ever wanted to turn those ugly PHP Pear names into nice java/cpp style with one liner? No? Well, anyway, you can:
String pearPhpName = "Really_Fucked_Up_PHP_PearConvention_That_Looks_UGLY_because_of_no_NAMESPACES";
String javaAndCPPName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL , pearPhpName);
Output: ReallyFuckedUpPhpPearconventionThatLooksUglyBecauseOfNoNamespaces

But since Oracle has taken over Sun, you may actually want to turn those into sql style, right?
        String sqlName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, javaAndCPPName); 
Output: really_fucked_up_php_pearconvention_that_looks_ugly_because_of_no_namespaces

Collections

Guava has a superset of Google collections library 1.0, and this indeed is a very good reason to include this dependency in your poms. I won't even try to describe all the features, but just to point out a few nice things:
  • you have an Immutable version of pretty much everything
  • you get a few nice static and statically typed methods on common types like Lists, Sets, Maps, ObjectArrays, which include:
    • easy way of creating based on return type: e.g. newArrayList
    • transform (way to apply functions that returns Immutable version)
    • partition (paging)
    • reverse
And now for a few more interesting collections.


Mutlimaps

Mutlimap is basically a map that can have many values for a single key. Ever had to create a Map<T1, Set<T2>> in your code? You don't have to anymore.

Multimap<Integer, String> multimap = HashMultimap.create();
        multimap.put(1, "a");
        multimap.put(2, "b");
        multimap.put(3, "c");
        multimap.put(1, "a2"); 
There are of course immutable implementations as well: ImmutableListMultimap, ImmutableSetMultomap, etc.

You can construct immutables either in line (up to 5 elements) or using a builder:
Multimap<Integer, String> multimap = ImmutableSetMultimap.of(1, "a", 2, "b", 3, "c", 1, "a2"); 
Multimap<Integer, String> multimap = new ImmutableSetMultimap.Builder<Integer, String>()
        .put(1, "a")
        .put(2, "b")
        .put(3, "c")
        .put(1, "a2")
        .build();

BiMap

BiMap is a map that have only unique values. Consider this:
@Test(expected = IllegalArgumentException.class)
public void biMapShouldOnlyHaveUniqueValues() {
 BiMap<Integer, String> biMap = HashBiMap.create();
 biMap.put(1, "a");
 biMap.put(2, "b");
 biMap.put(3, "a"); //argh! an exception
} 
That allows you to inverse the map, so the values become key and the other way around:
BiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "a");
biMap.put(2, "b");
biMap.put(3, "c");

BiMap<String, Integer> invertedMap = biMap.inverse();
Not sure what I'd actually want to use it for.

Constraints

This allows you to add constraint checking on a collection, so that only values which pass the constraint may be added.

Imagine we want a collections of users with first letter 'r' in their logins.
Constraint<User> loginMustStartWithR = new Constraint<User>() {
    @Override
    public User checkElement(User user) {
        checkNotNull(user);
        
        if(!user.login.startsWith("r")) {
            throw new IllegalArgumentException("GTFO, you are not Rrrrrrrrr");
        }

        return user;
    }
};    
And now for a test:
@Test(expected = IllegalArgumentException.class)
public void shouldConstraintCollection() {
 //given
 Collection<User> users = newArrayList(new User(1L, "john", "rambo", "rambo"));
 Collection<User> usersThatStartWithR = constrainedCollection(users, loginMustStartWithR);

 //when
 usersThatStartWithR.add(new User(2L, "arnold", "schwarz", "commando"));
}
You also get notNull constraint out of the box:
//notice it's not an IllegalArgumentException :( 
@Test(expected = NullPointerException.class)
public void notNullConstraintShouldWork() {
 //given
 Collection<Integer> users = newArrayList(1);
 Collection<Integer> notNullCollection = constrainedCollection(users, notNull());

 //when
 notNullCollection.add(null);
} 
Thing to remember: constraints are not checking the data already present in a collection.

Tables

Just as expected, a table is a collection with columns, rows and values. No more Map<T1, Map<T2, T3>> I guess. The usage is simple and you can transpose:
Table<Integer, String, String> table = HashBasedTable.create();
table.put(1, "a", "1a");
table.put(1, "b", "1b");
table.put(2, "a", "2a");
table.put(2, "b", "2b");

Table transponedTable = Tables.transpose(table);
That's all, folks. I didn't present util.concurent, primitives, io and net packages, but you probably already know what to expect.

October 17, 2010

Java Developers' Day 2010 review

On the 7-8th of October 2010, Cracow held Java Developers' Day conference. This year it was two days long, so I guess they'll have to think about changing the name. My expectations weren't very high. First of all, I've heard an opinion that JDD is getting worse every year. Second, for the same price as GeeCON you got only one track. Third some of the lectures seemed really uninspiring.

For example, I was afraid, that the one about Flex is going to be the same one I've seen on 4Developers, half a year ago in Poznań. And, of course, there was the one most controversial to all the people I had a chance speaking with, the sponsored lecture from Wipro Technologies, titled: “Wipro in Europe and development opportunities on Polish market”.

Doesn't sound like something you'd like to listen to on a Java conference, does it? More like an advertisement, to me.

Fortunately, my doubts were mostly unfounded.

The first day started a little earlier than planned, with Bill Burke talk about RESTful Java. Quite nice, I must say, as long as you have no idea what REST means, as half of the lecture was very basic. The other part was about JAX-RS (and RESTEasy implementation), and that's where it got my attention. I haven't had a chance to use JAX-RS yet, but the simplicity and efficiency of it is very appealing. I'll have to give it a shot, especially when .NET/Java web service integration is sometimes very painful.

The second talk,  “Java programming in days of multi-core processors”, by Angelika Langer, was gorgeous. Maybe it's because of my limited experience in concurrency, maybe because Angelika presented a more in-depth view on the things happening under the hood, than I am used to, and maybe because she threw away the incorrect model most books present. What I'm sure about, is that Angelika is a great trainer and speaker, with vast knowledge and expertise.  It was a pure pleasure to listen to her and I can only hope to be so passionate and sharp at her age.

Not that she's that old, mind you. It's just that terms like “burned-out” and “tired” do not seem to have anything to do with her.


Then there was Jarosław Błąd from e-point, talking about performance tests in JEE. That was also quite nice, though a little too basic. I wish the speaker could show us a little more real case scenarios and stories, as it was obvious he had a lot of interesting thoughts on that matter, but probably because of NDAs, he decided to go with more theoretical and generic information instead. Anyway, this was a sponsored talk done right. Thanks e-point for not leaving us with just advertisements.

After the lunch came the hit of the day, Ted Neward talk about functional programming for busy developer. A few slides passed by, when Ted asked the audience, whether we would rather see presentation or life coding. Guess what the answer was.

The great thing about the lecture was that Ted didn't use anything more than standard Java, to show us the benefits of thinking in terms of functional languages. The examples were practical, with stuff you can really find from time to time in your code, and the advantages clear and explicit. Somewhere in the middle of the show, Ted said, that he wants us to remember, that we do not have to use anything fancy like Scala, to start solving some classes of problems in a much better way. I only wish he had more time on his hands, but I was lucky to sign in for Scala workshops with him on Friday.

I didn't go for Flex presentation, partially because of the beforementioned doubts, partially because I've met some friends and speakers on the way. I really wish I could be there, on their lectures, especially on Łukasz Kuczera talk about Lift+Comet and Łukasz Szydło presentation about Apprenticeship, but I could either do that or go for the workshop with Ted Neward, and after what Ted had shown us a few hours before, I was sure his workshop will be a mind opener.

And here is for all those anxious about just one track on JDD10. There were actually two on Friday, if you count the workshops, and even though that doesn't seem like much, the quality of what Ted had to offer, beat up the disadvantage of not being able to change every session for something different.

The last lecture on Thursday was “Brave changes: how to make new ideas happen”, given by Linda Rising. While not Java specific, that was quite interesting to me, mostly because of the latest changes I've been part of at TouK (both my own initiatives that you can read about here and here, and overall works on defining company goals and vision). Thing to remember: what your audience is eating is more important than what they are listening to. Scary but true.

Then there was the integration party. And as expected from programmers, Nintendo Wii had a much bigger take than girls :)

For three hours on Friday, I've been enjoying Ted Neward's Scala workshops. I won't give you much details, except it was really great, since Witek Wołejszo wrote a nice summary already.

And I didn't dare to go for “Wipro in Europe and development opportunities on Polish market”. I was afraid, that my positive experience from JDD10 could be a bit reduced.

Overall, another great conference. Thanks to Witek Wołejszo, Piotr Przybyłek and Tomasz Dziurko for this interesting trip.

October 13, 2010

Wicket form submit not safe for redirecting to intercept page

The problem

When you have a form, that anybody can see, but only logged on users can POST, you may want to redirect the user to the login page, and back to the form after login

Using wicket 1.3/1.4, if you do that using redirectToInterceptPage(loginPage) or RestartResponseAtInterceptPageException, after returning, the client will loose all the data entered to the form.

The details

The reason why this happens, is because of how redirectToInterceptPage works. It saves the URL of the requested page, and later, when continueToOriginalDestination is called, it redirects the client to the saved URL using GET. When the last call from the client was a non-ajax POST to the form, the client will be redirected without any posted data. Wicket will handle the situation issuing  HTTP 302 and redirecting the user again, but all the data is already lost.

The funny thing is that the data is actually getting to the form, because of the first POST, but then it's overwritten with nulls on the redirected GET. To make it clear, here's the HTTP conversation:

Client: POST http://localhost:8080/test?wicket:interface=:3:form::IFormSubmitListener:: (post to the form)
Server: HTTP 302 Moved Temporarily (the input was parsed, the model was updated, but you are being redirected to the login page because of redirectToInterceptPage or exception)
Client: GET http://localhost:8080/?wicket:interface=:4:::: 
Server: HTTP 200 OK (server is responding with the login page)
Client: POST  https://localhost:8443/j_spring_security_check.... (post login and password, here using spring security)
Server: HTTP 302 Moved Temporarily (validation is done. Now you are redirected from spring security to the page with wicket redirectToInterceptPage)
Client: GET https://localhost:8443/redirectAfterLogin  (here  redirectToInterceptPage is called)
Server: HTTP 302 Moved Temporarily (you are being redirected the original URL)
Client: GET http://localhost:8080/test?wicket:interface=:3:form::IFormSubmitListener:: (the same URL as the first POST but this time without post data. now your form is being submitted again, but with nulls instead of entered data)
Server: HTTP 302 Moved Temporarily (being redirected by wicket, because of Redirect After Post pattern)
Client: GET http://localhost:8080/?wicket:interface=:3:1::: (back on the form page)
Server: HTTP 200 OK (the form is empty by now)

As you see, if wicket would not redirect you at the end to the url requested by POST, but to the one called by last GET before the original POST, your data would be there.

The issue was reported two years ago. Doesn't look like it's getting fixed any time soon.

The walkaround

If you can require your users to be logged in before you show them the form, you are safe. If not, you can submit the form by AJAX. This will solve the problem, because wicket will recognize, that it cannot redirect the user to the AJAX POST target (<ajax-response> is not exactly what the user would like to have rendered in the browser), and will redirect with GET to the URL of the last page instead, which was also requested by GET. And since the data was converted to the form model in the first POST (line 1), all is well.

And in case you don't want to have a partial page update via AJAX, but would rather like to render the whole page, all you need to do is add setResponsePage(getPage()) to your button. For example like this:


    class AjaxSendButton extends AjaxFallbackButton {
        public AjaxSendButton(String id, Form form) {
            super(id, form);
        }

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form) {
            //process your form input here
            setResponsePage(getPage());
        }
    }

Now your ajax form behaves just like a non ajax form, but can be redirected to an intercept page

The catch

When submitting forms via AJAX you have to be aware, that your form may be submitted without your submit button being clicked on. This may have unforseen consequences. For the whole problem description and a solution go here

October 5, 2010

Video from my presentation at Agile Warsaw

Here's the video from my presentation and the discussion about Agile Skills Project and our experiments in motivating developers at my company, that I had a chance to show at Agile Warsaw.

Do not ask my why the camera is 100% time focused on the wall, I have no freaking idea :) The voices are there, and that matters.

You can either watch it on Parleys: http://parleys.com/d/2019 or right here. Be warned: it's in Polish.