Archive

Posts Tagged ‘wicket’

Wicket: fournir des données JSON via Ajax

septembre 3, 2010 1 commentaire

[Article also available in English]

Il y a quelques semaines, nous devions retourner des données sous forme JSON suite à des appels JavaScript. N’étant pas familier avec la chose, nous étions partis sur une page ne retournant qu’un contenu JSON. Quelque chose comme ça:

 @Override
    protected void onRender(final MarkupStream markupStream)
    {
        try
        {
            OutputStream outputStream = getResponse().getOutputStream();
            outputStream.write(jsonData.getBytes());
            outputStream.flush();
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }

    }

L’url de cette page était fournie au code JavaScript via cet appel:

 
RequestCycle.get().urlFor(jsonPage);

Bien évidemment, l’appel et la gestion de cette page étaient encapsulés, histoire de ne pas polluer chaque utilisateur avec ces subtilités.
Toutefois, bien que fonctionnelle, cette solution n’est pas parfaite. En effet, cette page supplémentaire implique un contexte différente où les infos doivent être amenées. Rester au sein même du composant/contexte pourrait être plus plus sympa (c’est certes toujours possible, mais bien moins propre et requérant plus de travail). Cette solution est également plutôt verbeuse.

Le bon côté de la chose est que cette page, avec peu de contenu, prend également peu de place une fois sérialisée, ce qui arrive souvent avec Wicket. Je vous l’disais, rien n’est parfait 😉

Cependant, plus récemment, je cherchais une façon de coordonner un Behavior Ajax Wicket avec une fonction jQuery, les deux se déclenchant sur le même événement JavaScript. En chemin, j’ai trouvé cette « astuce » de Richard Wilkinson dans une conversation nommée Wicket, Ajax and JSON. Et devinez quoi: c’est tout simple de faire interagir du JavaScript et un Behavior via des données JSON (ou quelque contenu de votre choix).
Voici le code de Richard:

 
    AbstractAjaxBehavior behaviour = new AbstractAjaxBehavior()
        {
            private static final long serialVersionUID = 1L;

            @SuppressWarnings("unchecked")
            public void onRequest()
            {
                //get parameters
                final RequestCycle requestCycle = RequestCycle.get();

                final PageParameters pageParameters = new PageParameters(requestCycle.getRequest().getParameterMap());
               
                //do something using nice json library to produce a string of json
                String json = .......
               
               
                requestCycle.setRequestTarget(new StringRequestTarget("application/json", "utf-8", json));
            }

        };
        add(behaviour);

Pour accéder à l’url de ce Behavior, il suffit de procéder ainsi:

 behaviour.getCallbackUrl(true)

Ma première implémentation tourne nickel, même si je ne suis pas sûr de toutes les implications du booléen fourni pour obtenir l’url, dont la JavaDoc est:
* @param onlyTargetActivePage
* if true the callback to this behavior will be ignore if the page is not the last
* one the user accessed

Quoiqu’il en soit, au final, l’essentiel est dans la facilité avec laquelle tout cela est faisable. Finies la page et les lignes de code supplémentaires, ainsi que de passer des infos à travers tout ce petit monde. Ce Behavior résout tout cela joliment.

Bien sûr, l’intégration de JavaScript avec le côté serveur est toujours un travail conséquent, mais au moins Wicket fournit vraiment des outils efficaces pour cela !

🙂

++
joseph

PS: dans sa réponse, Richard parle également de l’intégration de jQuery dans Wicket, via le projet anciennement nommé wiQuery et récemment intégré dans wicketstuff-core en tant que « jquery » project. Quelqu’un l’a t il déjà utilisé ? Des retours d’expérience ?
PS2: Plus d’info sur Richard sur son blog Out for a duck, all about Wicket, sans nouvelle entrée depuis quelque temps malheureusement.

Publicités
Étiquettes : , , ,

Wicket: providing JSON content through Ajax

septembre 2, 2010 5 commentaires

[Article également disponible en Français.]

A few weeks ago, we had a need to give back some JSON content to some client side JavaScript. Not knowing exactly how to do that, we went for a page rendering itself with only the JSON content. Something like that:

 @Override
    protected void onRender(final MarkupStream markupStream)
    {
        try
        {
            OutputStream outputStream = getResponse().getOutputStream();
            outputStream.write(jsonData.getBytes());
            outputStream.flush();
        }
        catch (IOException e)
        {
            throw new RuntimeException(e);
        }

    }

Then, the url for this page was provided to the page through

 
RequestCycle.get().urlFor(jsonPage);

For sure, the call to this page was done through some component encapsulating the whole business.
Yet, while working, this solution had drawbacks. The biggest one, IMHO, being that the extra page means a different context, where the info have to be pushed. It would be nice to be able to stay in the component/context (which is still doable, I agree, but less clean and more work). It’s also quite verbose. On the good side on the picture, this page being filled with less content is then small on the disk when about to be serialized way and forth. You can’t have the cake and eat it 😉

