I just started hating Java

By Confusion on Thursday 7 January 2010 15:42 - Comments (32)
Categories: Java, Python, Software engineering, Views: 8.387

A new year, a new hatred. I've just officially begun hating the language in which I do most of my work: Java. The tiresome verboseness finally got to me. Please compare with me:


Java:
1
2
3
4
5
6
7
8
9
10
11
12
private static String joinObjectFields(final List<SomeObject> objects, 
        final Character seperator, final SomeObject exclude) {

        String result = "";
        for (SomeObject object: objects) {
            if (!object.equals(exclude)) {
                result += object.someField + seperator;
            }
        }
        // Strip last ; (and see edit3)
        return result.substring(0, result.length() - 1);
    }




Python:
1
2
3
4
def joinObjectFields(objects, seperator, exclude):

  fields = [object.someField for object in objects if object != exclude]
  return seperator.join(fields)



To prevent "these pieces of code don't do the same thing", an alternate Java implementation, more like the Python one:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private static String joinObjectFields(final List<SomeObject> objects, 
        final Character seperator, final SomeObject exclude) {

        final String[] fields = new String[objects.size()];
        for (int i = 0; i < fields.length; i++) {
            if (!object.get(i).equals(exclude)) {
                fields[i] = object.someField;
            }
            else {
                fields[i] = "";
            }
        }
        return StringUtils.join(fields, ';');
    }


Doesn't get much better, even if you would initialize the array to contain "" in every field using a utility method.

For extra hatred, consider the necessary changes to the code to enable the same method to join the contents of a different object field.

Edit: A colleague noted that cloning the list and removing the 'exclude' would make matters slightly better.

Edit2: And before someone starts calling me a Python fanboy: you can also do this in a much shorter fashion in Scheme, Ruby, Perl, Scala, Lisp/Clojure, etc.

Edit3: And of course I stupidly forgot to check whether result.length() is actually > 0 in the first implementation.

Edit4: As JanDM rightly points out, I shouldn't use curly braces in Python :P.

Edit 5: This version in Java, posted by Markus in the comments, is far superior: I wasn't making any sense here: the code does a different thing.

Avoid storing configuration data in your revision control system

By Confusion on Tuesday 20 October 2009 22:02 - Comments (3)
Categories: Java, Software engineering, XML, Views: 4.939

After a discussion with a colleague this afternoon, I thought I'd share the following: you should avoid storing configuration data in your revision control system. Especially authentication credentials should not be in there. Here's why:
  1. When securing servers and networks, things like the server hosting an RCS don't get the same priority as, say, your web facing production server. Mistakes are easy to make and you can simply use Google to find 'accidentally' web facing RCS's that expose passwords.
  2. There will be plenty of copies 'out there', outside of your control. How many developers have that data stored on their machine? How careful are they with their laptops and your production passwords?
  3. Access to the configuration is limited to those that should be able to change it: no accidental changes by a junior performing a careless check in.
  4. If you can use the exact same build for your development, test/staging and production environment, then you can cleanly separate between code problems and configuration problems. If you need to rebuild a distributable archive to have the build process include environment-specific configuration, there will always be the doubt that some other difference may have sneaked in.
  5. It's much easier to change the configuration if you don't have to make a new build to deploy the change.
Now I specifically say 'avoid' and not 'do not ever', because many frameworks do not make this separation particularly easy. In the Java world, standard frameworks like Maven, Spring and Hibernate all impose obstacles to succeed at keeping sensitive configuration data out of RCS's.

Maven is a build tool that offers all kinds of build-time placeholder substitution capabilities, which is diametrically opposed to this advice. Spring does dependency injection and the configuration to wire your application together strongly attracts other types of configuration data to be included with it. And if you are paranoid enough to give production databases different names, so you can never accidentally run a test against a production database: how do you get that name into your Hibernate OR mappings at startup time?

It takes careful thought and thorough understanding of the build and startup processes, but in my opinion it is well worth it. Every time I deploy a new version of the one application in which configuration and code are completely separated, where I just have to drop a new .jar and restart, I dance with joy.

