Archive for July, 2007

Convert urls to Hyperlinks with the IvalueConverter

Friday, July 20th, 2007

In my TwitterViewer in WPF I found that status can have urls in the body so they can’t
be bind directly to a TextBlock.
With a Converter I find maybe a good solution : Split the text with a regular expression,
build inline elements (simple Run for
text and Hyperlink for
urls) and put them in the Inlines property of the TextBlock :

<
Label
Margin
="8,0,8,0"
x
:
Name
="status"
Grid
.
Column
="1"
>


      <
Label
.
Content
>





<
Binding
Path
="Text"
Converter
="{StaticResource
urlConverter}"/>


       </
Label
.
Content
>


</
Label
>

And the code of the Converter implementation :

          String[] LinksText = Regex.Split((String)value, @"(\bhttp://[^
]+\b)"); TextBlock txtBlock = newTextBlock();
txtBlock.TextWrapping = System.Windows.TextWrapping.Wrap; foreach (String textSplit in LinksText)
{ if (textSplit.Length > 0) { if (textSplit.Substring(0,
1).Equals("h")) { Hyperlink textFormate
= newHyperlink(newRun(textSplit));
textFormate.NavigateUri = newUri(textSplit);
txtBlock.Inlines.Add(textFormate); } else  {
txtBlock.Inlines.Add(newRun(textSplit));
} } } return txtBlock;




Twitter Viewer

Persistence in J2EE : JPA tutorial and example

Thursday, July 19th, 2007

I’m currently performing a study on J2EE persistence tools and frameworks, and I came accross this great JPA tutorial using implementations by Hibernate and Toplink.

Serge Tahé provides very clear and simple explanations based on easy to run examples, both in Hibernate and Toplink (and with a great variety of databases – I ran most of them with Derby, just because I already had it running on my machine). The tutorial exposes progressive examples going from very basic peristence code to quite advanced mapping configurations, and explores some of the limits of the tools, as well as behavior differences between Hibernate and toplink. It is accessible to a large public : almost from java beginners to expert who do not yet have a deep experience in JPA.

All in french unfortunately for those of you who don’t speak our wonderful language…

how to databind a ListView programmatically and update it with PageFunction

Monday, July 16th, 2007

I’ve read a lot of tutorials about databinding in WPF but often it’s all about XAML.
In my TwitterViewer
application
 in WPF I need to update the TwitterManager class with username
and password of the user. I choose to set the binding in code. Here is the constructor
of the main page :

          public MainPage() { InitializeComponent(); //create
a provider  odp = newObjectDataProvider();
odp.MethodName = "GetStatuses"; odp.ObjectInstance
= newTwitterManager("tewmgd", "xxxx");
odp.IsInitialLoadEnabled = false; Binding myBinding
= newBinding();
myBinding.Source = odp; //set the source of the
ItemsSource  statusList.SetBinding(ListView.ItemsSourceProperty,
myBinding); odp.Refresh(); }

With an  hyperLink the user can navigate to another page to change the settings
(username and password). The PageFunction control
allows the launching page to subscribe to the Return event and since it’s a generic
class, the return object is typesafe :

          void settingsLink_Click(object sender, RoutedEventArgs e)
{ //create a new instance of the settings page SettingsPage pageFunction
= newSettingsPage(); //subscribe
to the return event  pageFunction.Return += newReturnEventHandler<TwitterManager>
(OnSettingsReturned); this.NavigationService.Navigate(pageFunction); }
          public
          void OnSettingsReturned(object sender,ReturnEventArgs<TwitterManager>
e) { //change the source of the provider  odp.ObjectInstance
= e.Result; //refresh the provider and with it the
listview  odp.Refresh(); }


In the target page the button event
handler uses the OnReturn method to navigate backward and set the result object :

          private
          void OnClickDone(object sender, RoutedEventArgs e)
{ OnReturn(newReturnEventArgs<TwitterManager>(
newTwitterManager(this.txtUserName.Text,this.txtPassword.Text)));
}
          Update, screenshoots of the two pages :
        
          
            Twitter Viewer
          
          
            Twitter Viewer (2)
          
        

GWT : enrichir l’émulation JRE

Tuesday, July 10th, 2007

Avant-propos (ou le pourquoi du comment)
La sérialisation GWT répond à une règle stricte : seules quelques classes issues de la Java Runtime Environment sont supportées, et malheur à quiconque s’en écarte. De manière cohérente, certaines classes de base sont supportées. Par contre, rien n’assure que les classes dérivées le soient.
C’est justement ce comportement, au demeurant fort logique, qui est la cause de nombreuses SerializationException lors de l’envoi de date du serveur vers le client.
En effet, il est fort probable que le moteur de persistance, peu au fait des subtilités de sérialisation Javascript, aie tôt fait de remplacer votre instance de java.util.Date par une dérivation SQL (java.sql.Date ou java.sql.Timestamp) plus proche de son modèle relationnel.
Généralement, le contournement préconisé revient à créer un objet Date standard à partir de sa variation SQL afin de ne pas heurter môssieur GWT ;). Sauf que… la classe Timestamp est plus précise que la classe Date, et donc que cette conversion peut poser quelques problèmes de synchronisation au retour sur le serveur. Je pense notamment aux malheureux qui ont basé la gestion de version sur un champ Timestamp et qui se retrouvent bien embêtés avec leur valeur de retour tronquée…
Ce problème ayant été relevé par un utilisateur de ma librairie hibernate4gwt, j’ai décidé de m’attaquer au problème.

