Essentials at Poundland in Colwyn Bay!

Saturday, 4 December 2010

0 comments
This has nothing to with Android, or anything techie but I thouoght it was a quite funny.. 

My sister took this photo this back in our home town of Colwyn Bay in Poundland shop. Apparently 2 pregnancy kits were a pound - Now that's value for money!

HttpClient and ConnectionPoolTimeoutException

Monday, 15 November 2010

1 comments
I've recently had a bit of trouble with my application's DefaultHttpClient instance throwing a ConnectionPoolTimeoutException quite consistently after a number of requests to the same location. (See bottom of the entry for a stacktrace).

There doesn't seem to be anything regarding this particular stacktrace in any of the Android developer forums up to now but coincidently Axis2 framework users (Also using Apache HttpClient) reported the same exception occuring after 3 requests to the same location, which is exactly what I experienced.

Here was my instance creation code for the HttpClient:

HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

// Where ClientConfig.P_DEFAULT_CONN_TIMEOUT = 15 seconds
HttpConnectionParams.setConnectionTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);
ConnManagerParams.setTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);

httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry), params);

If you're using TheradSafeClientConnManager be aware that there is a "Max connections per route" property available which is pretty well hidden, and again isn't mentioned in any of the example code I came across. Setting this to a higher value got rid of my issue.

...
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() {
    @Override
    public int getMaxForRoute(HttpRoute httproute)
    {
        return 10;
    }
});
...

