Wicket Routes Mount

Wicket

At Code-Troopers, we like to work with the frameworks we love. One of them is Apache Wicket, and it happens to some of us doing some Play! Framework or Ruby on Rails (either for a client project, a side project or giving back OSS love).

One thing really great is this two frameworks is the central route system, one file allows to group all the routes handled by your application. Wicket does not provide such way of grouping routes, you can manually mount routes into your application or annotate your page classes.

Wicket routes mount library

This small library project available on Github allows to group mounts into a central file. To use it, simply add its dependency to your pom.xml (artifact is available on Maven central):

<dependency>
    <groupId>com.code-troopers</groupId>
    <artifactId>wicket-route-mount</artifactId>
    <version>0.1</version>
</dependency>


This dependency will transitively gets wicket-auth-roles (if there is a special need for a version without this dependency, it could be done easily).

Usage

To use it, simply create a routes.conf file at the root of the sources in your project (typically src/main/resources/) respecting the following format :

# mountPoint        class                           roles
/home               codetroopers.HomePage           
/secured            codetroopers.SecuredPage        USER
/user/${mode}/#{id} codetroopers.UserPage           ADMIN,USER

The files content is the following :

  • Mount path : using standard Wicket syntax (${requiredParam} and #{optionalParam} are available)
  • Page class : fully qualified name of the page class to mount
  • Roles (optional) : comma separated list of roles required to access the page

IntelliJ IDEA can do completion for class names in this file (you just need to hit the ctrl+space shortcut twice)

Alfred.app Glassfish workflow

alfred-iconI recently bought the Alfred.app Powerpack. It is byfar the best application launcher / automation engine I’ve ever used. One of the new features of the second version of this application is user customizable workflows.
In my daily activities, I start, stop, restart and kill my Glassfish server several times a day. In order to save me a few keystrokes and a few alt-tabbing, I created this small workflow allowing me to manage my local Glassfish instance.

You can find the Alfred worfklow at the following url http://bit.ly/alfred-glassfish.
You will probably need to adapt the GF_PATH variable in the script to point to the root of your Glassfish installation.

Once this small step is done, you’ll end up with the following prompt in your Alfred :

Alfred with Glassfish workflow enabled

Alfred with Glassfish workflow enabled

Wicket 6 + CDI on Heroku

herokuwicketAs an Apache Wicket user for more than five years I really enjoy its programming model. I recently played with Play Framework 2.1 and Scala and discovered that deploying to Heroku is as easy as a git push. I wondered how difficult it could be using this mechanism to deploy a Wicket application.

Existing attempts

My initial investigation led me to this blog post from Martijn Dashorst explaining how to deploy a Wicket 1.5 application to Heroku, the service has slightly evolved since and the quickstart no longer deploys (Maven repository is no longer available to the run environment).

Adding JPA in the mix

I adapted it to deploy and use Wicket 6 instead of 1.5. And as I am a CDI fan I completed the quickstart with the CDI Wicket module (inspired from this post from Igor Vaynberg) and made the necessary steps to use the heroku bundled PostgreSQL database as a JPA datasource.

The key to make the database works correctly on Heroku resides in the following code snippet, where we parse the provided environment variable to populate hibernate properties.

try {
     URI dbUri = new URI(System.getenv("DATABASE_URL"));
     String username = dbUri.getUserInfo().split(":")[0];
     String password = dbUri.getUserInfo().split(":")[1];
     String dbUrl = "jdbc:postgresql://" + dbUri.getHost() 
                    + ':' + dbUri.getPort() + dbUri.getPath();
     System.setProperty("hibernate.connection.url", dbUrl);
     System.setProperty("hibernate.connection.user", username);
     System.setProperty("hibernate.connection.password", password);
} catch (Exception e) {
     LOGGER.error("Unable to extract database url");
}

Session replication

On Wicket mailing lists, a user recently asked the steps required to get the data store works correctly on Heroku (as the disk space is ephemeral), the key is using a NoSQL backend like Redis. So I wrote a simple and basic implementation of IDataStore using Redis (I think it can be optimized by someone familiar with Redis, pull requests are welcome).

Hands on

The quickstart can be found at the following address and deploys fine on a stack with Redis Cloud and PostgreSQL add ons enabled.
In the end you got :

  • Wicket 6
  • CDI via Weld
  • JPA with PostgreSQL
  • Redis datastore

You can see it live at the following address : http://wicket-6-sample.herokuapp.com/, the app can take a few seconds to start, as Heroku will stop it if it is idling for too long.

Use Wicket templating system to generate Html

html-iconApache Wicket is a great web framework, its clear separation between logic and markup allows to focus on what’s need to be done.

As we use Wicket at SRMvision, we needed to send mails with rather rich templates to our users. The first implementation we used was relying on Wicket to generate these templates using Html. We finally don’t use it (our mailing tasks are done by a background job, thus we don’t have access to our webapp), but I though the code used in our fast proof of concept could help someone else.

import org.apache.wicket.markup.MarkupType;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.request.Response;
import org.apache.wicket.response.StringResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Simple panel allowing to use the templating engine 
 *    provided by Wicket to generate HTML.
 * Typical use would be to generate mail content.
 *
 * User of this class will need to subclass it 
 *    and create a panel as usual. 
 * Then a call to getHtml() will return the generated Html.
 *
 * @author cedric at gatay.fr
 */
public class HtmlTemplaterPanel extends Panel {
    private static final Logger LOGGER = 
        LoggerFactory.getLogger(HtmlTemplaterPanel.class);

    /**
     * Default constructor takes no wicket:id > 
     *   the panel will not be added to any component
     */
    public HtmlTemplaterPanel(){
        super("dummy");
    }

    /**
     * Call this whenever you want to get
     *   the Html for this component
     * @return Html or empty string
     */
    public String getHtml(){
        final Response origResponse = getRequestCycle().getResponse();
        try{
            final StringResponse stringResponse = new StringResponse();
            getRequestCycle().setResponse(stringResponse);
            renderAssociatedMarkup("panel", "");
            return stringResponse.toString();
        }catch(Exception e){
            LOGGER.error("Unable to build HTML for panel : {}",
                         e.getMessage());
        }finally{
            getRequestCycle().setResponse(origResponse);
        }
        return "";
    }

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

    @Override
    public MarkupType getMarkupType() {
        return MarkupType.HTML_MARKUP_TYPE;
    }
}

If you want to generate a template using Apache Wicket, you only need to create a Panel and its associated markup which inherits this simple class. Then, when you want to get the Html for your component, call getHtml().

The only drawback of this is that you need a RequestCycle to generate the markup (you’ll find out why reading the code).

De Free à Numericable

Marre de Free…

Depuis 2003 maintenant je suis client ADSL de Free. Là où j’ai toujours conseillé et trouvé que Free était un des acteurs du marché qui faisait bouger les choses, j’ai depuis changé d’avis.

La Freebox révolution est une belle machine, arrivée bien avant les machines des concurrents mais, comme Free l’avait fait avec la version précédente, le produit livré était bien loin des promesses tenues lors de la conférence de presse. Il aura fallu une bonne année avant que la box soit réellement stabilisée et n’ait plus ces bugs les plus gênants (volume non conservé, paramètres volatiles). En plus de cette technique consistant à considérer le client comme beta testeur, vient maintenant le problème du débit : celui ci n’a pas arrêté pas de se dégrader : la situation était telle que j’en venais à me connecter au VPN de ma société pour réussir un build Maven dans des temps raisonnables (80ko/s qui se transforment en 2Mo/s pour télécharger des dépendances). En supplément je suis abonné Canal Plus et l’accès à Canal Plus à la demande via la Freebox est devenu complètement erratique (problème étrange parce que depuis ma TV l’accès fonctionne bien mieux, Free est sûrement moins à blâmer dans ce cas).

L’élément déclenchant le changement chez moi a été le récent événement concernant les DNS menteurs de la Freebox effectuant un bloquage automatique et non configurable des publicités. Ce sujet a donné lieu à des centaines de commentaires sur Internet, et je me situe du côté de ceux qui ne sont pas opposé à l’intégration de la fonctionnalité, mais pas de cette façon : les utilisateurs lambda auront cette fonctionnalité activé par défaut et n’auront plus la possibilité de découvrir des opportunités grâce à la publicité. Et pour les utilisateurs avancés la non configurabilité du bloquage rend l’initiative complètement inutile.

Ayant la chance d’être desservi par le câble, le choix d’un nouveau fournisseur d’accès a été largement simplifié : Bouygues télécom et son offre BBox sensation ou Numericable. Vu les mauvais retours que j’ai pu avoir sur le boitier de chez Bouygues et le fait que le réseau utilisé est celui de Numericable je me suis tourné vers ce fournisseur.

Passage chez Numericable

J’ai passé ma commande le 7 janvier, le 11 janvier j’ai reçu LaBox en relai colis. Le branchement fait le soir même, rien ne marchait : j’avais le signal correctement synchronisé mais ni TV ni Internet.

Pour informations, la procédure d’inscription via le site http://signup.numericable.fr ne fonctionnait pas (impossible de reconnaitre le matériel).

Le lendemain, j’ai contacté le service client via le chat (très bonne expérience utilisateur ceci dit en passant) qui a fini d’activer ma ligne. Internet fonctionnait comme voulu mais j’avais toujours un problème avec le service TV, LaBox me gratifiait d’un message “droits expirés” dès l’allumage et en allant dans le menu de diagnostic le numéro de carte ne s’affichait même pas. La solution à ce problème était tout simplement de garder LaBox sur une des chaines qui fonctionnait (317 – D17 a fonctionné pour moi) pendant environ une heure. Une heure plus tard, toutes les chaines fonctionnaient comme prévu et la magie a fait que le numéro de carte est désormais visible dans la partie diagnostic de LaBox.

J’ai enfin une connexion fiable et rapide ainsi qu’un service TV de très bonne qualité. La seule fonctionnalité bonus de la Freebox qui va me manquer est le support AirPlay, l’iPad avec Spotify vers l’amplificateur home cinéma via AirPlay est une chose que j’utilise très souvent quand je reçois du monde. Je suis donc à la recherche d’une bonne alternative peu couteuse.