vendredi 29 janvier 2010

Soirée Java EE 6 à l'Alpes JUG

Les inscriptions pour la soirée Java EE 6 à l'Alpes JUG avec Antonio Goncalves (Java champion, auteur du livre Beginning Java EE 6 Platform With GlassFish 3 ...) sont ouvertes!
Si vous êtes de la région grenobloise, vous ne pouvez pas rater cette soirée d'exception!
Les détails sur l'évènement sont disponibles ici, et pour les inscriptions, c'est par !

jeudi 28 janvier 2010

Compte rendu du coding dojo Play! framework à l'Alpes JUG

L'Alpes JUG organisait hier en collaboration avec le CARA un coding dojo sur le thème de Play! framework. Play! est un framework de développement agile permettant de créer des applications web avec un minimum de code et un minimum d'efforts.
Guillaume Bort, le leader technique du projet nous a montré comment réaliser une application de gestion de contacts (équivalente à l'application Wicket zencontact de Zenika) à partir d'une maquette html/css statique. En développant l'application il nous a présenté les concepts du framework, de la partie IHM à l'accès à la base de données.

dimanche 24 janvier 2010

Nouveau tutoriel sur NeoDatis

Philippe de K33G.org nous propose aujourd'hui un tutoriel sur la base de données objet NeoDatis, aussi bien pour Java que C#.
Ce tuto en plus d'être très détaillé permet de comparer les manière de mettre en oeuvre cette base NoSQL dans les 2 langages.

Bonne lecture et bon dimanche!
Lire l'article

jeudi 21 janvier 2010

Hibernate Search : intégration à une application existante (partie 2)

Partie 2 : Intégration d'Hibernate search dans une application existante.

Dans la partie précédente, nous avons vu les concepts d'Hibernate search et de Lucene.

Aujourd'hui nous allons voir comment intégrer Hibernate Search dans une application existante, que nous allons générer à l'aide du CRUD Generator de NetBeans 6.8. Pour mémoire, ce billet explique comment générer une application web avec cet outil.

Pour des raisons de compatibilité entre JPA et Hibernate search, nous allons cette fois générer une appli web JEE 5. La version d'Hibernate search que nous ajouterons au projet NetBeans est la version 3.1.1GA.
Cette application sera basée sur les technologies JSF et JPA.

Tout d'abord, on définit nos entités JPA, Proprietaire et Appartement :

@Entity
@Indexed
public class Appartement implements Serializable {

@Id
@DocumentId
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@ManyToOne
@IndexedEmbedded
private Proprietaire proprietaire;

@Field(index=Index.TOKENIZED)
private String adresse;

//getters & setters
...
}


@Entity
public class Proprietaire implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Field(index=Index.TOKENIZED)
private String firstName;

@Field(index=Index.TOKENIZED)
private String lastName;

//getters & setters
...
}


Vous remarquerez que j'ai ajouté des annotations spécifiques à Hibernate search sur ces entités.
@DocumentId permet de dire au framework que nous allons indexer les objets de type Appartement dans Lucene.
@Field(index=Index.TOKENIZED) signifie que les champs en question seront ajoutés à l'index.

Même si ce sont les appartements qui nous intéressent dans le cadre de nos recherches, nous voulons indexer certaines informations du propriétaire. C'est pourquoi la classe liée Proprietaire (ce lien étant exprimé pour Hibernate search par l'annotation @IndexEmbedded) contient elle aussi des champs pourvus de l'annotation @Field.

Une fois notre application web générée à partir de nos entités, nous pouvons ajouter notre code spécifique qui nous permettra d'effectuer des recherches "full text" sur les appartements de notre agence.

Ajoutons la méthode suivante à la classe AppartementJPAController :

public List<Appartement> filterAppartements(String filter) {
EntityManager em = getEntityManager();
try {
//Définition des champs de recherche
String[] fields = new String[]{"adresse", "proprietaire.lastName"};
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
org.apache.lucene.search.Query query = null;
try {
query = parser.parse(filter);
} catch (ParseException ex) {
Logger.getLogger(AppartementJpaController.class.getName()).log(Level.SEVERE, null, ex);
}
//création du fullTextEntityManager
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(query, Appartement.class).setCriteriaQuery(null);
//récupération des résultats
return persistenceQuery.getResultList();
} finally {
em.close();
}
}


Cette méthode permet de lancer une recherche sur les appartements à partir d'un filtre de recherche. Un objet "fullTextEntityManager" est créé à partir de l'entity manager JPA.
La recherche sera effectuée sur les champs représentant l'adresse de l'appartement ainsi que le nom et prénom de son propriétaire.
Pour reprendre l'exemple de l'article précédent, le mot clé "Victor" renverra aussi bien les appartements de la rue Victor Hugo que les appartements dont le propriétaire s'appele Victor.

Modifions maintenant notre controlleur JSF pour lui permettre d'appeler cette méthode.
On ajoute à la classe AppartementController une variable "filter" ainsi qu'une méthode pour lancer la recherche :

private String filter;

public String filter() {
if (filter!=null)
appartementItems = jpaController.filterAppartements(getFilter());
pagingInfo.setItemCount(appartementItems.size());
return "appartement_list";
}



Cette méthode permet de recharger la liste des appartements affichés par la jsp pour n'afficher que ceux qui correspondent à notre recherche. L'appel à la méthode pagingInfo.setItemCount() permet d'afficher une valeur correcte pour le nombre d'éléments à afficher au niveau de la pagination (par exemple "items 1 ... 5 of 10").

Enfin, nous allons modifier la JSP appartement/List.jsp pour ajouter le champ de recherche qui appelera la méthode filter() du controller JSF (AppartementController) :




Et voilà nous avons une application fonctionnelle qui nous permet de lancer des recherches avec Lucene.
Dans la prochaine partie nous verrons comment améliorer les résultats de ces recherches avec l'approximation et les synonymes.