Ellipse Tutorial

Comment utiliser le service d'indexation

AccueilNotre catalogue de formationsNos partenairesDemande de devisEllipse FrameworkJWT (Javascript Widget Toolkit)License d'exploitation de nos logicielsVos développements sur mesuresTutorial sur le langage CSSTutorial sur le langage XMLTutorial sur le langage JavaTutorial sur le langage Visual Basic 6.0Historique de la sociétéNous contacterA propos de ce site
 

ATTENTION : Tutorial en cours d'écriture ! N'hésitez pas à nous signaler toute erreur ou suggestion.

Accès rapide :
   Moteur de base de données utilisées
   Activation du moteur d'indexation
   Ajout d'un scanner pour un nouveau type de fichier
   Implémenter une page de recherche

Le framework Ellipse intègre un moteur d'indexation afin de permettre des recherches parmi les documents de votre application Web. Ce moteur d'indexation a été conçu de manière à simplifier à l'extrême son installation au sein de vos applications Web Ellipse. Une API, elle aussi très simple d'emploi, a de plus été définie afin d'intérroger la base de données résultante de l'indexation des documents de votre application Web. Via cette API vous pourrez retourner à vos utilisateurs un ensemble de documents répondant aux différents critères de recherche.

Moteur de base de données utilisées

Pour stocker le contenu des différents documents scannés, une base de données relationnelle est utilisée : il s'agit de la base de données Java DB. Pour information, Java DB est une distribution supportée par SUN Microsystems de la base de données Derby (développée par la fondation Apache). Java DB est développée exclusivement en Java, donc portable.

Je vous rappelle que Java DB est intégrée au Java SE depuis sa version 6.0. Néanmoins, Java DB n'est pas directement accessible via le CLASSPATH initial du J2SE. EN CONSEQUENCE, IL EST NECESSAIRE DE CONFIGURER VOTRE SERVEUR WEB (TOMCAT OU TOUT AUTRE SERVEUR D'APPLICATION J2EE) AFIN QU'IL ETENDE, LORS DE SON DEMARRAGE, LE CLASSPATH POUR POINTER AUSSI VERS LE FICHIER DERBY.JAR. Sans cette étape (spécifique à chaque serveur), les manipulations suivantes ne pourront pas fonctionner !

Activation du moteur d'indexation

L'activation du moteur d'indexation est très simple. L'ajout d'une seule définition de paramètre dans le fichier "web.xml" peut suffire à configurer son lancement au démarrage de votre application Web. Comme le montre l'exemple ci-dessous (en ligne 26), le paramètre SEARCH_ENGINE_ENABLED indique à l'application Web Ellipse que le moteur d'indexation est requis. A défaut de définir, ce paramètre sera considéré comme valant faux.

 
01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE web-app PUBLIC
03   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
04   "http://java.sun.com/dtd/web-app_2_3.dtd">
05 
06 
07 <web-app>
08 
09     <display-name>Virtual Caddy - Ellipse Sample</display-name>
10     <description>Ellipse Sample</description>
11 
12     <context-param>
13     	<param-name>TRACE_ENABLED</param-name>
14     	<param-value>true</param-value>
15     </context-param>
16     <context-param>
17     	<param-name>TRACE_LOCALHOST_ONLY</param-name>
18     	<param-value>true</param-value>
19     </context-param>
20     <context-param>
21     	<param-name>TRACE_URL</param-name>
22     	<param-value>Trace.wp</param-value>
23     </context-param>
24 
25     <context-param>
26     	<param-name>SEARCH_ENGINE_ENABLED</param-name>
27     	<param-value>true</param-value>
28     </context-param>
29 
30     <servlet>
31       <servlet-name>Ellipse Servlet</servlet-name>
32       <servlet-class>corelib.services.web.webapplications.ControllerServlet</servlet-class>
33     </servlet>
34 
35     <servlet-mapping>
36         <servlet-name>Ellipse Servlet</servlet-name>
37         <url-pattern>*.wp</url-pattern>
38     </servlet-mapping>
39 
40 </web-app>
Fichier "WEB-INF/web.xml"