The stacktrace:
fetch() sending failed to url http://192.168.0.45/blah
org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:175)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:325)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
    at chesspresso.client.android.net.HttpCall.fetch(HttpCall.java:114)
    at chesspresso.client.android.net.HttpCall.fetch(HttpCall.java:134)
    at chesspresso.client.android.net.HttpCall.post(HttpCall.java:107)
    at chesspresso.client.android.net.ServerCallGoogle.loginGoogle(ServerCallGoogle.java:30)
    at chesspresso.client.android.activity.support.ActivityProcessesGoogle$LoginGoogleTask.doInBackground(ActivityProcessesGoogle.java:72)
    at chesspresso.client.android.activity.support.ActivityProcessesGoogle$LoginGoogleTask.doInBackground(ActivityProcessesGoogle.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
    at java.lang.Thread.run(Thread.java:1096)

Apache HttpClient is obviously used quite a lot by many apps yet it's configurable parameters haven't been explained in android examples as well as they should be I would say.

Samsung Galaxy Tab - Bit of a Gimmick

Tuesday, 2 November 2010

6 comments
I don't normally purchase cutting edge technology on their day of release, but this time around the Galaxy Tab caught my attention. Over the last few days I followed internet reviews, opinions and videos of the release of this thing and after a while I convinced myself that I needed to buy one. I definitely needed a Froyo based device of some sorts as I've been using a 1.5 device for a long time as my main phone and that was the only piece of hardware I had for development. For development a decent handset is essential as of course you need to check your work on the real thing every now and again and the latest release emulators can be painfully slow especially in debug mode, so I went to the Carphone Warehouse yesterday on the day of release and purchased one for 499 GBP.

Probably the most expensive gadget I will ever buy, but the best price I could find - A 1GB data only 1-month rolling contract with TalkTalk (and a free month) that I can cancel any time - which I probably will in the next few days. This for 499GBP.

After 24 hours with this thing now I'm a bit surprised at the large number of positive reviews this device has received... Its main flaw is that it doesn't really fill in a space that needs to be filled! It's an oversize mobile phone that simply can't replace your laptop or netbook for any real purpose.

I use Gmail and Google Reader a lot for example, and I was thinking this would be a great device just to read my mail and browse my feeds. Replying to email with the on-screen keyboard is annoying and the mobile gmail client is no where near as good as what you'd receive on your laptop browser. The same with Google Reader. So many features that aren't available that you just end up using your laptop/netbook.

I also thought this thing would be great for Skype. No it's not. Again down to the actual Skype application for Android because it doesn't seem to support video calling at the moment and again there are far too many features that are missing from what you could be installing on your PC. Again, another reason to ditch the tablet and pick up your laptop instead.

Of course this thing won't replace your mobile phone either because it is far too big to carry around in your pocket. I was thinking of taking it to the gym this morning and to try a particular excercise / rep application and maybe to listen to some podcasts, but really having this thing AND my mobile is just silly. It works as a mobile of course and supports Bluetooth etc. but it's far too big to bring up to your ear as a mobile phone.

At a price of usually 530 GBP it is incredibly expensive for a bit of a gimmick really. I guarantee that more often than not it won't allow you to do what you want as well as your current laptop and mobile phone. You'll also look like a bit of an idiot if someone phones you on it.

And another little criticism before I go! I have a spot in the house from which I use my laptop quite often and I usually get 2 bars on my Windows 7 status bar icon. The Tab can't find my access point from the same spot! I didn't notice any review as yet which also commented on the quality of the wifi but in my opinion it's definitely not as good as my laptop wifi interface.

Sorry, but I'm not a convinced with this one. A bad impulse purchase!

GAE and Log4j - Getting them to work a bit better together

Sunday, 3 October 2010

3 comments
The Problem
App Engine supports Log4j, and you'll be able to see your log4j statements come through either as a stdout or stderr message. The trouble that I've had is that if you want to make full use of the nice log highlighting GAE supports in its console then all stdout / stderr messages will come through as a warning.

A good portion of Java frameworks use Log4j as their logging framework. I'm using Apache Wicket as my front-end framework for example, and when user has hit upon a bug on a page, I'd like to know about it as an error and not just a warning.

A Solution
Here's a Log4j Appender which I've written that creates JUL log statements based on original Log4j log events. A Log4j -> JUL bridge if you like, passing on the original severity level to JUL. It's pretty basic, but it works for me!

Here's the code for the Appender itself:
/**
 * 
 * @author Eurig Jones
 */
public class GAELogAppender extends AppenderSkeleton
{
    private static final Logger L = Logger.getLogger("log4j");

    @Override
    protected void append(LoggingEvent event)
    {
        StringBuilder b = new StringBuilder();
        Level level = event.getLevel();
        String s[] = event.getThrowableStrRep();

        b.append(event.getMessage().toString());

        if (s != null)
            for (String line : s)
                b.append(line).append('\n');

        if (level.equals(Level.FATAL))
            FATAL(b.toString());
        if (level.equals(Level.ERROR))
           ERROR(b.toString());
        if (level.equals(Level.WARN))
           WARN(b.toString());
        if (level.equals(Level.INFO))
           INFO(b.toString());
        if (level.equals(Level.DEBUG))
           DEBUG(b.toString());
        if (level.equals(Level.TRACE))
           TRACE(b.toString());
    }

    private void FATAL(String msg)
    {
        L.severe(msg);
    }

    private void ERROR(String msg)
    {
        L.severe(msg);
    }

    private void WARN(String msg)
    {
        L.warning(msg);
    }

    private void INFO(String msg)
    {
        L.info(msg);
    }

    private void DEBUG(String msg)
    {
        L.fine(msg);
    }

    private void TRACE(String msg)
    {
        L.finest(msg);
    }

    @Override
    public boolean requiresLayout()
    {
        return false;
    }

    @Override
    public void close()
    {
    }
}
Now all we need to do is setup the log4j.properties and logging.properties configurations correctly to make it work. Here is a snippet of my log4j.properties:
#log4j.appender.A1=org.apache.log4j.ConsoleAppender
#log4j.appender.A1.layout=org.apache.log4j.PatternLayout
#log4j.appender.A1.layout.ConversionPattern=%d ...
#log4j.appender.A1=org.apache.log4j.jul.JULAppender

log4j.appender.A1=chesspresso.server.log.GAELogAppender

log4j.logger=ERROR, A1

...
log4j.logger.org.apache.wicket=WARN, A1
...
Above shows that I've replaced the original ConsoleAppender - the default appender which GAE uses, with the new GAELogAppender. This allowing all Log4j statements to go through this instead of the console.

Now the GAE logging.properties file...
.level = INFO
chesspresso.server.log.GAELogAppender=FINEST
...
As you can see, I've added the GAELogAppender here to allow all severities to be filtered through. This means that anything that hits our new appender will reach the GAE logging system, as long as our log4j.properties will allow it to filter through.

I'm still a bit unsure of how exactly GAE Maps JUL severities in it's frontend. In JUL you have FINEST, FINER, INFO, WARNING, SEVERE but the front-end seems to display these differently. It has an ERROR and CRITICAL as well as a WARNING. SEVERE seems to be flagged as an ERROR, but how can you flag something as CRITICAL? Maybe it's in some documentation I've probably scanned through :-)

