Slow initial start-up time in your Java App Engine Application?

Saturday 24 April 2010

2 comments
A lot of developers have been complaining about slow start-up times of their applications in app-engine production recently on the App Engine issues list. 10-20 second start-up times is not uncommon causing long waits for app users and potential errors in some applications. This is made worse by applications that rely on frameworks that do quite a bit on start-up. With app engine your application doesn't get a permanent JVM instance like you would usualy so this means that if there's been no activity for a while the JVM goes cold so your app will have to start-up again on the next request.

The good news for people suffering with this issue (and that is all App Engine developers I would say) is that the GAE team has accepted the issue and introduced it into their roadmap - "Ability to reserve instances to reduce application loading overhead". Personally I really won't mind paying for my own JVM instance if it's not too expensive, and I would guess that this is probably the direction the GAE team will go.

My "quick-fix" (or hack) for this issue at least until the GAE team sorts it out, is to ping your app every few minutes to keep the JVM "warm". Here I've created a blank servlet that gets called by the AE background cron.xml tasks every few minutes...

web.xml:
...
<servlet>
    <display-name>BlankServlet</display-name>
    <servlet-name>BlankServlet</servlet-name>
    <servlet-class>my.package.BlankServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>BlankServlet</servlet-name>
    <url-pattern>/blank.html</url-pattern>
</servlet-mapping>
...

BlankServlet.java:
public class BlankServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    {
        // Nothing needed here.
    }
}

cron.xml:
<?xml version="1.0" encoding="UTF-8"?>

<cronentries>
    <cron>
        <url>/blank.html</url>
        <description>Ping a blank page to keep the JVM warm</description>
        <schedule>every 5 minutes</schedule>
    </cron>
</cronentries>
You could of course ping your main welcome page instead but you might have some code in your pages that you might not want to be executed by an automatic process - maybe your Google Analytics javascript for example.

Wicket - Submitting a form to an anchor position

Tuesday 20 April 2010

2 comments
I had a non-ajax style form on the bottom of a long page. When the form is submitted, the top of the page is displayed, and not the bottom. Annoying for a user if they've submitted a comment to a page for example, and they have to scroll down right to the bottom of the page to see if it's been added. In a standard form in HTML you can just submit the form to an anchor like this...
<form method="post" action="/myPage.html#jumpToHere">
... my form content ...
</form>

<div id="jumpToHere">
... Jump back to here once submitted
</div>
In Wicket you can do this by overriding the onComponentTag() method in your wicket Form...
public class MyForm extends Form<T>
{
   ...

   @Override
   protected void onComponentTag(ComponentTag tag)
   {
       super.onComponentTag(tag);
       StringBuilder b = new StringBuilder(tag.getString("action").toString()).append("#jumpToHere");
       tag.put("action", b.toString());
   }
}

Wicket Locale drop-down selector

Monday 12 April 2010

2 comments
I needed a drop-down in Wicket which allowed the user to select their language to update the app/site content. I also wanted the languages to appear in their own character sets as well. Something that looks like this...



Java and the Locale class can provide us with this quite easily so here is a simple component based on the standard Wicket DropDownChoice component that does the job. You pass it a bunch of Locale objects representing the languages that you want to be supported and it will update the model you give it when it's selected...
/**
 * Wicket Drop-down language / locale selector
 *
 * @author Eurig Jones
 */
public class DropDownLocale extends DropDownChoice<Locale>
{
   public DropDownLocale(String id, IModel<Locale> model, List locales)
   {
       super(id, model, locales);
       setChoiceRenderer(new LocaleChoiceRenderer());
   }
  
   @Override
   protected void onSelectionChanged(Locale newSelection)
   {
       getSession().setLocale(newSelection);
   }

   @Override
   protected boolean wantOnSelectionChangedNotifications()
   {
       return true;
   }

   private class LocaleChoiceRenderer implements IChoiceRenderer<Locale>
   {
       @Override
       public Object getDisplayValue(Locale locale)
       {
           // Change this to just locale.getDisplayLanguage() and it'll display the languages in the currently selected language / Locale and character set.
           return locale.getDisplayLanguage(locale);
       }

       @Override
       public String getIdValue(Locale locale, int i)
       {
           return locale.getLanguage();
       }
   }
}
Some markup...
<select wicket:id="selectLanguage"></select>
Here is some example calling code. We pass our new DropDownLocale component a bunch of Locale objects representing the languages we intend to support. We also pass it a model to update. Here I have chosen to directly modify the session using a PropertyModel so as soon as the drop-down is used, the app is updated with the correct language...
List<Locale> supportedLanguages = new ArrayList<Locale>();
supportedLanguages.add(Locale.ENGLISH);
supportedLanguages.add(Locale.FRENCH);
supportedLanguages.add(Locale.JAPANESE);

PropertyModel<Locale> model = new PropertyModel<Locale>(getSession(), "locale");
DropDownLocale selectLanguage = new DropDownLocale("selectLanguage", model, supportedLanguages);
add(selectLanguage);