Portage du timestamp : premier essai
Dans ma grande naïveté (je suis parfois d’un optimisme béat), j’ai cru qu’en définissant une classe d’émulation classique _ comprenez implémentant (Is)Serializable _ le tour serait joué.
Hélas, trois fois hélas, la sérialisation JavaScript semble assez mal s’accommoder de l’héritage nécessaire entre Timestamp et Date. J’ai d’ailleurs ouvert une fiche de bug (n°1164) concernant ce problème… sans réponse à ce jour '(

Portage du timestamp : seconde tentative
Etant d’un naturel têtu, j’ai parcouru les sources de GWT à la recherche du mécanisme permettant la sérialisation de l’objet java.util.Date.
En fait, un objet émulé nécessite deux classes :

  • Une classe d’émulation JSNI, situé dans le dossier ‘com/google/gwt/emul/<package-emulé>’ ou un de vos répertoires propre en suivant la même nomenclature
  • Un serialiseur dédié, portant le même nom que la classe, agrémenté de « _CustomFieldSerializer ».

L’écriture de la classe d’émulation JSNI s’est avéré relativement simple, en m’appuyant sur l’existant Date, seul le champ « nanoseconds » devant être ajouté.

Le sérialiseur quand à lui répond à un certain nombre de règles plus ou moins tacites (il n’existe pas d’interface à implémenter) :

  • Il doit être situé soit au même niveau que la classe concernée, soit dans le package ‘com.google.gwt.user.client.rpc.core.<package.émulé>’
  • Il doit implémenter les méthodes « serialize » et « deserialize », celles-ci prenant en charge le type associé.
  • Si la classe associée n’a pas de constructeur vide, l’interface doit prendre en charge la construction de l’instance par le biais de la méthode « instantiate »
  • Bien entendu, les appels à la sérialisation et à la désérialisation doivent s’effectuer dans le même ordre, sous peine de mauvaise surprise
public final class Timestamp_CustomFieldSerializer
{
  public static void deserialize(SerializationStreamReader streamReader,
			         Timestamp instance)
                                 throws SerializationException
  {
    // no fields
  }

  public static Timestamp instantiate(SerializationStreamReader streamReader)
                                      throws SerializationException
  {
    Timestamp instance =  new Timestamp(streamReader.readLong());
    instance.setNanos(streamReader.readInt());

    return instance;
  }

  public static void serialize(SerializationStreamWriter streamWriter,
	                       Timestamp instance)
                               throws SerializationException
  {
    streamWriter.writeLong(instance.getTime());
    streamWriter.writeInt(instance.getNanos());
  }
}

Notez bien que les méthodes utilisent et renvoie des objets de type Timestamp et non de simples objets, ce qui explique qu’il n’y ait pas d’interface générique à implémenter.
Et ça marche !

Dernière remarque : concernant le portage en Javascript d’une classe existante, c’est cette dernière qui est utilisée en Hosted Mode, et qu’il faut déployer l’application GWT en mode Web pour voir s’exécuter le code JSNI et valider son fonctionnement.

Les limites du “miracle GWT”

Sunday, July 8th, 2007

GWT au pays des Bisounours
Sentez-vous ce parfum d’euphorie un brin béat qui traverse le web à la seule évocation de GWT, cette propension à parer de qualités la librairie de Google parfois au mépris de toute objectivité ? Ressentez-vous à la lecture des différents articles de présentation l’ombre de ce doute face à cette librairie, dont on vous promet monts et merveille sans contrepartie ? Parfaite intégration avec l’existant, productivité multipliée par 5, la fin des migraines Javascript ? Se peut-il vraiment que tout soit aussi parfait ?
Non, bien sûr que non…
J’avoue ne pas être d’un nature très « groupie », et donc que les superlatifs provoque en moi au mieux un haussement de sourcil interrogateur, et bien plus souvent un réaction de méfiance face au merveilleux que l’on me promet.
Soyons clairs : je pense, je suis persuadé que GWT est une bonne librairie, un très bon outil. Pas moins. Pas plus non plus. En effet, elle résout nombre de problématiques liées aux développements Ajax et Web 2.0.
De là à dire qu’elle ne souffre d’aucun défaut, il y a un pas que je me refuse à franchir. Explication en détail…

