ubuntu 12.04 android sdk fun

Jenkins says:
[INFO] /bin/sh: 1: /home/jenkins/opt/sdk/android-sdk/platform-tools/aapt: not found
[ERROR] Error when generating sources.
org.apache.maven.plugin.MojoExecutionException:

Ehm.. ok.

cd /home/jenkins/opt/sdk/android-sdk/platform-tools/
root@javaone:/home/jenkins/opt/sdk/android-sdk/platform-tools# ls -al
total 23204
drwxrwxr-x 5 jenkins jenkins 4096 Jul 4 13:39 .
drwxr-x--- 12 jenkins jenkins 4096 Jul 4 13:41 ..
-rw-rw-r-- 1 jenkins jenkins 401602 Jul 4 13:39 NOTICE.txt
-rwxrwxr-x 1 jenkins jenkins 929144 Jul 4 13:39 aapt
-rwxrwxr-x 1 jenkins jenkins 204436 Jul 4 13:39 adb
-rwxrwxr-x 1 jenkins jenkins 226004 Jul 4 13:39 aidl
(...)
root@javaone:/home/jenkins/opt/sdk/android-sdk/platform-tools# ./aapt
bash: ./aapt: No such file or directory
root@javaone:/home/jenkins/opt/sdk/android-sdk/platform-tools#

Ok, now WTF?!

root@javaone:/home/jenkins/opt/sdk/android-sdk/platform-tools# file aapt
aapt: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, stripped

Gotcha! 32bit. ia32-libs does this, right?

root@javaone:~# apt-get install ia32-libs
Some packages could not be installed. (...)

The following packages have unmet dependencies:
 ia32-libs : Depends: ia32-libs-multiarch
E: Unable to correct problems, you have held broken packages.

Oh no, you don't!

root@javaone:~# apt-get install ia32-libs-multiarch
Some packages could not be installed. (..)
The following packages have unmet dependencies:
 ia32-libs-multiarch:i386 : Depends: libgphoto2-2:i386 but it is not going to be installed
 Depends: libsane:i386 but it is not going to be installed
 E: Unable to correct problems, you have held broken packages.
 root@javaone:~# apt-get install libgphoto2-2:i386 libsane:i386

 Some packages could not be installed. (..)

The following packages have unmet dependencies:
 libgphoto2-2:i386 : Depends: libgd2-xpm:i386 (>= 2.0.36~rc1~dfsg) but it is not going to be installed
 E: Unable to correct problems, you have held broken packages.
 root@javaone:~# apt-get install libgd2-xpm:i386

 The following extra packages will be installed:
 gcc-4.6-base:i386 libc6:i386 libexpat1:i386 libfontconfig1:i386 libfreetype6:i386 libgcc1:i386 libgd2-xpm libjpeg-turbo8:i386 libjpeg8:i386 libpng12-0:i386 libx11-6:i386 libxau6:i386 libxcb1:i386
 libxdmcp6:i386 libxpm4:i386 zlib1g:i386
 Suggested packages:
 glibc-doc:i386 locales:i386 libgd-tools libgd-tools:i386
 The following NEW packages will be installed:
 gcc-4.6-base:i386 libc6:i386 libexpat1:i386 libfontconfig1:i386 libfreetype6:i386 libgcc1:i386 libgd2-xpm libgd2-xpm:i386 libjpeg-turbo8:i386 libjpeg8:i386 libpng12-0:i386 libx11-6:i386
 libxau6:i386 libxcb1:i386 libxdmcp6:i386 libxpm4:i386 zlib1g:i386
 0 upgraded, 17 newly installed, 3 to remove and 3 not upgraded.

Ok, a few minutes later I could do a:

apt-get --no-install-recommends install ia32-libs-multiarch

And..

root@javaone:/home/jenkins/opt/sdk/android-sdk/platform-tools# ./aapt
<pre><pre>Android Asset Packaging Tool

Usage:
 aapt l[ist] [-v] [-a] file.{zip,jar,apk}
 List contents of Zip-compatible archive.

It works. Let's make a chef out of it and be happy 🙂

High season?

I get around 5 job offers a day, mostly sad intranet userless “maintainance and development” where anybody able to write forms in JSF/Struts 1 would do – not my cup of tea. Recently however I have received a call from a technical recruiter from one of the polish companies (which was present at Confitura) and.. we actually had a nice talk. Not only did my interlocutor ask about SOLID, but he knew about threads! And memory flushing with volatiles plus he has read Java Concurrency in Practice.. “the” book for Concurrency in Java for the past few years. And he heard about Java Memory Model! I was pleasantly surprised with the person’s level and attitude. And I really wish more organisations would do such things, it would definitely improve the overall feelings many share towards any form of “employee seekers”.