Dans l'état actuel des choses, l'indexation des documents est réalisée par un thread d'arrière plan au démarrage de l'application Web considérée. Il est néanmoins possible de forcer la reconstruction de la base de données via les lignes de code suivantes.

 
SearchEngine searchEngine = SearchEngine.getInstance();
searchEngine.startScanning();

Lors d'une reconstruction de la base, le moteur d'indexation va scanner tous les types de documents pris en charge et ce récursivement dans tous les dossiers de l'application Web. Notez néanmoins que le moteur d'indexation ne traitera pas le dossier WEB-INF étant donné que celui-ci ne peut pas contenir de documents téléchargeables via HTTP. Notez aussi que la base de données gérée par le moteur d'indexation est stockée dans ce dossier.

Il est aussi possible de demander au moteur d'indexation d'ignorer certains répertoires de l'application Web considérée. Pour ce faire il faut rajouter le paramètre SEARCH_ENGINE_EXCLUDES. La valeur associée consiste en une liste de répertoires séparés par des points-virgules. Attention : cette valeur est bien-entendu "case-sensitive". L'exemple ci-dessous vous montre, par exemple, comment ignorer tous les documents contenus dans le répertoire admin.

 
01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE web-app PUBLIC
03   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
04   "http://java.sun.com/dtd/web-app_2_3.dtd">
05 
06 
07 <web-app>
08 
24     <!-- File begin -->
29 
25     <context-param>
26     	<param-name>SEARCH_ENGINE_ENABLED</param-name>
27     	<param-value>true</param-value>
28     </context-param>
29 
25     <context-param>
26     	<param-name>SEARCH_ENGINE_EXCLUDES</param-name>
27     	<param-value>admin</param-value>
28     </context-param>
29 
24     <!-- File end -->
39 
40 </web-app>
Fichier "WEB-INF/web.xml"

Ajout d'un scanner pour un nouveau type de fichier

Pour l'heure seules les pages web Ellipse sont acceptées par le moteur d'indexation. Néanmoins celui-ci est conçu de manière à pouvoir intégrer de nouveau type de parseurs, si le besoin se fait ressentir. Au sein de l'architecture du moteur d'indexation, tout type de parseur doit implémenter l'interface corelib.services.web.searchengine.database.scanners.DocumentScanner. Voici un extrait de la déclaration de l'interface en question.

 
01 package corelib.services.web.searchengine.scanners;
02 
03 public interface DocumentScanner {
04
05     public String getDocumentTitle();
06
07     public WordDictionary scanWebPage( String documentFilename ) throws DocumentScannerException;
08 
09 }
Interface "corelib.services.web.searchengine.scanners.DocumentScanner"

La première méthode, getDocumentTitle, permet de récupérer le titre du document scanné. La seconde méthode, scanWebPage, analyse et extrait les mots contenus dans le document passé en paramètre. La localisation du document, passée en paramètre, est exprimée via un chemin en absolu sur le système de fichier. Cette méthode doit de plus retourner une instance de type corelib.services.web.searchengine.scanners.WordDictionary. C'est grâce à cet objet que le moteur d'indexation pourra retrouver les mots contenu dans le document considéré.

La classe WordDictionary expose notamment la méthode addWordScore qui ajoute au dictionnaire un mot avec son score associé. Si ce mot existe déjà pour ce document, alors seul le score est incrémenté. Si vous ne souhaitez pas prendre en charge le découpage d'une chaîne de caractères en mot, vous pouvez aussi utiliser la méthode public void parseString( String theString, WordScoreEnum currentScore ). Le premier paramètre correspond à la chaîne de caractères à découper. Le second, au score associé aux mots contenus dans la chaîne. Le score, représenté par un type énuméré dépend du contexte dans lequel la chaîne a été trouvée (un titre de document, un sous titre, ...). Pour de plus amples informations, je vous renvoie vers la javadoc de Ellipse.