This is a quick implementation of this Appender for me and so far it works, but I'd love to hear some feedback about what it doesn't do (or doesn't do properly) as I've not used it in anger.

AppEngine, JRebel and Eclipse - Getting them to work together

Wednesday, 29 September 2010

6 comments
I recently started using JRebel for development, but initially I had a bit of trouble getting it to gel with the App Engine / Eclipse setup. After an email or two with the guys at Zero Turnaround I finally got it to work, and it's well worth the effort. Here is a guide for what you need to do...

  1. Install JRebel, the latest version for your platform.

  2. Get into Eclipse and install the JRebel Eclipse Plugin using the "Install New Software..." link under the Help menu, and add the JRebel Update site...

    http://www.zeroturnaround.com/update-site

    I specified the "JRebel Eclipse Debugger Integration" and "JRebel Eclipse Integration only" components.

  3. Specified the jrebel.jar in Eclipse / JRebel preferences. (Mine was in my C:\Program Files\ZeroTurnaround\JRebel\jrebel.jar folder.

  4. The installation Wizard provided with JRebel provides you a guide to get it working in Eclipse. Make sure you go through those steps. (...adding org.zeroturnaround.* etc in Eclipse preferences)

  5. Modified the dev_appserver.cmd, which on my PC sat in

    C:\dev\eclipse\eclipse-SDK-3.6-win32\plugins\com.google.appengine.eclipse.sdkbundle.1.3.7_1.3.7.v201008311427\appengine-java-sdk-1.3.7\bin\dev_appserver.cmd

    Here is it's contents:

    @java -cp "%~dp0\..\lib\appengine-tools-api.jar" ^
        com.google.appengine.tools.KickStart ^
    --jvm_flag=-javaagent:%REBEL_HOME%\jrebel.jar --jvm_flag=-noverify ^
           com.google.appengine.tools.development.DevAppServerMain %*
    


  6. Now you need to add this to the VM Arguments for your Run configuration for your App Engine application:
    -javaagent:/opt/jrebel/jrebel.jar -noverify
    Again, make sure this points to your jrebel.jar location.

  7. Once you've modified the VM Arguments in the app run config then you should see the JRebel text appear in the console.

  8. By the way, you don't need to execute your application in Debug mode to get JRebel to work. If you modify a file in Debug mode you'll still get the "Hot Code Replace Failed" message.

  9. To test I simply booted up the app, and added a method to a class and called it - You'll see a message in the console saying that JRebel is reloading the class.

Now enjoy a considerably quicker method of developing / deploying App Engine apps. $59 bucks is well worth it!

I'm hoping the team at Zero Turnaround turn their attention to Android's Dalvik VM next. JRebel would be of HUGE benefit to developing Android apps and I'm sure with the amount of Android developers out there at the moment it would be a big money spinner for them too.

Wicket and App Engine - How to avoid loading Wicket on startup

Thursday, 23 September 2010

1 comments
A GAE app of mine (www.chesspresso.net) which is a backend to an Android app that most requests come via other code rather than through Wicket. Wicket is my chosen framework which I use to display the front-end of the application (the website!). And most of the requests to the application does not require wicket.

As I'm sure many GAE users know, the startup time is a big problem especially for low traffic apps, and having to load a framework such as Wicket on startup is damaging to the request time for an App.

To avoid having to start the WicketFilter every time the app starts I have extended the WicketFilter to only initialize when the first Wicket page is hit:

public class RequestWicketFilter extends WicketFilter
{
   private static boolean  requestMade = false;
   private static boolean  initialized = false;
   private static FilterConfig fConf;

   @Override
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
   {
      if (!requestMade)
         requestMade = true;

         init(fConf);
         super.doFilter(req, res, chain);
   }

   @Override
   public void init(FilterConfig fC) throws ServletException
   {
      if (fConf == null)
         fConf = fC;

      if (requestMade && !initialized)
      {
         super.init(fConf);
         initialized = true;
      }
   }
}

Eclipse freezing / crashing on start-up - How to get going again.

Monday, 3 May 2010

1 comments
I've been suffering from freezes starting up Eclipse for quite a while now. It happens every few days for reasons I'm not sure of and it's incredibly annoying! My Eclipse Galileo installation has a number of plug-ins on top of it at the moment. Android Development Kit and the App engine plug-in are two of them, but I use lots more but I don't think its to do with any one in particular. Here is how I usually get going again...

  1. Go to the folder of your workspace and rename the project you were working on to something else, if you're not sure what project is that might be causing problems, rename them all or just move them to somewhere else temporarily!
  2. Start-up eclipse and it should start-up this time.
  3. Rename or move back all the folders to what they were and open them in your eclipse.
  4. Clean your workspace.
  5. Un-check "build-automatically" under "Project"
  6. Re-start eclipse.
  7. Check back "build automatically"
Working?

If you're having trouble renaming your project folder because some program has a lock on it, I would suggest downloading a neat little utility called Unlocker which just adds an option to your context menu for a file or folder.