|
| 27-06-09 / 18:45 : Navigon MobileNavigator France (cjed) | Une version France de Navigon MobileNavigator est disponible sur l'AppStore. La taille est réduite à 340 Mo (au lieu de 1,65 Go) et le prix est de 49,99 euros jusqu'au 30 juin - 69,99 euros après). Pour rappel la version Europe (inclut la Grande-Bretagne et l'Irlande) est proposé 74,99 euros jusqu'au 30 juin (pratique pour des pays comme la Grèce où les panneaux utilisent un autre alphabet, et le coût de l'achat de cartes est davantage amorti si on voyage souvent). Il n'est pas précisé si une MAJ vers la version Europe sera proposée, et le degré de précision pour les autres pays que la France n'est pas indiqué (on atteint à priori les 1,65 Go avec seulement 5 pays de la taille de la France - or la version Europe inclut plus de 30 pays). | Commenter | 27-06-09 / 16:39 : MJ Style : 1996-2009 (cjed) | Parmi les morceaux composés en 1996 on trouve MJ Style, inspiré des fameux pas de dance et rythmes de MJ.
Il n'y a donc plus aucune chance qu'il puisse l'écouter.
J'ai également réarrangé la plupart de ses musiques dans les années 90, en utilisant le JV880, et plus tard le XV. | Commenter | 19-06-09 / 00:55 : Google AppEngine : limitations / solutions (cjed) | Voici quelques limitations à considérer pour le déploiement sur AppEngine, qui sont pour la plupart dues aux contraintes de réplication ou de garantie des performances. On peut accéder à une liste de compatibilité des différents frameworks J2EE et à une liste des APIs Java supportées.
Limitation à 1000 fichiers
Une application est limitée à 1000 fichiers. Pour Cappuccino il faut donc utiliser l'outil Press (avec option flatten - à tester avec la version 0.71 car posait problème dans la 0.70 beta) ou supprimer les fichiers .j (ne conserver que les fichiers .sj). Pour la démo de CP2JavaWS les fichiers images des composants non utilisés on été également supprimés (les performances devraient cependant être meilleures avec l'utilisation de Press).
Puisque la notion de machine physique n'existe plus il n'est pas possible d'écrire dans des fichiers. On peut uniquement lire des fichiers, qui doivent se trouver dans le WEB-INF ou être accessibles via le classloader.
Limitation des requêtes à 1000 résultats / limitation de l'offset
Pour des raisons de performances les requêtes ne peuvent retourner plus de 1000 résultats. De plus l'offset ne peut dépasser la position 1000 (0 lignes sont alors retournées), ce qui interdit de parcourir les éléments d'une table de milliers d'éléments via un limit(offset, count). On peut ajouter un critère sur l'index dans la requête, afin de récupérer les éléments en plusieurs fois (palliers de 1000), cependant cela n'est possible que si le tri est effectué sur l'index (cette solution ne fonctionne pas si on trie sur une autre colonne). Il en va de même pour une combinaison de select sur les index et de select where index in (plage d'index) limit count (la première requête étant limitée). Même problème si on passe par une table de tri temporaire (le résultat du select utilisé pour l'insert est limité), de plus cette solution oblige à recalculer le contenu de la table temporaire si la colonne de tri ou les critères de sélection additionnels changent.
Une solution est de définir une clé spéciale (voir section Python Queries on Keys, _key_), gérée en mémoire et sans limite de lecture (la même section pour Java/JDO ne précise cependant pas ces informations). Mais il faudrait pouvoir modifier dynamiquement cette clé précisée (dépend du critère de tri), ou définir pour chaque colonne de tri possible une colonne additionnelle (remplies à chaque insert), concaténation de la valeur de la colonne de tri et de l'index. On pourrait alors ajouter à la requête un critère _key_>valeur limite précédente (valeur de la colonne composite du dernier élément lu lors de la dernière requête batch pour 1000 éléments triés). Un critère sur la clé primaire ne fonctionne en effet pas si on trie sur une autre colonne, du fait que le critère s'applique avant le tri (problème contourné si la clé est composite et comprend la valeur de la colonne de tri choisie).
On peut finalement considérer que les critères de recherches doivent être affinés si une requête renvoie (plus de) 1000 résultats.
Limitation du mapping / synchronisation de caches
Hibernate n'est pas supporté, du fait qu'il instancie de manière statique un générateur d'UUID basé sur l'inetAddress (non supportée dans AppEngine comme toutes les instructions liées à la machine physique : threads, etc.) Une version modifiée d'une classe Hibernate est ainsi fournie dans CP2JavaWS (se base sur du code du framework JUG).
La démo de CP2JavaWS utilise une base HSQLDB en mémoire pour simplifier l'insallation (pas de serveur de base de données à créer), et la table et données initiales sont créées au démarrage du contexte (via un context listener). Les valeurs de la 3ème colonne (age) sont générées aléatoirement, afin de permettre le test de tri sur les 1000 enregistrements. C'est pourquoi ces données peuvent varier selon le moment d'accès (les valeurs dépendent de l'instance de l'application atteinte puisqu'elles sont en mémoire), ce qui n'est pas gênant pour cet exemple (pas de persistance).
On pourrait configurer une url vers un serveur de base de données, mais cela nécessiterait l'hébergement de ce serveur hors d'AppEngine. Et enfin l'utilisation d'un fichier local pour persister les données, même dans WEB-INF, n'est pas possible (lecture seule).
Mais surtout il faut considérer la problématique de synchronisation mémoire entre les noeuds (instances) de l'application, du fait que les couches de mapping utilisent deux caches d'objets en mémoire (synchronisation à deux niveaux). On trouve ainsi un cache de niveau 1 par persistanceManager/MappingSession (typiquement pour une session utilisateur) pour pouvoir comparer un objet de travail modifié avec l'objet original lu (fieldLocking), et un cache de niveau 2 par persistanceManagerFactory/SessionFactory pour pouvoir comparer les originaux des persistanceManagers avec les objets courants du cache central (nécessaire pour l'optimistic locking. L'accès direct - backdoor - à la base sans passer par la persistanceManagerFactory - qui est le plus souvent centralisée/récuprée via JNDI - est évidemment interdit afin de garantir l'intégrité).
Le datastore de GAE est basé sur le framework de mapping DataNucleus (implémente JDO et JPA). Par défaut le cache de niveau 2 est désactivé dans DataNucleus, mais en l'activant (paramétrage) on peut choisir son implémentation parmi les frameworks suivants : EHCache, Oracle Coherence, memcached, etc. Dans cette liste seuls Oracle Coherence et memcached permettent un fonctionnement dans un environnement distribué (réplication des caches de niveau 2 sur les différents noeuds du cloud) - également le cas pour les versions plus récentes de EHCache. Grâce à l'architecture de plugins de DataNucleus il est possible de développer une extension pour un autre framework de cache gérant le mode distribué : JBoss cache, OSCache, Terracotta, etc.
Le datastore Google utilise une implémentation propriétaire de l'interface JCache (JSR107) pour permettre la distribution du datastore, et offre une prise en compte automatique de cette réplication. A la base DataNucleus propose une API manuelle pour la réplication des datastores (par exemple le JDOReplicationManager pour synchroniser des PersistanceManagerFactory de différentes machines). L'AppEngine SDK permet aussi via les APIs Memcache de gérer (manuellement) la réplication d'objets particuliers (hors caches du datastore) si nécessaire.
Pour remplacer DataNucleus par Hibernate (peut fonctionner avec des caches distribués comme JBossCache, OSCache, Coherence et les versions plus récentes d'EHCache) dans une application GAE il faudrait pouvoir intervenir au niveau du processus de réplication (synchroniser les HibernateSessionFactory). La configuration (statique) de ces caches distribués nécessite de connaître le host des différents noeuds, information non accessible dans GAE.
Finalement on est obligé d'utiliser le datastore Google, avec les contraintes suivantes (ne viennent pas de limitations de Datanucleus) : pas de requêtes de type aggrégation, pas de requêtes polymorphiques, filtres limités, join limités, relations many-to-many limitées, etc.
BigTable n'étant pas relationnel (contrainte du cloud), l'intérêt de JDO est que cette spécification n'est pas restreinte à un datastore de type base de données relationnelle (contrairement à JPA). DataNucleus gère différents types de datastore, et une extension (plugin) pour BigTable a du être développée par Google (notamment pour gérer l'accès depuis l'interface JPA). Bien que le datastore de GAE soit d'un niveau d'abstraction plus élevé que BigTable, certaines limitations semblent directement liées à ce choix d'implémentation, le but étant de garantir un temps de réponse court quelle que soit la requête (d'où les restrictions).
Pas de support des webservices SOAP
Cela n'est à priori pas gênant puisque les solutions RDA actuelles (GWT et Cappuccino/CP2JavaWS) se basent sur du JSON (enrichi propriétaire).
Communication inter-applications
Pour communiquer avec une autre application il est nécessaire de passer par les APIs URL Fetch du SDK AppEngine.
Outils et intégration à WTP
Le plugin Eclipse permet de créer un projet web (avec le fichier de configuration propre à AppEngine pour la webapp, et les jars requis - doivent cependant être ajoutés manuellement au classpath), mais n'offre pas l'intégration avec WTP (ni le moyen d'arrêter le serveur de test AppEngine une fois lancé - il faut passer par le bouton de WTP). On peut déployer un projet AppEngine depuis un projet WTP si on renomme le WebContent en war, et si on place le fichier appengine-web.xml dans le WEB-INF du projet WTP. Cependant on perd alors la phase d'enrichissement (enhancement) requise pour les implémentations JPA et JDO du datastore (il est probable qu'on puisse simplement ajouter le builder associé dans le fichier .project).
La contrainte de la phase d'enhancement réduit cependant l'intérêt de la solution (d'autant plus si on utilise GWT qui possède également une contrainte de génération). Des solutions JDO comme LIDO proposaient de se passer d'enhancement si besoin (mais performances évidemment moindres dans ce mode dynamique). | Commenter | 16-06-09 / 23:41 : MAJ Java pour Leopard (cjed) | Une mise à jour (update 4) de Java 6, 5 et 1.4.2 est disponible pour Leopard (Java 6 ne supporte que les mac Intel). Les versions à jour sont alors 1.6.0_13, 1.5.0_19, et 1.4.2_21. | Commenter | 14-06-09 / 13:19 : Cappuccino 0.71 et démo des contrôles (cjed) | Une RC1 de Cappuccino 0.71 est disponible. Elle apporte les améliorations suivantes et il est possible de voir une démo en ligne de l'ensemble des contrôles. On note notamment le nouveau type Segmented Control. | Commenter | 13-06-09 / 01:33 : CP2JavaWS 0.72 : corrections/support AppEngine (cjed) | Une nouvelle version de CP2JavaWS est disponible sur sourceforge :
Note : now uses json2lib stringify and parse methods from latest Cappuccino main branch (and future 0.71 version). Then it does not work for version 0.7 (or you should replace these methods manually by these from CPValue).
These two new methods should lead to general better performance.
- Modified server-side demo HabilitationServiceImpl to return true for the
genericDAOService methods.
- CP2JavaWSEndpoint init had a bug with testing presence of sameDomain
argument : replaced if(aSameDomain) with if (aSameDomain!=nil).
- CP2JavaWSTableViewDelegate : in sendSynchRequest, added the test for
sameDomain (was ok for sendAsynchRequest) to use JSONP mode if not same
domain.
- Modified hibernate config .hbm file to use assigned generator for the id, as AppEngine does not provides the InetAddress class.
However Hibernate's SessionFactoryImpl still owns a static field of type UUIDHexGenerator that is always initialized, and that extends AbstractUUIDGenerator, whose uses InetAddress in its static init part.
Then had to redefine AbstractUUIDGenerator (included in same original package name in the demo project's src folder) : when deploying to AppEngine we have to comment the line that uses InetAddress and uncomment the line that uses a random generated address (based on JUG project, also licenced under LGPL).
A working demo is now available on AppEngine (same code as the included webapp example except the endpoint's url and use of the random generated address in the redefined AbstractUUIDGenerator class) :
http://cp2javaws.appspot.com
(tested on Safari 4 and Firefox 3.0.x. Is ways faster on Safari, however performance should be improved with upcoming Firefox 3.5 release). | Commenter | 08-06-09 / 23:02 : Snow Leopard pour septembre / Safari 4 (cjed) | Apple a dévoilé les premiers gains de performance attendus par Snow Leopard : en moyenne 50% de performance en plus (temps de lancement des applications, Finder, preview, wake up et shutdown, Time machine), du simple fait des optimisations (réécriture en Cocoa et utilisation de Grand Central et du 64 bits). De la même manière QuickTimeX est jusqu'à 2,8 fois plus rapide. Enfin on note une amélioration de la navigation dans Exposé et les stacks, et une meilleure gestion de l'éjection des médias lorsque des fichiers y sont ouverts. La taille de l'installation passe à 6 Go (environ la moitié de celle Leopard).
La surprise est son prix, seulement 29$ la mise à jour depuis Leopard. La sortie est prévue en septembre.
la version finale de Safari 4 est téléchargeable ici, pour mac et PC. Sur Windows elle utilise à présent le look natif de Vista. Les performances (html et javascript) sont présentées comme 4 fois meilleures qu'avec les dernières beta de Firefox 3.5. | Commenter | 08-06-09 / 22:37 : iPhone 3G S / iPhone OS 3.0 / MacBookPro 13' (cjed) | Comme supposé, Apple a présenté un nouvel iPhone, le 3G S, jusqu'à 2 fois plus rapide et équippé d'un nouveau processeur 3D gérant la version 2.0 d'OpenGL ES. Il possède également un capteur 3 mpixels (avec autofocus), supporte l'enregistrement vidéo (30 fps en VGA) et l'édition vidéo sur l'iPhone, et apporte une boussole et les commandes vocales. L'autonomie est améliorée et le prix est de 199$ (modèle 16 Go). L'ancien modèle 3G 8Go passe à 99$.
L'OS 3.0 pour iPhone est annoncé pour le 17 juin.
Enfin un nouveau MacBook Pro 13' a été présenté, à un prix similaire à l'ancien MacBook (même carte graphique 9400M). | Commenter | 08-06-09 / 02:25 : CP2JavaWS 0.71 : service DAO générique/CPTableView (cjed) | Une nouvelle version de CP2JavaWS est disponible sur sourceforge :
Note : now uses json2lib stringify and parse methods from latest Cappuccino main branch (and future 0.71 version). Then it does not work for version 0.7 (or you should replace these methods manually by these from CPValue).
These two new methods should lead to general better performance.
- fixed a cache problem : now if an asynchronous request was pending before a cache fault, its return is ignored (as the state isn't the same as originally expected after a cache fault).
- the sorting code now works properly (as soon as headers and CPSortDescriptors are added to CPTableView). It can still be tested by modifying the init value for currentSortDescriptorsStr in CP2JavaWSTableViewDelegate (see commented code). The reference is now the position in the table, and limit(first, length) requests are used.
- added a new generic service, GenericMasterDetailDAOService, that manages retrieving of elements for any CP class, using Hibernate. It then avoids having to define a DAO service (the previous mode is still available, for custom management or non-database datastores).
To use the new mode, pass the table elements CP class name when creating the CP2JavaWSTableViewDelegate, instead size and read method names (that are then generic). | Commenter | 07-06-09 / 00:17 : Précisions techniques sur Google Wave (cjed) | Pour compléter les premières impressions sur Google Wave, voici quelques informations et avis plus techniques :
Les technologies clés à la base de Google Wave sont les suivantes (voir le reste de l'article The Secret Sauce Behind Google Wave) :
- GWT Ajax library, which not only powers complex interactions on a browser, but also provides a reasonably tuned rendering for small form-factor mobile devices, such as Android and iPhone
- XMPP protocol that provides a foundation for the Wave Federation Protocol
- the real-time keystroke-by-keystroke communication pioneered several years ago in Google Suggest, and now in production in high-scalability deployment the AppEngine cloud computing platform on which are hosted the Robot extensions to Wave
- the Big Table data persistence mechanism that powers Google’s implementation of a Wave server (something which is not required by the spec, but which facilitates developer productivity and production scalability)
On y trouve également une présentation intéressante de la théorie "operational transformation theory (OT)".
Les 3 protocoles et 2 APIs derrière Google Wave (voir l'article complet, Wave Protocol Thoughts) sont :
- Federation (XMPP)
- The robot protocol (JSONRPC)
- The gadget API (OpenSocial)
- The wave embed API (Javascript)
- The client-server protocol (As defined by GWT)
On peut également lire des informations intéressantes dans les commentaires :
"Actually, the Gadget spec on the Wave docs site specifically notes that it does not support the OpenSocial APIs. They have their own API that mirrors some of the OpenSocial functions."
"Waves are containers for Wavelets. Wavelets are containers for Blips. Blips have content that are XML. So we have XML tunneled over JSON tunneled over HTTP POST"
Mais on lit aussi "Waves are XML and can be served over XMPP."
"My understanding is that XMPP is for federation of servers, not for
robots."
"XMPP is much better than HTTP for client initiated interactions,
particularly for ones behind a NAT"
" I don't really understand why they don't base all three of their protocols on XMPP... I suppose you would need something like HTML5 WebSockets to make this work cleanly with a browser-based client."
" I would love there to be a standard API (much like DOM) for browsers to adopt that manages XMPP communications as a parallel to XHR. Leave HTTP for what it is good at, and do persistent connections another way."
"do you know if you have to use GWT to use parts of Wave?"
"No, it is not required at all.
On peut donc utiliser Cappuccino comme client, et il apparaît que les WebSockets de HTML5 pourraient être la solution pour unifier les différents protocoles. | Commenter | 06-06-09 / 00:00 : Google Wave / OpenDoc / Cappuccino&CP2JavaWS (cjed) | Lors du Google I/O, Google a annoncé Google Wave, une solution technique de type sociale, permettant l'échange d'informations en provenance de divers canaux (REST JSON, JSONP, etc.) et domaines, et leur agrégation pour former une application composite (à la manière d'un bureau métier). Il y a deux jours on découvrait l'application Almost.at, assez similaire, réalisée en Cappuccino (référencée un peu plus tard sur Ajaxian). Récemment je pointais un ancien article de Greg Maletic à propos d' Opendoc d'Apple (technologie abandonnée il y a 10 ans).
Cette semaine plusieurs blog comparent Google Wave à OpenDoc :
Exploring Google Wave as a Social-Enabled OpenDoc : a modern re-imagination of Apple’s abandoned OpenDoc component software technology that has been social-enabled and lives in “the cloud... Waves, the software components that allow a Wave document to contain supplemental datatypes, are called gadgets, rather than parts. Examples of gadgets can include a YouTube player, a chess or sudoku game, a photo album fed by mRSS, and even a Google Maps object.
Google Wave: OpenDoc Redux : The overall concept often seems very similar to that of OpenDoc, back from 1992, and in the days when Microsoft was happy to work with Apple. No Gears, but impressive HTML 5...
What Intrigues Me About Google Wave : My initial thought was was, “Hey, somebody finally got Apple’s OpenDoc to work.”
Twitter - Tweetie : google wave is really just IM + opendoc. anybody else remember opendoc? i think i'm the only one.
Personnellement j'ai conçu les endpoints de CP2JavaWS avec un delegate propre pour l'authentification (d'où les modifications nécessaires apportées à la classe CPURLConnection), afin de permettre l'assemblage de services distants (et provenant d'applications et domaines distincts) en une application composite (container à la manière d'un bureau métier), principe qui peut rappeler également la technologie Portlets. Le choix de JSONP est automatique dans CP2JavaWS si le domaine de la webapp distribuant un composant/service est différent de celui du fichier index.html de l'application cliente CP. Evidemment j'avais à l'idée les concepts d'OpenDoc et ai commencé à prendre des notes il y a quelques mois. | Commenter | 03-06-09 / 01:17 : Almost.at : reader de news avec Cappuccino (cjed) | Un an après la surprise de l'application 280Slides, on peut découvrir une nouvelle application impressionnate basée sur Cappuccino : Almost.at. Il s'agit d'un lecteur de canaux de news (Twitter, youtube), avec une interface à la iTunes (graphique de type equalizer pour choisir la date des événements à afficher, boutons pause/play pour stopper le rafraîchissement automatique - requêtes asynchrones JSONP). De plus une implémentation des sheets est proposée (simple fenêtre dont la frame est animée via CPPropertyAnimation).
Encore une fois l'intérêt réside dans la manière dont l'application est réalisée : concepts objects avancés (dynamic bindings via IB et bientôt Atlas, chaîne de délégation - vrai système de messages, programmation le plus souvent via delegates au lieu d'héritage), fonctionnalités évoluées proposées par l'implémentation de Cocoa de Cappuccino (drag&drop, undo/redo, moteur quartz avec composition et core animation, apportant notamment la transparence et ombrage automatique des widgets, etc.), code à écrire très réduit, très propre et réutilisable. Incomparable donc aux applications Flash, même l'impressionnant, très puissant et très pratique Pixlr. | Commenter | 02-06-09 / 03:25 : CP2JavaWS 0.7 : remote tables browsing (cjed) | Une nouvelle version de CP2JavaWS est disponible sur sourceforge :
- New CP2JavaWSTableViewDelegate component, that manages retrieving of rows objects values automatically : triggers requests to the server through CP2JavaWS bridge classes when needed. It allows fast browsing of large table selection results without stressing the application server nor database server, and without requiring any pagination !
No GWT component, JSF or other provides that feature yet : they all use pagination (data splitted into multiple pages), that is less practical, less intuitive and slower to reach the desired element (if you have hundreds of elements you can’t have all pages number displayed, so you have to use many times forward/fast forward buttons).
Requests are sent ahead asynchronously when we reach near cache's end, so the application user interface remains responsive.
The requested rows count (next or previous cache size) adapts automatically to the current visible rows (that depends from the enclosing scrollview size - could be resized then).
Use of fast scroll using the scrollbar or scroll area is allowed (generates a cache fault and then a synchronous - that time only - call to reset all caches from the next requested position).
Ready for column sorting (infos are passed to the remote service's read method) once the datasource delegate method is managed in CPTableView.
Can pass selection criteria (SQL, HQL, or any other WHERE clause part string) to the remote service's read method if selection must be restricted (pass null to browse the whole table).
Use (see included example) :
- create the CPTableView and columns as usual but pass the corresponding attribute of the remote collection's elements class as the column id (you can pass any nested property using EL type path, as CPPropertyUtils is used here).
- create the table datasource (and set it as the tableView datasource) passing the endPoint, remote Java service interface name, read method and get size (whole table size) method names, index/primary key attribute name, additional criterias string :
tableViewDelegate = [CP2JavaWSTableViewDelegate createForEndPoint:endPoint1 javaServiceInterface:@"com.cp2javaws.demo.services.IDemoService2" readMethod:@"readCustomersForIndexCriteriaAndCountIsForward" sizeMethod:@"customersCount" idAttName:@"customerId" criterias:nil];
The read method on the server must follow this signature :
(Integer indexCriteriaValue, Integer count, Boolean isForward, String criterias, List sortDescriptors).
Fixes :
- fixed a problem with CP2JavaWSURLConnection's instance authDelegate scope, that lead to the application not working if using index.html (uses Press and then all global vars appear in the same file - same scope) instead of index-debug.html.
- fixed a problem when encoding/decoding null attributes values (if using custom CPCoding implementation and not checking for null attributes - ok when relying on automatic mode). These fields are now ignored (not included in JSON string).
- now follows correct rules when checking for sameDomain setting at endPoint creation (allows use of a local file for the client CP application if the server is local and Safari is used).
- Added preliminary support for synchronous calls (do not manage digest authentication yet). Then asynchronous mode remains the default (should also be preferred as it allows more responsive user interface). | Commenter |
|