Recently, I was looking for a way to deal with a Wicket Ajax behavior and some jQuery function both acting on the same JavaScript event. And on the way, I found this answer from Richard Wilkinson on a topic named Wicket, Ajax and JSON. And guess what, it’s dead simple to interact between JavaScript and a behavior through JSON data (or whatever content you prefer).
Here is the code from Richard:

 
    AbstractAjaxBehavior behaviour = new AbstractAjaxBehavior()
        {
            private static final long serialVersionUID = 1L;

            @SuppressWarnings("unchecked")
            public void onRequest()
            {
                //get parameters
                final RequestCycle requestCycle = RequestCycle.get();

                final PageParameters pageParameters = new PageParameters(requestCycle.getRequest().getParameterMap());
               
                //do something using nice json library to produce a string of json
                String json = .......
               
               
                requestCycle.setRequestTarget(new StringRequestTarget("application/json", "utf-8", json));
            }

        };
        add(behaviour);

Then, to get at the behavior, one just has to provide the JavaScript with the outcome of

 behaviour.getCallbackUrl(true)

The basic implementation I did and used work all fine, yet I’m not sure yet of all the implications of the boolean provided, whose javadoc is:
* @param onlyTargetActivePage
* if true the callback to this behavior will be ignore if the page is not the last
* one the user accessed

Anyway, in the end, what matters is how easy it is to do ! No more extra page, extra lines and information being passed around. This simple behavior does it all nicely !

Yes, integrating JavaScript and server side is still some work, but damn Wicket provides really first level tools for this!

🙂

++
joseph

PS: Richard speaks as well of JQuery integration for Wicket, formerly wiquery and now integrated into wicketstuff-core as the jquery project. Did anyone ever try it ? Any feedback ?
PS2: More about Richard on his blog Out for a duck, all about Wicket (no new entry since a while though).

Étiquettes : , , ,

Small Wicket tips

juillet 23, 2010 Laisser un commentaire

[Cet article est également disponible en français.]
In the last weeks, I’ve been doing quite some Wicket work.

Here are some small tips gathered on the way 🙂

  • If you use an AjaxButton, don’t forget to override onError and to add a feedback panel to the target! Indeed, an AjaxButton triggers form validation. And if this fails, then feedback messages should have been created on the way. Having them displayed is kind of handy ;).
  • Know and use Component.setRenderBodyOnly(boolean renderTag).This little method allows to skip the component tag when rendering. Doesn’t sound crazy like that, but comes handy when one has an optional fieldset.
  • FormComponent.updateModel() is only effective if the new model object isn’t equal to the previous one.Indeed, FormComponent.updateModel() calls Component.setDefaultModelObject(), when checks for non equality before setting the new object. Why ? It saves making an extra page version if no change was done. Yet, if your equals isn’t appropriate, this may result in changes not being done for no visible reason. To avoid this, override Component.getModelComparator() and provide an appropriate comparator, like one testing only for same reference equality.

Hopefully it may help someone 🙂

++
joseph

Étiquettes : , ,

Petites astuces Wicket

juillet 23, 2010 Laisser un commentaire

[This article is also available in English.]
Ces dernières semaines, j’ai pas mal utilisé Wicket.

Voici quelques petites astuces rencontrées en chemin 🙂

  • Si vous utilisez un AjaxButton, surchargez onError et ajoutez un FeedbackPanel à ce qui sera réaffiché! En effet, un AjaxButton déclenche la validation du formulaire auquel il est rattaché. Et si cette validation échoue, il est fort probable que des FeedbackMessage soient créés en chemin. Il serait dommage de ne pas les afficher ;).
  • Connaissez et utilisez Component.setRenderBodyOnly(boolean renderTag).Cette petit méthode permet de ne pas afficher le tag html auquel le composant est attaché, tout en affichant son contenu. Ca peut paraitre anodin, mais cela s’avère bien pratique lorsqu’on veut afficher de façon optionnel le fieldset entourant un composant.
  • FormComponent.updateModel() n’est effectif que si le nouvel objet rattaché au modèle n’est pas égal au précédent.En effet, FormComponent.updateModel() appelle Component.setDefaultModelObject() avec le nouvel objet. setDefaultModelObject vérifie alors que le nouvel objet ne soit pas égal au précédent. Il fait cela afin d’éviter de créer une version non nécessaire de la page (qui sera ensuite gardée dans la PageMap). Ceci dit, si votre equals() n’est pas approprié, cela peut amener certains changements à ne pas être pris en compte (sans raison évidente). Pour éviter cela, il suffit de surcharger Component.getModelComparator() et de fournir un comparateur correspondant. Par exemple un comparateur ne vérifiant que l’égalité des références.

J’espère que cela pourra aider !

++
joseph

Étiquettes : , ,

Wicket et ses fonctionnalités de templating

juin 19, 2010 1 commentaire

[This note is also available in English.]

Wicket fournit des fonctionnalités de templating. Rien de bien folichon, mais c’est tout de même bien pratique, surtout quand il faut intégrer du JavaScript.