Be sure to know enough of the language you are arguing against

By Confusion on Monday 22 June 2009 17:31 - Comments (3)
Categories: Python, Software engineering, Views: 2.945

A flamewar ensues, where people try to show that their solution in their favorite language is better. Well, that didn't really happen, but it makes for a more dramatic ending.

[1] I don't claim he's serious. In fact, I think he just ends his post on a tongue-in-cheek, semi-hopeful note.
[2] Singling out the least interesting part of the blog post as the title of his submission, IMHO
[3] Which explains the title of this post: if you don't have at least that much understanding of a language that you know whether a certain solution is possible or not, than you probably shouldn't be commenting on it.
[4] Act 4 has many variations, but usually people produce a different solution in the original language that approaches the solution in the alternative language.

Installing DB2 Express C on linux

By Confusion on Saturday 20 June 2009 15:43 - Comments (2)
Category: Software engineering, Views: 5.648

For anyone else trying to install DB2 Express C, the free community edition of IBM's DB2, on his linux system and running into problems:
  • You need to source sqllib/db2profile in every shell where you are going to run commands from sqllib/bin:
    code:
    1
    
    confusion@ulm:~$ . sqllib/db2profile

  • Running the db2val validation program multiple times in a row can yield different results. For instance, on the first attempt, it told me it couldn't find the sqllib/logs directory. However, that one was already present (perhaps created by db2val?) and when I ran the validation program again, it noticed that.
  • If db2val fails to start your instance with
    SQL1220N The database manager shared memory set cannot be allocated.
    then you probably need to increase the maximum amount of shared memory the kernel may allocate:
    code:
    1
    
    sysctl -w kernel.shmmax=268435456


    The default is 32M and this increases it to 256M, which turned out to be enough. For 64-bit systems, they advise pushing it to 1GB.

    Edit: As moto-moi points out in the comments, this is a temporary change that will disappear with a reboot. To make it permanent, follow his instructions.
  • If running
    code:
    1
    
    confusion@ulm:~$ sqllib/adm/db2start

    returns
    SQL10007N Message "-1390" could not be retrieved. Reason code: "3".
    then you probably forgot the first step I described here.
  • If you try to make a connection from your favorite programming language and you receive
    ROOT CAPABILITY REQUIRED
    then you probably did a non-root install. Unfortunately, DB2 doesn't have any DB-level users: all user management, including authentication, is delegated to the OS. On a *nix system, the routine checking the password usually requires root privileges. The problem is that the file sqllib/security/db2ckpw needs to be owned by root and needs to have its setuid bit set:

    code:
    1
    2
    
    chown root db2ckpw
    chmod u+s db2ckpw


    I first found the file sqllib/security32/db2ckpw, but that doesn't seem to be used on linux. Might be the Windows version? Afterwards, perform a

    code:
    1
    2
    3
    
    db2 force applications all
    db2stop
    db2start


    The first command breaks all connections, otherwise the db2stop probably won't work.
  • Keep an eye on sqllib/db2dump/db2diag.log: that's where interesting logging about DB2's functioning ends up. The db2diag command can be used to extract information from that file and can be used to tail it, if you haven't done so already.
  • A warning I encountered in the db2diag log was
    The user per process file descriptor limit of 1024 is less than the maxfilop setting of 30720
    This can be solved by issuing

    code:
    1
    
    ulimit -n 32768


    However, that usually won't work, as the default limits prevent you from going above 1024. To overcome that limit, add the following line to /etc/security/limits.conf

    code:
    1
    
    your_db2_user hard nofile 32768


    After that, you need to open a new shell (for that user) (if you are running an X environment: restart X) and the new shell will have it maximum number of file descriptors set to 32768 after you issue the ulimit command. Now all you need to do is restart DB2.

A simple Java puzzler

By Confusion on Thursday 18 June 2009 14:59 - Comments (17)
Categories: Java, Software engineering, Views: 2.969


Java:
1
2
final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365;
        System.out.println(YEAR_IN_MS);


What will be printed?