lunedì 31 ottobre 2011

Creare un autocomplete con Spring e DWR

Una settimana fa avevo bisogno di fare un autocomplete in un textbox per un progetto in Java, in cui stavo lavorando. Mi serviva per fornire suggerimenti agli utenti. Ho deciso di fare tutto ciò utilizzando il DWR (Direct Web Remoting). DWR è una libreria che ci permette di esporrere un servizio server-side al javascript. Verrano create alcune librerie javascript al runtime che poi utilizzeremo.

In pratica l'utente inizia a scrivere nel textbox. Utilizzando l'evento "onkeyup" chiamo una funzione javascript che fa delle chiamate asincrone all'oggetto DWR. Quest'ultimo cercherà nel database se ci sono suggerimenti da visualizzare. Ritorna i suggerimenti che recupera dal database al javascript e quest'ultimo le visualizzerà all'utente. È molto semplice da implementare ed ora vi spiegherò come fare.

Passo 1:
Creo l’interfaccia AutoCompleteDao:

 public interface AutoCompleteDao {  
   List<String> getResults(String input) throws DataAccessException;  
 }  


Poi implemento l’interfaccia appena creata. Il metodo getResults non fa altro che una “like” sulla tabella del database per una certa stringa, che prende come parametro di input, e restituisce i risultati come una lista di stringhe:

 public class AutoCompleteImpl implements AutoCompleteDao {  
   String sql;  
   public AutoCompleteImpl(String sql) {  
     super();  
     this.sql = sql;  
   }  
   public List<String> getResults(String input)  
       throws DataAccessException {  
   // implementazione del metodo, semplicemente faccio una “like” con  
   // il parametro di input.  
   // return list di risultati.    
   }  
 }  