Ces fonctionnalités sont cependant très peu discutées voir même, je suspecte, globalement inconnues. Aussi, creusons un peu la chose!

Comme tout système de templating, tout tourne autour de texte contenant des variables, définies par ${variable} et dont les valeurs sont données via Java.

Voyons un exemple simple, un fichier de template nommé javascript.tpl:

alert('${variable}');

Wicket permet d’aisément accéder à ces templates en tant que ressources mises dans des packages Java, via la classe PackagedTextTemplate:

public PackagedTextTemplate(final Class clazz, final String fileName)

Par exemple:

PackagedTextTemplate jsTemplate = new PackagedTextTemplate(this.getClass(), "javascript.tpl");

Ainsi, le template se trouve à côté de la classe Java et de l’html l’utilisant, rendant le tout aisé d’utilisation.

Les variables sont fournies au moyen d’une simple Map:

Map parameters = new HashMap();
parameters.put("variable","test working");

Au final ce template trônera certainement au milieu d’html. Aussi Wicket fournit plusieurs options pour cela:

  • contribution au header html:
    add(TextTemplateHeaderContributor.forJavaScript(jsTemplate, new  Model((Serializable) parameters)));
  • accolé à des éléments du body html:
    Java:

    Label myScript = new Label("myScript", new JavaScriptTemplate(jsTemplate).asString(parameters));
    myScript.setEscapeModelStrings(false);
    add(myScript);

    Html :

    <wicket:container wicket:id="myScript"></wicket:container>

Vous avez sans doute remarqué que, dans chacun des cas, je ne fournis pas le tag qui devrait entourer le tout. Pas d’inquiétude à avoir, Wicket le fait pour vous.
L’html résultant est en effet:

<script type="text/javascript"><!--/*--><![CDATA[/*><!--*/
alert('test working');
/*-->]]>*/</script>

Si le template contenait plutôt du CSS, il faut juste utiliser un CssTemplate au lieu du JavaScriptTemplate.

Quelques info supplémentaires sont disponibles sur le wiki wicket: Including CSS resources.

++
joseph

Étiquettes : , , , ,

(Petite) Astuce wicket : ne pas caster sa classe Application

Salut

Fréquemment, il m’arrive du voir du code wicket tel que

((MyApplication)Application.get()).myApplicationSpecificMethod();

Perso, cela me pique toujours un peu les yeux. Or, il y a tout simple, à savoir définir dans MyApplication quelque chose comme:

public static MyApplication getWebApplication() {
return (MyApplication) Application.get();
}

on peut alors écrire :

MyApplication.getMyApplication().myApplicationSpecificMethod();

Cela peut s’applique également à la Session, pour sûr.

voilà, trois fois rien, clairement, mais un pas de plus vers un code propre. Ca en vaut donc la peine (et ça m’évitera de me répéter sur le forum wicket développez.com, even better ;)).

++
joseph

Étiquettes : , ,

Playing with Wicket’s templates

janvier 28, 2010 3 commentaires

[Ce billet est également disponible en français.]

Wicket comes with some templating facilities. Nothing fancy, but still they’re quite handy, especially when integrating JavaScript components.

These functionalities aren’t much advertised and I would say even quite unknown. So, let’s dig in !

Basically, this templating is about some text containing variables, for example ${variable}, whose values are provided through Java code.

Let’s take a simple example, a template file named javascript.tpl containing :

alert('${variable}');

Wicket is nice enough to provide an easy to access the templates as package resources, through the PackagedTextTemplate class :

public PackagedTextTemplate(final Class clazz, final String fileName)

For example :

PackagedTextTemplate jsTemplate = new PackagedTextTemplate(this.getClass(), "javascript.tpl");

Thus the template can be next to the .html page and the Java class using it, making the whole quite cohesive.

Providing the variables is done through a simple Map :

Map parameters = new HashMap();
parameters.put("variable","test working");

And then, you most probably want to include this template in some html. Wicket provides you different options :

  • as an header contribution :
    add(TextTemplateHeaderContributor.forJavaScript(jsTemplate, new  Model((Serializable) parameters)));
  • directly next to some element in the html file:
    Java side :

    Label myScript = new Label("myScript", new JavaScriptTemplate(jsTemplate).asString(parameters));
    myScript.setEscapeModelStrings(false);
    add(myScript);

    Html side :

    <wicket:container wicket:id="myScript"></wicket:container>

You may have noticed that, in both cases, I didn’t provided the surrounding script tag (and the appropriate inner wrapping). Fear not, Wicket does it for you !
Indeed, the rendered html is :

<script type="text/javascript"><!--/*--><![CDATA[/*><!--*/
alert('test working');
/*-->]]>*/</script>

If the template was about some CSS stuff, one would just need to wrap it using a CssTemplate instead of the JavaScriptTemplate.

A bit more info are available there Including CSS resources.

++
joseph

Étiquettes : , , , ,
%d blogueurs aiment cette page :