Developing ANDROID sucks!

DISCLAIMER: you guessed it, this is a rant!

I am very interested in doing mobile development as a hobby. I started iOS development about a year ago but i stopped after publishing my first iPhone app dzone mobile because i thought that all those AppStore™ and iTunes Connect™ stuff was a pain in the ass and distracting me from beeing productive.

So I began developing this same app for the ANDROID platform, in order to get a feeling for it. I’ve been doing Java for about 7 years now, so developing on ANDROID should be rather familiar to me instead of learning all this verbose Objective-C nerdy pointer stuff. I am very well known to Eclipse, so working with the ANDROID Plugin should be easy, right?

I started the app in November of 2010, when I had some spare time between jobs, but somehow I stopped in the middle of the project and just recently started all over. I was wondering why I had not worked on the app for about half a year?

The answer is simple: Developing ANDROID sucks!

Eclipse

I stopped working with Java in the middle of last year, switching to Ruby development with TextMate and MacVim. Coming back to Eclipse is like getting hit by a truck! This IDE is so overwhelming, but instead of giving you what you need it hides the most common features, so that you have to search for it on stackoverflow.

Is it really necessary for me to do Open-Clean-Refresh-Close-Open-Refresh cycles on my project to let Eclipse realize that everything is fine besides Eclipse itself?

Why do people, building Eclipse plugins, make the same errors again and again? Swallow errors, so that you need to have the Error Log View open all the time? Show build failures without any hints? Are you serious about that LogCat stuff? WTF?

I am using the debugger all the time when I am new to some Framework in order to better understand what is going on. But this is not very usefull unless you can see the source code of where you currently are… Guess what, it’s reeeeally hard to get it going!

Emulator

The ANDROID Emulator is really slow on the Mac. I don’t know if it’s much faster on other systems, but i think it sucks. The startup time takes even more than eclipse, you need to fiddle around with runtime settings in order to adjust it to your needs and why is it so difficult to put all the options you have in the menu bar instead of hiding it somewhere in the function keys?

But the best thing is, that the emulator is just not working right in the beginning.

It does not properly respond to mouse gestures or the keyboard and ah yeah, I forgott, it’s ugly!

Desing-Flaws

Developing for iOS is a tough choice if one is coming from a language like Java that has a decent Runtime with garbage collection. I spent most of my development time with allocation/deallocation problems. This is something you really need to get into if you want to have fun working with Objective-C even though they just released ARC (automatic reference counting) on iOS 5. Besides that, I really think that iOS does a better job in designing an architecture that is developer friendly.

The thing that I just can’t get over on ANDROID devices is that the application (the activity to be precise) is going to be reloaded if you rotate your device and you need to take care of a lot of things in order to let your app respond to that interaction. Just have a look at your future self

It’s really sad to me, that the ANDROID designers decided to repeat the bad design decisions that had been established in Java Enterprise™ all over again! It took the Java community about a decade to step back and come to frameworks where developer productivity is THE thing to focus on. All the rookies that start their “Java career” with ANDROID will be doomed to go through this same process again! Poor bastards…

XML

Finally! Let’s define everything in XML! I am getting bored at bashing on XML…

$ find . -name "*.xml"
./AndroidManifest.xml
./res/layout/details.xml
./res/menu/options.xml
./res/values/strings.xml
./res/xml/preferences.xml

iOS is also using XML for their interfaces, but they hide all that shit behind a really decent InterfaceBuilder!

The Builder and XML Tools in the Eclipse Plugin are so ugly that i rather write the whole shit by hand, BITCHES!

Tight coupling

Why, for gods sake, did they come up with the idea to use inheritance for everything in ANDROID? It’s even worse than in J2EE because you are not bound to Interfaces but Classes! Hello dear ANDROID designers, there is no such thing as Mixins or Multi-Inheritance in Java?! How am I supposed to write clean code with that? Answer: You are not going to write clean code anyway, because you have to do premature optimization on your code so that it can run on all the shitty ANDROID devices! YEAH!

Just forget everything you learned form state of the art frameworks like MVC or DI. It’s just not possible! BY DESIGN!

Just put state, lifecycle, business and view logic in one class; also helps reducing your package size, HOORAY!

Checked Exceptions

Do we really need more Checked Exceptions? Really?

Testing

Writing tests for iOS was nearly impossible at the time I was doing it. Even the guys at the Cocoaheads Hamburg did not know how to get it running. But this situation has improved over the last months. Special thanks to XING for doing a lot of research there and presenting it on the Usergroup!

I thought that testing for ANDROID would be really cool, because the Java community has a really strong background on TDD and Testing is even a Topic on the Dev Guide, even though it is the LAST one…

Let me make it clear to you: Testing ANDROID sucks!