Legacy Code Retreat

Last Saturday, we’ve had a Legacy Code Retreat. As usual, ABB was kind enough to provide us with the rooms (it’s kind of a tradition to have retreats there now). Anyway, the event was a bit different from a traditional Code Retreat – this time, we were not trying to implement Conway’s Game of Life. We battled with code, written by somebody before about which we didn’t know too much. The event was fun, and from my point of view it was the smoothest CR we’ve done – the biggest change was most probably that there were 6 people available to help and look after (4x) others (official term is facilitators, but I don’t like it). Before, when we were trying to work in just 3 people, it was much harder – for us to code at least a bit, for us to be able to spend an adequate amount of time at what everybody was doing.

As for the activities, we spent the first session getting the general hang of the problem and trying to prepare a Golden Master for further testing. It was particularly useful to actually have met a week before and write the Golden Master in many of the available languages – it turned out that our initial impressions about what performs how during 10000 iterations were sometimes off by an order of magnitude. Or two.

The best session there was (maybe because I managed to code) was “quick refactorings” – finish refactor within 2 minutes or

git checkout -- .

Went surprisingly well, we only reverted our changes once and managed to do quite a lot.

What turned out to be the two, most problematic things?
1) Network access. You need it to share code among people.
2) Many people do not know git.

And since a picture..

Legacy Code Retreat

Confitura

The best Confitura I have been to so far.

Great people, amazing atmosphere, tons of prizes, interesting quizzes, sponsors with capable and very approachable people at booths.. with technical things to talk about!

Confitura has always been a “family” conference to me, meaning: I spent a lot of time in the corridors talking. but this year.. I’ve been to most of the talks. The only talk I couldn’t stand and left after 5 minutes, was “Patters”, which wasn’t, nicely put, approachable.

But then.. Akamai and their keynote. It was the first US-based company presentation that included a slide with the globe centered on Europe. Plus their attitude towards DDOSes – nice, very nice 🙂

News of the day: Waldek Kot znowu nadaje. This was the first presentation since long in which I’ve actually been looking forward to an “About me” slide. On top of that, the code samples were good, live coding worked.. well, classy Waldek is classy! Then Jakub Nabrdalik with Tomek Przybysz – engaging ping pong and good content up to grails intro. Tomek Nurkiewicz’s “if avoidance” had some good, real-life examples of bizzare things. Bizzarre up to the 45th level, as in 45-level polynomial instead of a 6-branch if. First reaction: huge WTF! Imagine finding such “treasure” in the codebase. I’d be off cycling in no-time. Then me with “Continuous Delivery”, slides are on SlideShare.

And then, the closing keynote. Then the most hilarious talk I’ve heard since “The Diabolical Developer”. At least comparable – full of energy, strong emotions, bias and mocking people who just learnt 3 annotations from Hibernate, became promoted and apply to a company that actually cares about code. The reactions were very mixed, but I enjoyed the talk and, well, agree with at least half of it.

Once again, the best Konficzer I’ve been to!

Dropbox or.. my 3*10^-2PLN

Here’s the use case: I’ve got a big load of pictures which I want to be able to work on using my desktop or notebook as I please.
Data transfer during such activity is minimal, limited to updating a relatively small catalogue file and (mostly) deleting files I reject. I’ve tried DropBox, it’s nice and does the job, but.. RAW files are big, and I usually end up with 20-30GB of data. Plus preview files, plus something.

What I could do is put them on a separate hard drive… but that’s slow. I tried – maybe an SSD external harddrive would do the job, but still, I would be limited by firewire/USB lags. And couldn’t easily benefit from multi-harddrive setup.
I decided to use the files locally, but put them into a cloud storage to do the rsyncing, but it sucks because I have to do it manually.

I don’t do my pictures on Linux, so having a Linux client is not required.

So.. dropbox: nice, simple, handles conflicts nicely plus does lan sync. Almost perfect, because price tag is higher than Google Drive.
Google Drive: I have it anyway with my gmail account, usually uploads are fast.
Problems? A few. Client hangs and needs to be restarted, doesn’t know what to do if the same file is being uploaded from two computers at the same time and does not do LAN sync.

So.. because it’s 5$/month, I’m staying with Google Drive. Does the job, even though I have to let it upload from a single source for a day.

Maybe they fix it.. 😉

So.. you’d like to hire?

  1. What salary range are we discussing?

