Wednesday, January 30, 2013

Java to Scala idioms: id list from object list

Well, i was amazed.

I just needed to get a list of IDs of database-stored objects, in order to pass them for later-on updates with the 'where ... in' query. And got that with scala mind-blowing way. Instead of Java (please omit comments about lots of auto-boxing and array creation etc -- its only verbosity-related sample):

List dbObjects = ...
ArrayList idArray = new ArrayList(dbObjects.size());
for(DBObject o : dbObjects) {
  idArray.add(o.getId());
}

I would just write something like

val ids = dbObjects.map(_.getId)

And that's it!

Moreover, I'm now using slick with lifted embedding. For it, i need to map objects I want to store in DB to tuples consistent with db schema (prior to insert). I'm now about to do this by providing a mapping function in the Table descendants describing DB schema, and using it whenever I want to store objects. Just need to  think of types a bit so it is consistent,but general use would be, instead of:

DBObjects.insertAll(objects.map(x => (x.id, x.name, ...)) 

I would use

DBObjects.insertAll(objects), while inside this thing would use its own mapping functions.
Great stuff about it is that it is all compile-time checked -- e.g, if I change schema, I will get compilation errors about the tuples don't match on that conversion function.

Isn't that nice?

Monday, January 28, 2013

sbt and IntelliJ idea support

For now, not so as good as Maven integration, however worth seeing.
Found:

  1. https://github.com/mpeltonen/sbt-idea - SBT plugin for generating IDEA files (.idea structure, not the old one) from the SBT build definition.
    Unfortunately, the project created is not ideal -- it adds some additional module for SBT build itself, and in my case it picked up wrong web.xml for webapp.
    It is OK to change this, however as soon as you add another one lib in SBT, you'll have to re-generate and re-configure IDEA again. 
  2. https://github.com/orfjackal/idea-sbt-plugin/wiki - IDEA plugin to run SBT commands in IDE, include to the build process and show notifications in-place. Not too bad. 
Issues with those are that, not alike maven integration, IDEA does not track automatically changes in SBT, and on re-configuration of the build some work is needed. 

On the side, just an idea whether it is possible at all. Maven's pom.xml provides ready model, while SBT provides a set of transformations - some of them may be pretty complex. One would need to run sbt behind IDEA to gather the actual ending values of the Setting[T] at the end. I guess :)

Tuesday, January 22, 2013

Android HttpsUrlConnection, self-signed certificate and hostname verifier

Today, an Android hint. Note for myself for future :)

So, what we have:

  1. Server
    REST (JAX-RS+akka), published to Tomcat. Tomcat serves app via HTTPS having a self-signed certificate (official tomcat docs).
    No CA, no chain - just a single certificate done in a really usual way.
    Tomcat is published on a box accessible only via IP, no DNS here.
    The actual server is https://46.4.224.49 just in case someone wants to take a look @cert.
  2. Client
    Android, trying to talk to the server above in JSON. Should use HTTPS for both traffic encryption and identity confirmation.
Generally, implementation seems pretty straightforward - get the public certificate, and make Android https facilities to trust it. 

I decided to use HttpsUrlConnection rather than HttpClient as the documentation suggest the former was only preferred for small operations in Android versions prior to 3. Trick is that Android is not shipped with the JKS keystore implementation which seems to belong to Oracle (Sun before).

After some googling I combined 3 articles to make a good working example:
  1. http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
    use first 2 steps, how to obtain public certificate off the server, pack it to the BKS keystore and some clues on how to setup BouncyCastle
    (hint - as of early 2013 we need version bcprov-jdk15on-146.jar, though newer is there)
    Added correct line to jre/lib/security/java.security to support another one provider, and dropped the jar into jre/lib/ext. This is only needed for keytool to understand new format.
  2. http://developer.android.com/reference/javax/net/ssl/HttpsURLConnection.html
    Feed HttpsUrlConnection with the SslSocketFactory relying on that keystore. Keystore is put into the res/raw and loaded via context.getResources().openRawResource(int id)
And this is where the trouble started. The test code was producing error. After getting the certificate in the error has changed from 'Not trusted certificate' to 'Can not verify hostname'. Which is progress. 

The very major of the solutions on the Internet were just allowing all the hostname, and even deeper, accepting all the certificates -- which was inacceptable due to security reason.

The certificate had an IP address in CN field. After some research, it was clear that certificate is there, it is trusted, however hostname check fails. That's when DefaultHostnameVerifier was spotted (yes i know javadoc is old, but debugger shows this very class, which is hidden in library-no source). However, old javadoc says clearly that all the checks are declined!

Surely we can not have this check passed as nothing is allowed. 

The issue is resolved easily with setting conn.setHostnameVerifier(new BrowserCompatHostnameVerifier()) - this triggers HttpsUrlConnection to the same mode as the browser (passing *.domain CNs, and IP addresses, etc), which is perfectly OK for our case.