Because of all the tight coupling and multithreaded environment it is nearly impossible to test something. Even simple tasks like testing your Utility-Methods needs to be done in the Emulator! Just have a look at this multiscreen setup guide of how to get it running with JUnit (Hello?! JUnit 3 is deprecated for YEARS!).

Despite all this crap, I finally did it! So please test my dzone application, because I do not own an ANDROID phone myself…

Ruby in Java, Java in Ruby, JRuby or Ruby Java Bridge?

Hosting (J)Rails applications on a high availability Java infrastructure with clusters, loadbalancers and all that shit stuff is great, if you already have it in place.

But does running an app on the JRE make it a JRuby application by default? Do you really want to be stuck on JRuby?

I really like the idea of running code with the most appropriate runtime available, that is why I use RVM all the time. JRuby is still very slow on startup and tools like autotest/autospec take minutes for just a handfull of tests…

So I would like to host Rails applications on a Tomcat, but on the other hand I want the tests to be executed with MRI! This should not be a problem as long as you don’t want to share a common codebase within Ruby and Java.

Integration

Is there a best practice for combining Java and Ruby?

Since every project is different, I think that you’ve got to evaluate the possible solutions to pick the one that fits best.

The next sections cover some approaches on integration of Java and Ruby code. Make sure to have RVM installed if you want to execute the provided example code. I assume that a JRE is provided with every OS nowadays…

Java in Ruby

There are two common solutions for embeding Java into a Ruby application. The first and obvious one is via JRuby, which can only be run with the JRuby runtime:

require 'java'

puts "access java.util.UUID via JRuby"
puts java.util.UUID.randomUUID().toString()
rvm use jruby 
=> Using jruby 1.5.0.RC1

jruby lib/jruby.rb 
=> access java.util.UUID via JRuby
=> a16fda6a-c57d-43b9-8376-801e48fe56b3

The same thing is possible using the Ruby Java Bridge from MRI:

require 'rjb'

puts "access java.util.UUID via RJB"
puts Rjb::import('java.util.UUID').randomUUID().toString()
rvm use 1.8.7
=> Using ruby 1.8.7 p249

ruby lib/rjb.rb 
=> access java.util.UUID via RJB
=> 1db8298c-5486-4933-be00-cdb180388e38

But it is also possible to do it the other way around!

Ruby in Java

Evaluating Ruby code in Java is dead simple with help of the JRuby library. You just need to set up a scripting container that executes your scripts:

  @Test
  public void execute_jruby_scriptlet() {
    new ScriptingContainer().runScriptlet("puts 'hello jruby world'");
  }

A more advanced example is to wire a Ruby class as a Spring bean. You need to provide some configuration and a Java interface that can be used as the basis for the bean:


<lang:jruby id="identifier" script-interfaces="de.nofail.Identifier" script-source="classpath:/ruby/identifier.rb">
    <lang:property name="uuid" value="#{ T(java.util.UUID).randomUUID().toString() }" />
</lang:jruby>
# identifier.rb
class Identifier
  def setUuid(uuid)
    @uuid = uuid
  end
  def getUuid()
    @uuid
  end
  def to_s()
    "Identifier[#{@uuid}]"
  end
end

# don't forget to return an instance as a bean
Identifier.new
// Identifier.java
public interface Identifier {
  String getUuid();
}
// SpringJRubyBeanTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext.xml")
public class SpringJRubyBeanTest {

  @Resource(name = "identifier")
  Identifier identifier;

  @Test
  public void generateUuid_success() {
    System.out.println("uuid: " + identifier);
  }
}

The code is currently not running with JRuby 1.5.0.RC1 so you need the latest stable release for testing.

checking Ruby enginges

It is even possible to mix and match all those approches! You just need to keep track of the Ruby engine that is evaluating your code. I created a little helper called which_ruby (available on rubygems) as a sidekick for this article, but more on that in the next week.

Some Ruby sugar in your cup of Java!

taming webapp logging with log4j

Logging is an aspect of programming that should follow some simple rules. If I should describe logging for a dictionary it would be something like: “Providing essential information with object introspection at a decent level of output that enables you to look into a running application or providing runtime information for debugging.”

But even the simplest thing can be complicated if you use Java…

There are different logging frameworks like log4j, commons logging or logback even though Java includes it’s own java.util.logging API. To make it even worse, the Java community came up with a simple logging facade so one can use the logging framework of choice but implement against the facade - WTF?!

a standard that sucks

I would guess that 99% of Java code is written against log4j. Nobody really want’s to switch a logging framework during implementation and most developers I know see log4j as a technical standard.