Le syndrome de la librairie magique
Comme toute nouvelle librairie, les avantages de GWT ont tendance à en cacher les limites. Souvenez-vous du précédent « Hibernate » : l’accès aux bases de données devenait tellement plus simple que l’on a cru, à tort, que la gestion de la persistance se ferait sans mal, et mieux, sans avoir besoin de comprendre les mécanismes sous-jacents tels que transactions, jointures et accès concurrents.
On assiste ici au même phénomène : la création d’application Ajax est rendu tellement plus abordable avec GWT que l’analyse s’en arrête aux bienfaits sans en mesurer les coûts et les pièges. Ne vous faites pas d’illusion : une connaissance, même partielle, de Javascript et des mécanismes associés reste nécessaire pour éviter toute déconvenue.
A mon avis, GWT, tout comme Hibernate ou Java en son temps, résout 80% des problèmes, mais crée 20% de problématiques nouvelles et complètement inédites qu’il serait malhonnête d’ignorer ou de passer sous silence.

Le mythe de l’intégration avec l’existant
L’un des arguments les moins recevable pour le modeste auteur d’hibernate4gwt que je suis est de dire que GWT fonctionne sans peine avec les applications existantes.
C’est bien entendu parfaitement faux avec toute application Spring-Hibernate (pour rester sur des technos éprouvées).
Le simple fait que GWT ne supporte que la syntaxe Java 1.4 pour la partie JavaScript de l’application interdit d’utiliser annotations et collections typées, pourtant largement répandues dans nos applications. Il en découle l’impossibilité pure et simple d’utiliser les entités du Domaine dans la partie cliente d’une application GWT.
Face à ce problème, la communauté se contente pour l’instant de pis-aller. La plus répandue consiste à convertir les entités du modèle en DTO (data transfer objects) par l’entremise de Dozer, ce qui implique l’apprentissage d’une nouvelle librairie et l’écriture des fichiers de mapping idoines. Avouez que pour une intégration naturelle, on peut repasser…

Et encore, je vous fais grâce des problématiques propres à la coexistence des entités Hibernate avec GWT -/. Pour plus d’info sur ce sujet, je vous renvoie au site web d’hibernate4gwt, où j’ai posté un article sur le sujet…

Une documentation anémique
A la différence d’Hibernate ou de Spring, deux poids lourds de l’Open-Source cités plus haut, GWT ne bénéficie que d’une documentation, disons, sommaire. Quelques pages web couvrant les cas standard, mais rien concernant de manière exhaustive le fonctionnement de la librairie.
C’est d’autant plus gênant que cette librairie contient de nombreux concepts innovants qu’il conviendrait de mieux documenter (je pense notamment aux Serializer et aux Generators) afin d’en encourager l’adoption, l’usage et l’enrichissement.
Heureusement, quelques passionnés, tel Robert Hanson, ont pris le taureau par les cornes et entrepris un large travail de vulgarisation que ce soit sur leur site web (dont Timepedia est sans doute l’un des meilleurs exemples) ou par le biais de livres (le célèbre et pour l’instant relativement unique « GWT in action »), mais cela peut difficilement avoir la valeur d’un manuel de référence estampillé « officiel », nécessaire à l’adoption par le plus grand nombre.

Dans la jungle des widgets
Les composants graphiques GWT affichent une situation paradoxale : le framework en lui-même en propose relativement peu (cf. Kitchen Sink, la démo “officielle” GWT), et les librairies de composants tierces (Open-Source ou non) sont pléthores.
Pourtant, autant on peut faire confiance au caractère professionnel des widgets natifs GWT, autant on est en droit de s’interroger concernant les autres composants : quelle est leur fiabilité ? Leur pérennité ? Gèrent-ils convenablement l’arbre DOM ?
Bref, des interrogations que l’on ne peut évacuer d’un simple haussement d’épaule et qui demanderait une évaluation minutieuse, ou l’émergence d’un standard de fait, ce qui ne semble pas encore le cas.

Programmation graphique : un pas en avant, un pas en arrière ?
Avec sa programmation entièrement en Java et événementielle, GWT nous renvoie un peu à l’ère de Swing, avec ses avantages et ses inconvénients.
Au rayon des premiers, la programmation graphique retrouve enfin son unité, face aux innombrables lnagages nécessaires à une page JSF-Ajax (HTML, JSP, JSTL, Javascript,…)
Concernant les défauts, on notera la fin de la séparation entre design et programmation, tel qu’il avait été introduit justement avec les JSP/JSF.
Plus important, GWT n’est pas structurant en terme de programmation. Il n’existe pas à ce jour de framework standardisant la programmation d’une action, ou les règles de navigation, à la manière d’un Struts en son temps…
Du coup, chaque développeur a l’embarras du choix pour coder le comportement de son application, et au vue du forum officiel, nombreux sont ceux qui sont embarrassés par ce choix p. De plus, les projets y perdent en homogénéité, et donc le retour d’expérience sur telle ou telle pratique sont plus lents.

Conclusion
Ces manques, ces défauts, ne doivent pas vous faire perdre de vue mon propos premier : GWT est un très bon outil, sans doute le meilleur disponible concernant le développement d’application Ajax.
Mais au milieu de toute cette vague d’enthousiasme parfois sans recul, il me semblait important de ramener GWT à un juste statut : celui d’une librairie, utile et productive certes, mais dont l’adoption ne se fera pas sans impact…