Une fois votre DocumentScanner codé, il ne vous reste plus qu'à l'inscrire dans votre application Web pour l'(es) extension(s) de fichiers associée(s). Pour ce faire, ajoutez encore une fois, le paramètre SEARCH_ENGINE_ADDITIONAL_SCANNERS au fichier WEB-INF/web.xml.

 
01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE web-app PUBLIC
03   "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
04   "http://java.sun.com/dtd/web-app_2_3.dtd">
05 
06 
07 <web-app>
08 
24     <!-- File begin -->
29 
25     <context-param>
26     	<param-name>SEARCH_ENGINE_ENABLED</param-name>
27     	<param-value>true</param-value>
28     </context-param>
29 
25     <context-param>
26     	<param-name>SEARCH_ENGINE_ADDITIONAL_SCANNERS</param-name>
27     	<param-value>ext1=fr.package.ClassBasedOnDocumentScanner;html=fr.package.OtherClass</param-value>
28     </context-param>
29 
24     <!-- File end -->
39 
40 </web-app>
Fichier "WEB-INF/web.xml"

Implémenter une page de recherche

Pour clore ce tutorial, nous allons voir comment interroger le moteur d'indexation pour connaître la liste de pages (classées par ordre de pertinence) qui répond à un critère de recherche donnée. Pour obtenir un ensemble de résultats, il vous faut invoquer la méthode getSearchResultSet à partir du singleton SearchEngine.getInstance(). Cette méthode accepte deux paramètres : la chaîne de caractères à rechercher (elle sera automatiquement découpée en mots via la méthode WordDictionary.parseString) ainsi que le nombre de résultats à retourner. Le code suivant vous montre comment coder une classe de page Web permettant d'interroger le moteur d'indexation.

 
01 package corelib.services.web.samples;
02 
03 import corelib.services.web.searchengine.SearchEngine;
04 import corelib.services.web.searchengine.SearchResult;
05 import corelib.services.web.searchengine.SearchResultSet;
06 import corelib.services.web.webapplications.WebPage;
07 
08 
09 public class Search extends WebPage {
10 
11     private SearchResult [] results = null;
12 
13 
14     public String getRequestedString() {
15         return request.getParameter( "txtSearch" );
16     }
17 
18 
19     public SearchResult [] getResults() {
20         if ( this.results == null ) {
21             SearchEngine searchEngine = SearchEngine.getInstance();
22             SearchResultSet resultSet = searchEngine.getSearchResultSet( request.getParameter( "txtSearch" ), 50 );
23             this.results = resultSet.toArray();            
24         }
25         return this.results;
26     }
27 
28 }
Classe "corelib.services.web.samples.Search"

ATTENTION : le cycle de vie d'une page Web impose qu'on calcule les résultats avant de passer dans les gestionnaires de clique sur les boutons, et ceux à cause du data binding (la liaison au données). Le plus simple est donc de réaliser cette étape dans la méthode de récupération des résultats (içi getResults (lignes 19-26)).

Ensuite, il ne reste plus qu'a coder une page web pour présenter les résultats calculés. Notez l'utilisation de la liaison aux données via un composant web de type <web:Repeater>, pour plus de facilité.

 
01 <?xml version="1.0" encoding="ISO-8859-1" ?>
02 <web:Html xmlns:web="corelib.services.web.components"
03            codeBehind="corelib.services.web.samples.Search">
04     <head>
05         <title>Search page sample</title>
06         <link rel="stylesheet" type="text/css" href="Nolege.css" />
07         <script language="javascript" src="Includes/Global.js"></script>
08     </head>
09     <body>
10         <h1 align="center">Search page sample</h1>
11 
12         <form action="Search.wp" method="post">
13             <web:TextBox id="txtSearch" />&#160;
14             <web:Button id="btnSearch" value="Rechercher" />
15         </form>
16         
17 
18         <h2>Your results for
19              "<web:OutputText text="#{this.requestedString}" />"</h2>
20 
21         <ol>
22             <web:Repeater values="#{this.results}" elementAlias="result">
23 
24                 <li class="text" style="font-size: 11pt;">
25                     <web:Link href="#{result.filename}">
26                         <b><web:OutputText text="#{result.title}" /></b> <br/>
27                         <web:OutputText text="#{result.filename}" />
28                     </web:Link> -
29                     <web:OutputText text="#{result.fileSize}" /> ko.
30                 </li>
31 
32             </web:Repeater>
33         </ol>
34 
35     </body>
36 </web:Html>
Page web "Search.wp"