I won’t recommend using log4j to anyone. The log4j documentation is crap! There is no usefull literature either (I never thought that one would have to buy a book for logging…). The framework misses essential things like pattern matching filters (you will have to use log4j companions) and it is difficult to configure, especially on a tomcat.

Log4j is a bitch when it comes to deployment. One has to be careful where to put the log4j jar(s) and xml or plain text configuration files. If you do it wrong you end up with broken logging behavior; webapps log to the wrong log file, spit out stuff to the system out or stop logging at all.

this is how we do it

Our Java infrastructure is service oriented. We have a bunch of webservices hosted on serveral distributed tomcats and all wars depend on log4j for logging. We want to reload the logging configuration files at runtime (why is jboss able to do it and tomcat is not?!) and manipulate it via JMX.

additional log4j configuration

To achieve this, we have to put some additional configuration into every webapp. Log4j comes with a watchdog that looks for changes in the configuration files. The functionality can be enabled by using the configureAndWatch() method. There is a precanned Spring solution for this, but it has configuration overhead and environmental restrictions. So the best place to implement it ourselves is in a custom context listener:


   [...]
	
	<listener>
		<listener-class>de.nofail.TomcatLoggingListener</listener-class>
	</listener>
   [...]
   [...]
	public void contextInitialized(ServletContextEvent sce) {
		ServletContext servletContext = sce.getServletContext();
		try {
			String log4jFile = String.format("%s-log4j.xml", servletContext.getContextPath());
			String configFilename = new File(getClass().getResource(log4jFile).toURI()).getAbsolutePath();
			DOMConfigurator.configureAndWatch(configFilename, 1000);
		} catch (URISyntaxException e) {
			throw new IllegalStateException("Error resolving log4j configuration file for context=" + servletContext, e);
		}
	}
   [...]

This listener will use a config file named WEBAPP-log4j.xml lying in the root directory. The goal is, that every webapp has it’s own logging context. Every war should include a log4j.jar so that logging won’t be affected by other apps, the classloader hierarchie will ensure this. The different xml configuration files can than be placed in a shared tomcat directory for easy access of an operations team (which is probably yourself).

Using different configuration files has the advantage that you don’t have to mess around with appenders based on packages. That’s how one can configure different log levels for the same packages in each application, very usefull if you release a new application!

Java Management Extension

There are different ways to integrate JMX functionality into a webapp. The simplest approach is to use another servlet listener for propagating an mbean:


   [...]
	
	<listener>
		<listener-class>de.nofail.JMXListener</listener-class>
	</listener>
   [...]
   [...]
	public void contextInitialized(final ServletContextEvent sce) {
		try {
			TomcatLogging mbean = new TomcatLogging();
			ObjectName clutter = new ObjectName("de.nofail:type=TomcatLogging");
			ManagementFactory.getPlatformMBeanServer().registerMBean(mbean, clutter);
		} catch (Exception e) {
			throw new IllegalStateException("Could not create JMX context: " + e.getMessage(), e);
		}
	}
   [...]

If you are using Spring it’s easy to add JMX support via annotations.

Now you can access your running webapp via jconsole:

more information?

You can have a look at a working example based on Maven on github.

Drink a cup of Java™©®, but don’t forget the sugar!

Creating a Maven webapp from scratch

Doing a little research for an article about log4j configuration in Java webapps, I decided to use Maven as a sidekick. I already pointed out earlier that my favourite build tool is buildr. The reason I chose Maven is that it has archetypes and that there is a deprecated guide for using such an archetype to create a blank webapp that would be valuable for me.

installing Maven on OS X

The Maven documentation in general and the installation instructions in particular SUCK. They lack essential information as most Java documentation does. So here is a step by step guide for OS X:

# go to the place you want to install Maven to
cd ~/Library
# download latest Maven version
curl -O http://apache.autinity.de/maven/binaries/apache-maven-2.2.1-bin.zip
# unzip the archive
unzip apache-maven-2.2.1-bin.zip
# add a symlink for convenience
ln -s apache-maven-2.2.1 maven
# add executables to the PATH
echo export PATH="~/Library/maven/bin":\$PATH >> ~/.profile

# open a new bash and check Maven is running
mvn --version
=> Apache Maven 2.2.1 (r801777; 2009-08-06 21:16:01+0200)

creating the webapp

If Maven is running on the system, you can use the archetype to create a blank webapp:

# go to the workspace
cd ~/Documents/workspace/
# let Maven create a webapp
mvn archetype:generate \ 
   -DgroupId=de.nofail \
   -DartifactId=tomcat-logging \
   -Dversion=1.0.0-SNAPSHOT \
   -DarchetypeArtifactId=maven-archetype-webapp

This takes several minutes, as it requires a thousand some broken dependencies for whatever is necessary to create some files and folders! But after that, you have a fresh, apache conform webapp at hand:

# go to the webapp
cd tomcat-logging/
# let Maven create a distributable war
mvn clean package

This is very nice for a Java application! Zero configuration and you get a running webapp that you can start after another two thousand downloads instantly from the command line:

mvn jetty:run &
open http://localhost:8080/tomcat-logging/	

all by myself

There is just one big problem with this so far: it won’t work bejond that! Maven lacks sensible defaults everywhere! Examples? Here you go:

Java compiler

Maven uses Java 1.4 as the default compliance level for the Java compiler. So if you start adding some Annotations or Generics to your code, which are Java 1.5 features, your build will fail until configuring the compiler plugin properly:

	[...]
	<build>
		<plugins>
			[...]
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			[...]
		</plugins>
	</build>
	[...]

This should be a top level configuration!

Jetty plugin

Making changes to the code won’t change anything in the webapp run by the Jetty plugin. You need to configure the plugin in order to pick up changes. Since the plugin can not do any hot code replacement, it has to restart the context after every change. A no-go for most webapps:

	[...]
	<build>
		<plugins>
			[...]
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.10</version>
				<configuration>
					<scanIntervalSeconds>10</scanIntervalSeconds>
				</configuration>
			</plugin>
			[...]
		</plugins>
	</build>
	[...]

Why is this soooo much XML?

Eclipse integration

Maven has support for integrating a project into Eclipse via the Maven-Eclipse-Plugin:

# configure your workspace (do not use ~ to point to your home!)
mvn eclipse:configure-workspace -Declipse.workspace=../
# create Eclipse files
mvn eclipse:eclipse

These tasks add a M2_REPO classpath variable to your Eclipse environment that points to your local Maven repository and creates a .project and .classpath file from the existing pom. Just import the project with Import > General > Existing Projects into Workspace and your done.

better with Eclipse plugins

Since there are mature Eclipse plugins for Maven and Jetty, you should consider installing these from their update sites:

It’s never easy doing stuff from scratch, but Maven should help flatten the rocky path to Java projects. Instead it piles up another Mount Everest of complexity to climb for a Java developer…

additional information

Check out my github profile for a working example project that was created using these steps.

Maven - development for morons made easy!

Buildr – The build system that doesn’t suck

If you are a Java guy like me, you are probably doing a lot of ugly tasks in your everday work. One of these tasks is build management.

The Java community tries to tackle builds with standard tools like Ant and “all-in-one” solutions like Maven. Both are based on huge XML configuration files that are hard to read, painful to maintain and impossible to test. Even though these tools are mainstream, they are quite buggy. Just have a look at all the rants about maven you find on the net.

Java builds are known to become very complex over time. You have to compile things found here, include stuff from there, resolve dependencies in a remote repository, add something to the version control, […even more crazy stuff…]. Addressing such complex and dynamic tasks with static structures is just a stupid idea. What you really want to do is scripting!

scripting builds

Using scripting languages is a natural way to address build tasks. If you are close to the operating system you can do most things easily. Trust your admin, the shell is your friend!

The simplest way to get scripting power is to use bash scripts, which has the drawback that it’s not interoperable and you will always have to show consideration for WINDOW$ users…

There are portable frameworks that try to integrate the flexibilty of scripting languages like Ruby with the power of Ant or Maven. Have a look at Gradle, GMaven, Sbt, Raven, Gant or Antwrap as examples.
About one year ago I stumbled over another build tool that claims the slogan The build system that doesn’t suck which I found quite promising!

dynamic builds with Buildr

Buildr is an expressive Ruby DSL for managing builds based on Rake and Ant. Defining a Java project that follows the default Apache directory structure is dead simple:

# buildfile.rb
desc 'define a project called simple'
define 'simple' do
  info 'create a simple.jar from this project'
  package :jar
end

After installing the Buildr Gem you can call built-in or custom Buildr tasks on your project. This is done in the same way Rake would do it:

# install the Buildr gem
gem install buildr

# check buildr version
buildr -V
=> Buildr 1.3.5 (JRuby 1.4.0)

# build your Java project: compile, test, package
buildr package

Since Buildr is based on sensible defaults, it knows where to look for your class files, resources and tests. Before creating the jar, it compiles everything, executes the tests and then zips up the bytecode into a distributable.

Buildr does not support every build feature by default, but it’s easy to extend. Buildr at its core is just a bunch of tasks, chained in a predefined order. You can easily write your own tasks and plug them into the build to fit your needs. Buildr provides method hooks that allow you to integrate your tasks into the build cycle.

If this small example makes you say “Awesome!”, you should have a look at the best documentation of an open source framework I have ever seen. There are some sophisticated examples of how to use Buildr hosted on github as well.

Build, don’t goof up XML!