Passo 2:
Importo dwr.jar nel progetto e poi nel file web.xml aggiungo il DWR:

 <servlet>  
   <servlet-name>dwr</servlet-name>  
   <servlet-class>  
     org.directwebremoting.spring.DwrSpringServlet  
   </servlet-class>  
   <init-param>  
     <param-name>debug</param-name>  
     <param-value>true</param-value>  
   </init-param>  
   <init-param>  
     <param-name>scriptCompressed</param-name>  
     <param-value> false</param-value>  
   </init-param>  
   <init-param>  
     <param-name>crossDomainSessionSecurity</param-name>  
     <param-value>false</param-value>  
   </init-param>  
   <init-param>  
     <param-name>activeReverseAjaxEnabled</param-name>  
     <param-value>true</param-value>  
   </init-param>  
   <init-param>  
     <param-name>allowScriptTagRemoting</param-name>  
     <param-value>true </param-value>  
   </init-param>  
 </servlet>  
 <servlet-mapping>  
   <servlet-name>dwr</servlet-name>  
   <url-pattern>/dwr/*</url-pattern>  
 </servlet-mapping>  


Passo 3:
Dopodiché aggiungo nel file applicationContext.xml il seguente:

 <bean id="autoComplete" class="com.aldosinanaj.dwr.AutoCompleteDwr">  
   <dwr:remote javascript="AjaxAutoComplete"> //metodo javascript da invocare  
     <dwr:include method="getSuggestions"/>  
   </dwr:remote>  
   <property name="autoComplete" ref="autoComplete"></property>  
 </bean>  


Ho configurato il bean che sarà esposto nel javascript. Il tag “dwr:method” ci permette di dichiarare la funzione che verrà invocata da javascript.

Passo 4:
Ora creò la classe java che implementerà la funzione javascript definita al passo 3, ovvero la classe
com.aldosinanaj.dwr.AutoCompleteDwr.java
Riceve richieste da javascript, recupera i risultati dal database e li ritorna al javascript.

 public class AutoCompleteDwr {  
   private AutoCompleteDao autoComplete;  
   public String[] getSuggestions(String input) {  
     List<String> listaRisultati = autoComplete.getResults(input);  
     String[] arrayRisultati = listaRisultati.toArray(new String[]{});  
     return arrayRisultati;  
   }  
   public void setAutoComplete(AutoCompleteDao autoComplete) {  
     this.autoComplete = autoComplete;  
   }  
 }  


Passo 5:
Il textbox nella pagina jsp (autoComplete.jsp) verrà programmato come segue:

 <label>Cerca:</label>  
 <br>  
 <form:input path="cercaTextBox" size="23" id="cercaTextBox" onkeyup='autoComp(this.value);' />  
 <div class="divSuggerimenti" id="divSuggerimenti" style="display: none;" >  
   <div class="listaSuggerimenti" id="listaSuggerimenti" ></div>  
 </div>  


Utilizzo l’evento “onkeyup” per invocare la funzione javascript autoComp() che fa chiamate asincrone all’oggetto DWR. Non dimenticare di importare le funzioni javascript nella pagina. Le prime tre vengono creati al runtime.

 <script type='text/javascript'   
 src='${pageContext.request.contextPath}/dwr/interface/AjaxAutoCompleteIfaces.js'></script>  
 <script type='text/javascript' src='${pageContext.request.contextPath}/dwr/engine.js'></script>  
 <script type='text/javascript' src='${pageContext.request.contextPath}/dwr/util.js'></script>  
 <script type='text/javascript' src='${pageContext.request.contextPath}/js/autoComplete.js'></script>  


Passo  6:
Ora passiamo al javascript. Creò un file autoComplete.js con tutte le funzioni javascript che devo utilizzare.

 function autoComp(input) {  
   if (input.length >2){  
     AjaxAutoComplete.getSuggestions(input, callback);  
   }else{  
     document.getElementById("divSuggerimenti").style.display = "none";  
   }  
   rimuoviTutto();  
 }  
 function callback(msg) {  
   if (msg.length > 0) {  
     document.getElementById("divSuggerimenti").style.display = "block";  
     var listaSuggerimenti = document.getElementById("listaSuggerimenti");  
     var ul = document.createElement('ul');  
     for (var i = 0; i < msg.length; i++){  
       var li = document.createElement('li');  
       li.innerHTML = msg[i];  
       li.onclick = riempiTextBox(msg[i]);  
       ul.appendChild(li);  
     }  
     listaSuggerimenti.appendChild(ul);  
   }  
 }  
 function riempiTextBox(testo) {  
   document.getElementById("cercaTextBox").value = testo;  
   document.getElementById("divSuggerimenti").style.display = "none";  
   rimuoviTutto();  
 }  
 function rimuoviTutto() {  
   var listaSuggerimenti = document.getElementById("listaSuggerimenti");  
   var figli = listaSuggerimenti.childNodes;  
   for (var i = 0; i < figli.length; i++) {  
     listaSuggerimenti.removeChild(figli[i]);  
   }  
 }  


Passo  7:
L’ultimo passo è la creazione di un foglio di stile che lo chiamo autoComplete.css

 .divSuggerimenti {  
 position: relative;  
 width: 150px;  
 border: 1px solid #000;  
 }  
 .listaSuggerimenti ul {  
 margin: 0;  
 padding : 0;  
 list-style: none;  
 }  
 .listaSuggerimenti li:hover {  
 background-color: #eee;  
 color: #79AF2B;  
 font-weight: bold;  
 }  


Il risultato non sarà altro che:


domenica 30 ottobre 2011

Come sbrandizzare Acer Liquid Metal Vodafone

Un mese fa mi sono comprato lo smartphone Acer Liquid Metal marchiato vodafone (Acer_LiquidMetal_1.000.14_EMEA-VFIT). Il problema è che non riuscivo installare gli aggiornamenti ufficiali sul sito della Acer. Quindi per aver aggiornato il mio smartphone con il gingerbread ufficiale rilasciato dall'Acer ho seguito questi passi:
  1. Scaricato la recovery amonra da questo link.
  2. Scaricato z4root (l'applicazione per avere i diritti di root, ovvero amministratore) da qui.
  3. Scaricato la rom Acer_LiquidMetal_1.100.00_EMEA-GEN1_01.02.02 da qui.
  4. Scaricato l'ultima OS Android Gingerbread 2.3 e i driver USB dal sito di acer.
  5. Scaricato Acer Download Tool da qui.
  6. Ho installato i driver USB scaricato al punto 4.
  7. L'applicazione z4root l'ho copiata sulla microSD. Poi ho installato Astro File Manager dal market. Ho abilitato "Origini sconosciute" da Impostazioni --> Applicazioni. Ho abilitato anche "Debug USB" da Impostazioni --> Applicazioni --> Sviluppo. Ho avviato l'applicazione Astro e ho aperto il file z4root. Ho installato z4root in modalità Permanent Root.
  8. Poi sempre in modalità "Debug USB" ho collegato lo smartphone con il pc e ho clickato su install_recovery.cmd di amonra scaricato al punto 1. Si è aperto una finestra dos e ha rilevato il mio smartphone facendo vedere un numero accompagnato dalla parola Device. Ho seguito tutte le istruzioni che sono abbastanza banali. In questa fase lo schermo è nero con dei quadratini a colore. Alla fine di questo passo ho scollegato lo smartphone.
  9. Ho installo quickboot dal market. Dopodichè ho avviato quickboot e sono andato in modalità Recovery Mode. In questa modalità il touch non funziona. Per muovermi ho utilizzato i tasti di volume. Per selezionare la voce ho utilizzato il tasto della fotocamera. Per andere indietrò ho utilizzato il tasto on/off.
  10. Ho fatto un backup del mio firmware originale (cosi posso tornare quando voglio al mio firmware). Quindi vado su backup/restore e seleziono con il tasto fotocamera e poi seleziono nandroid backup. Il backup viene memorizzato nella cartella nandroid della microSD. Fatte attenzione a non cancellare questa cartella altrimenti perdete il vostro backup.
  11. Sono tornato indietro con il tasto on/off e ho selezionato la vole wipe all. Dopo aver fatto wipe all, ho selezionato la voce "reboot system now".
  12. Lo smartphone si è riavviato e dopodichè ho impostato di nuovo lo smartphone in modalità "Debug Mode" e l'ho collegato al pc.
  13. Ho aperto l'Acer Download Tool  scaricato al punto 5 e nella voce "Merged OS file" ho selezionato la rom scaricato al punto 3 e poi ho fatto Start. Ha impiegato intorno ai 20 minuti per flashare la rom.
  14. Dopo aver finito, lo smartphone si è riavviato ed ho scollegato il cavo. Alla fine ho ottenuto lo smartphone senza il brand vodafone ed ora è possibile installare la rom ufficiale Acer.
  15. Ho scompattato la rom scaricata al punto 4 e ho lanciato setup.exe. Ho seguito le istruzioni passo per passo ed era molto semplice. Ad un certo punto mi ha chiesto di collegare lo smartphone in modalità "Debug Mode". Alla fine ho aggiornato il mio smartphone con il GingerBread Android ufficiale Acer.
Sono molto soddisfatto di gingerbread per ora :-)

PS: Sbrandizzare l'acer porta alla perdità della garanzia e queste operazioni sono pericolose. Quindi non mi assumo nessuna responsabilità su eventuali danni da questa guida.