Basics

  1. What’s your dress code: do you wear casual clothes, business casuals, suits or does nobody care as long as it’s not revealing? What about spring/summer – are tshirts/shorts/sandals ok?
  2. What is the typical hardware setup for development – I love to work with 2 big screens (NOT a notebook + screen), with a powerful development machine, either a notebook w/ docking station or a powerful (>=4 core, >=8GB RAM) desktop. What’s yours?
  3. Which java version, frameworks, servers?
  4. I love using IntelliJ IDEA, is it a problem?
  5. Can I park my bike in a *safe* place? Next to my desk is ideal, next room probably as well.
  6. Is there a shower in the office?
  7. Which version control do you use, is it centralised (svn, perforce) or distributed (git, hg)
  8. What environment do you use for development (Windows or Linux or ..?) and deployment?
  9. What time do you start/finish work?
  10. Do you work in any ‘strange’ times – evenings, holidays, weekends?
  11. Do you do overtime? How much, how much is it paid, what’s the average overtime per month per developer?
  12. Which day of the month do salaries get transferred?
  13. Do you have a wiki? A library? Conduct internal trainings? Send people to trainings? Have a conference budget?
  14. Who chooses technologies used in projects? What role will my voice play there?
  15. Do you use a CI sever? Sonar?
  16. Who chooses technologies in the projects? How do you build them?
  17. What apart from java: groovy, scala, clojure, …?
  18. Can I work from home? Can I leave for a few hours and then make up for it later?

Ubuntu, fakeraid and GRUB problem

The case: Ubuntu 11.04 (Gnome 2 FTW) and newer fail to install on fakeraids. It’s even worse, setup claims to have installed everything correctly yet no system boots upon reset.

Here’s a what fixed it for me:
1) Run LiveCD, choose Try Ubuntu, run installer, don’t reboot after install.
2) CTRL-ALT-T (open terminal)

sudo mount --bind /dev  /target/dev 
sudo mount --bind /proc /target/proc 

3) Chroot into installed Ubuntu

sudo chroot /target
dpkg-reconfigure grub-pc

Grails – automatically reconnect to MySQL datasource

Well, I’m using Grails for a huge amount of quickly hacked apps.
Most of them use MySQL for persistence, because it just works 🙂

There is one problem with the driver, though – sometimes, when nothing is happening, it allows the connections to disconnect.
It wasn’t a matter of one option somewhere, unfortunately 🙁

According to MySQL JDBC driver configuration page, it might be enough to add

autoReconnect=true

to have

    development {
        dataSource {
            dbCreate = "create-drop"
            url = "jdbc:mysql://mysqlhost/database?useUnicode=true&autoReconnect=true"
            username = ""
            password = ""
        }
    }

But it doesn’t solve it ;(
After some searching, cursing and a beer, I’ve ended up with:

dataSource {
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    username = "secret"
    password = "santa"

   properties {
      maxActive = 50
      maxIdle = 25
      minIdle = 1
      initialSize = 1

      numTestsPerEvictionRun = 3
      maxWait = 10000

      testOnBorrow = true
      testWhileIdle = true
      testOnReturn = true

      validationQuery = "select now()"

      minEvictableIdleTimeMillis = 1000 * 60 * 5
      timeBetweenEvictionRunsMillis = 1000 * 60 * 5
   }
}

And this has been good enough to solve my pains. Thank you grails, for making me have problems I wouldn’t otherwise have.
Nice of you to allow me to fix them pretty fast at the same time 🙂

Sun Certified Java Developer

Today I received a following email:

“Hi Andrzej,
Congratulations! You have passed the Oracle Certified Master, Java SE6 Developer certification. You are among the elite 1% of certified Java professionals who have gone on to achieve the Oracle Certified Master, Java SE6 Developer certification.”

In comparison to the previous exams I took at Sun/Oracle, below was a bit of a change:

You have received a passing score. Passing grades do not receive a score, just the pass.

So card telling me how much luck I had in passing (except for “enough”).

The exam itself was surprisingly lot of fun to do, however without support from Oracle I would fail at problems caused by transition from Prometric to Pearson.

jTDS SQL driver in Glassfish

jtds in glassfish v3

cd /opt/servers/glassfish-3.1.1/glassfish/domains/domain1/lib
ln -s /opt/tools/maven-repo/net/sourceforge/jtds/jtds/1.2.5/jtds-1.2.5.jar

let’s setup the connection pool in the admin console. Ping works, seems to work?

[#|2011-10-01T20:27:09.078+0200|SEVERE|glassfish3.1.1|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=17;_ThreadName=Thread-3;|WebModule[/RTSuiteWeb]StandardWrapper.Throwable
java.lang.AbstractMethodError
	at com.sun.gjc.spi.jdbc40.ConnectionHolder40.init(ConnectionHolder40.java:96)
	at com.sun.gjc.spi.jdbc40.ConnectionHolder40.<init>(ConnectionHolder40.java:87)
	at com.sun.gjc.spi.jdbc40.ConnectionWrapper40.<init>(ConnectionWrapper40.java:64)
	at com.sun.gjc.spi.jdbc40.Jdbc40ObjectsFactory.getConnection(Jdbc40ObjectsFactory.java:90)
	at com.sun.gjc.spi.ManagedConnection.getConnection(ManagedConnection.java:462)
	at com.sun.enterprise.resource.allocator.LocalTxConnectorAllocator.fillInResourceObjects(LocalTxConnectorAllocator.java:119)
	at com.sun.enterprise.resource.pool.ConnectionPool.getResource(ConnectionPool.java:488)
	at com.sun.enterprise.resource.pool.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:242)
	at com.sun.enterprise.resource.pool.PoolManagerImpl.getResource(PoolManagerImpl.java:167)
	at com.sun.enterprise.connectors.ConnectionManagerImpl.getResource(ConnectionManagerImpl.java:338)
	at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:301)
	at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:236)
	at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165)
	at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:160)
	at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:113)

Bazinga!

Let’s see some source code:

protected void init() {
    try {
        defaultClientInfo = getClientInfo();
    } catch (SQLException e) {
        _logger.log(Level.INFO, "jdbc.unable_to_get_client_info", e.getMessage());
        if(_logger.isLoggable(Level.FINEST)) {
            _logger.log(Level.FINEST, "jdbc.unable_to_get_client_info", e);
        }
    }
}

com.sun.gjc.spi.jdbc40.ConnectionHolder40.java

    public Properties getClientInfo() throws SQLException {
        checkValidity();
        return con.getClientInfo();
    }

com.sun.gjc.spi.base.ConnectionHolder.java

protected void checkValidity() throws SQLException {
    if (isClosed) throw new SQLException("Connection closed");
    if (!valid) throw new SQLException("Invalid Connection");
    if (active == false) {
        mc.checkIfActive(this);
    }
}

Ok, so it’s the jdbc driver. Glassfish fails with an ConnectionJDBC3 object So.. let’s check the code

net.sourceforge.jtds.jdbcx.proxy.ConnectionProxy.java

public Properties getClientInfo() throws SQLException {
    // TODO Auto-generated method stub
    throw new AbstractMethodError();
}

Ant this indeed throws AbstractMethodError 😐

There is no newer version than 1.2.5. The thing is that jtds used to be compatible with jdk 1.3 and 1.4. JDK 5 brought JDBC 4.0, which brought many new methods in the java.sql.Connection. JTDS doesn’t claim to be implementing these, just wants to be compilable against jdk5/6 – hence AbstractMethodErrors. Some history about this

JDBC 4.0 API is supposed to be backwards compatible, there is no problem with using Java SE 6 with JDBC 3.0 drivers, as long as you do not use the new methods or classes there were introduced in JDBC 4.0 API. That’s the theory at least, since if you want to compile against newer api, you have to include some implementation of new methods.

How exactly does it happen that Glassfish decides a driver is JDBC 3.0 or 4.0 (or 4.1, introduced by JDK 7)? That’s pretty simple:

public void detectJDBC30Connection(Connection con, com.sun.gjc.spi.ManagedConnection mcObject) {

    String dataSourceProperty = mcObject.getManagedConnectionFactory().getJdbc30DataSource();
    if (dataSourceProperty != null) {
        setJdbc30Connection(Boolean.valueOf(dataSourceProperty));
        initJDBC30Connection = true;
    } else {
        try {
            Class paramClasses[] = new Class[]{Class.class};

            Method isWrapperMethod = con.getClass().getMethod("isWrapperFor", paramClasses);
            int modifiers = isWrapperMethod.getModifiers();
            setJdbc30Connection(Modifier.isAbstract(modifiers));
        } catch (NoSuchMethodException e) {
            setJdbc30Connection(true);
        } catch (AbstractMethodError e) {
            setJdbc30Connection(true);
        } catch (Throwable t) {
            setJdbc30Connection(true);
            _logger.log(Level.WARNING, "jdbc.unexpected_exception_on_detecting_jdbc_version", t);
        } finally {
            initJDBC30Connection = true;
        }
    }
}

And by mixture of the above, we have a problem, since jTDS claims to have a method which doesn’t work.
Solutions? There are 3:

  • get a proper JTDS version or something that will be detected as a proper JDBC3 driver. Latest version still using jdk4 was 1.2.2. And it works perfectly.
  • Use a different driver. I don’t have much experience with Microsoft SQL and JDBC yet, but there is a quite new driver from Microsoft itself, probably worth giving a spin.
  • Complex solution: fix JTDS driver.