Newsgroup: it.comp.java
Titolo: [JSP] Struttura cartelle <jsp:useBean.....>

Salve a tutti, rieccomi a postare!!!
Prometto che non appena potrò parteciperò attivamente a questo NG a cui devo
già moltissimo!
Sto sviluppando un'applicazione Rubrica in ambiente jsp e servlet, con l'uso
di un db access, come test, per imparare ad utilizzare la tecnologia.
L'applicazione implementa il modello MVC utilizzando:
Una setvlet:
controller        - smista le richieste dell'utente.
due Java-Beans per accedere al DB:
    DataBaseLib   - effettua le operazioni sul db
    UserLib       - effettua le operazioni di validazione utente sul db
(non chiedetemi perche' sono divise, non lo so)
alcune pagine JSP per visualizzare i dati restituiti dai bean.
    login.jsp     - mi connette al db e valida l'utente.
    rubrica.jsp   - visualizza il contenuto della rubrica. (non funziona)
per il momento, vorrei usare i seguenti tag per prelevare le informazioni:
    <jsp:useBean id="dbLib" class="sweng.db.DataBaseLib" scope="session"/>
    <jsp:getProperty name="dbLib" property="Contatti"/>
Il compilatore mi da errore alla riga -1, in qualche modo sono riuscito a
farmi dare un codice comprensibile d'errore ed ho visto che non mi trova il
bean DataBaseLib e non riesco a capire il motivo.
Forse il problema è nell'uso delle directory, le mie pagine jsp si trovano
nella root dell'applicazione, mentre la servlet e le classi si trovano
rispettivamente in \WEB-INF\Classes e in \WEB-INF\Classes\sweng\db\.
Dovrei mettere tutto insieme???
Ho sbagliato a mettere le classi in una cartella separata (package???)?
Di seguito il pezzo interessato della classe DataBaseLib:
.....
  public Vector getContatti()
  {
    return Contatti;
  }
  public void setContatti()
  {
    this.Contatti = Contatti;
  }
  public void stampaContatti()
  {
    String quStampaContatti="SELECT * FROM CONTATTI ORDER BY COGNOME, NOME";
    try
    {
      rsQuery=stmt.executeQuery(quStampaContatti);
      while(rsQuery.next())
      {
        Contatti.addElement(rsQuery.getString("IdContatto"));//inserisco nel
vector quello che torna dalla query
        Contatti.addElement(rsQuery.getString("Nome"));
        Contatti.addElement(rsQuery.getString("Congnome"));
        Contatti.addElement(rsQuery.getString("Telefono"));
        Contatti.addElement(rsQuery.getString("EMail"));
      }
    }
    catch(SQLException e)
    {
      System.out.println("errore" +e+ " SQL in DataBaseLib.stampaContatti");
    }
  }
}
Ringrazio tutti per l'aiuto,
ciao.
Davide

 rispettivamente in \WEB-INF\Classes e in \WEB-INF\Classes\sweng\db\.
[cut]
La directory per le classi dovrebbe essere \WEB-INF\classes (classes con
l'iniziale minuscola). Io metterei anche la servlet in un package. Se non
ricordo male qualche versione di Tomcat non trovava le classi se non erano
in un package.
-- 
Lucio Benfante - Java User Group Padova
Brainbench MVP for Java 1
http://www.brainbench.com
MyTranscript: 
http://www.brainbench.com/transcript.jsp?pid=167064

in un package.
Si, la directory corretta dove inserire le classi è WEB-INF/classes,
mentre se hai delle librerie (in formato .jar), devi metterle in
WEB-INF/lib.
Per quanto riguarda i "package", il discorso è semplice. Sun ha sempre
considerato "bad practice" scrivere codice senza inserirlo all'interno
di un package. Chi ha disegnato Tomcat ha utilizzato una struttura
tale per cui le pagine JSP sono eseguite all'interno di un package (se
non ricordo bene è org.apache.jsp). Questo significa che se
all'interno del nostro codice inseriamo classi senza package, Tomcat
le cerca all'interno di quel package.
Nelle pagine JSP si potrebbe usare la soluzione di importare le classi
senza package... ma questa soluazione non è certo delle migliori.
Il consiglio è sempre quello di scrivere classi all'interno di un
package..
	Regards,
		Kazuma
---
I've got nothing against God. It's his fan club I can't stand.
Alex "Kazuma" Garbagnati, 
http://www.kazuma.net
EJB & Tomcat jGuru FAQ Manager, 
http://www.jGuru.com
Tutor "Progetto Scuole", 
http://www.JIA.it
Java Italian Association - SUN - MIUR

 package..
Ora è così, ma non mi funziona ancora!! Forse devo mappare il mio package in
web.xml???

 web.xml???
No, in web.xml devi mappare la servlet, ma le pagine jsp ed il bean non
c'entrano.
..ci fai vedere qualche messaggio d'errore?


> ..ci fai vedere qualche messaggio d'errore?
Certo, eccolo:
description:
The server encountered an internal error () that prevented it from
fulfilling this request.
exception
org.apache.jasper.JasperException: Cannot find any information on property
'Telefono' in a bean of type 'sweng.db.DataBaseLib'
 at
org.apache.jasper.runtime.JspRuntimeLibrary.getReadMethod(JspRuntimeLibrary.
java:704)
 at
org.apache.jasper.compiler.Generator$GenerateVisitor.visit(Generator.java:69
4)
 at org.apache.jasper.compiler.Node$GetProperty.accept(Node.java:552)
 at org.apache.jasper.compiler.Node$Nodes.visit(Node.java:1028)
 at org.apache.jasper.compiler.Node$Visitor.visitBody(Node.java:1070)
 at org.apache.jasper.compiler.Node$Visitor.visit(Node.java:1076)
 at org.apache.jasper.compiler.Node$Root.accept(Node.java:232)
 at org.apache.jasper.compiler.Node$Nodes.visit(Node.java:1028)
 at org.apache.jasper.compiler.Generator.generate(Generator.java:1917)
 at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:242)
 at org.apache.jasper.compiler.Compiler.compile(Compiler.java:369)
 at
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:4
73)
 at
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:1
90)
 at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
 at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
 at
org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.
java:684)
 at
org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatch
er.java:432)
 at
org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher
.java:356)
 at sweng.db.controller.doPost(controller.java:119)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
 at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Application
FilterChain.java:247)
 at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterCh
ain.java:193)
 at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.ja
va:256)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
 at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
 at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.ja
va:191)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
 at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
 at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
 at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180
)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
 at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.
java:171)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641)
 at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172
)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:641)
 at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
 at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java
:174)
 at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invok
eNext(StandardPipeline.java:643)
 at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
 at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
 at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:594)
 at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConne
ction(Http11Protocol.java:392)
 at
org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
 at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.jav
a:619)
 at java.lang.Thread.run(Thread.java:536)
Ma la proprietà c'e', la prendo usando il tag <jsp:useBean...> e nella
classe ci sono i metodi setTelefono e getTelefono.
Vi allego il codice della classe.
package sweng.db;
[CUT]
public class DataBaseLib
{
[CUT]
  private String Telefono;
  private Vector Contatti=new Vector();
  public String getTelefono()
  {
    return Telefono;
  }
  public void setTelefono(String Telefono)
  {
    this.Telefono = Telefono;
  }
  public Vector getContatti()
  {
    return Contatti;
  }
  public void setContatti()
  {
    this.Contatti = Contatti;
  }
  public DataBaseLib()
  {
    try
    {
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
    }
    catch(ClassNotFoundException e)
    {
      System.out.println("errore in connettiDatabase");
    }
    try
    {
      con=DriverManager.getConnection(DB_URL,"","");
      stmt=con.createStatement();
    }
    catch(SQLException e)
    {
      System.out.println("Errore di connessione");
    }
    // non funziona nemmeno se faccio così:
    // Telefono = "76547654";
  }
  public void stampaContatti()
  {
    String quStampaContatti="SELECT * FROM CONTATTI ORDER BY COGNOME, NOME";
    try
    {
      rsQuery=stmt.executeQuery(quStampaContatti);
      while(rsQuery.next())
      {
        Contatti.addElement(rsQuery.getString("IdContatto"));//inserisco nel
vector quello che torna dalla query
        Contatti.addElement(rsQuery.getString("Nome"));
        Contatti.addElement(rsQuery.getString("Congnome"));
        Contatti.addElement(rsQuery.getString("Telefono"));
        Contatti.addElement(rsQuery.getString("EMail"));
      }
    }
    catch(SQLException e)
    {
      System.out.println("errore" +e+ " SQL in DataBaseLib.stampaContatti");
    }
  }
[CUT]
}
Mille grazie Ragazzi!

 classe ci sono i metodi setTelefono e getTelefono.
[cut]
Si', ma la proprieta' non si chiama Telefono, ma telefono (con l'iniziale
minuscola).


   }
A parte l'uso sconsiderato delle maiuscole (non offenderti, è solo che io
alla base di tutto uso sempre le Java Code Conventions che puoi trovare a
http://java.sun.com/docs/codeconv/
), non riesco a capire il problema...
L'errore, come hai giustamente fatto notare anche tu, è nell'impossibilità
di jasper di trovare il getter per la proprietà Telefono, getter che invece
esiste...
Puoi fare una prova idiota... nel tuo jsp:getProperty, puoi usare "telefono"
al posto di "Telefono" come, probabilmente, hai fatto? Non vorrei che jasper
si incasini (poco probabile, ma possibile)...


 minuscola).
... No comment, scusatemi, non lo sapevo!
 :-S
Ora funziona! Grazie mille

 si incasini (poco probabile, ma possibile)...
Infatti, e cosi si e incasinato perche uso la lettera maiuscola.
Quindi la proprieta ha la lettera minuscola, per convenzione?
Ora mi leggo il link, onde evitare altri problemi...
Mille grazie!!!

 Mille grazie!!!
La logica dovrebbe essere questa... Tu crei il tuo bean, che è un insieme di
proprietà che possono essere read/write, read only oppure write only. Questo
avviene tramite i getters/setters. Leggi attraverso un getter e scrivi
attraverso un setter (non il cane).
Il jsp:getProperty (e secondo la stessa logica il setProperty) altro non fa
che leggere la proprietà che tu gli hai detto di leggere, ricavarne il
getter (o il setter se si tratta di setProperty) e eseguire la chiamata al
metodo.  Siccome non esiste certezza del fatto che la tua proprietà sia di
tipo String (che, per HTML, è l'unico formato reale), probabilmente Jasper
va a cercare (tramite reflection) la proprietà all'interno del tuo bean.
Ora qui, però, avrei qualcosa da "contestare". Che tipo di ricerca effettua?
(si lo so, potrei dare un occhiata al codice e vedere... ma la pigrizia
impazza).
Io cercherei prima di tutto se esiste il getter. prendo il valore
all'interno del mio attributo, capitalizzo la prima lettera e ci aggiungo un
get davanti. Cerco, tramite reflection se questo metodo esiste. Se non
esiste posso fare l'intelligente e dire "magari è booleana" e creo il metodo
con l''is' al posto del 'get' davanti alla mia proprietà (sempre con
l'iniziale maiuscolata). Non c'è neanche questa? Allora lancio
l'eccezione...
Questo, però, non è il ragionamento di jasper. Se così fosse, anche violando
le convenzioni di codice, (come hai fatto), avresti ottenuto il tuo
risultato. Evidentemente l'analisi e la ricerca del metodo sono più
profonde... Non so quanto concordo con questo... (anche se a dire il vero,
costringere i developer a "strictly follow conventions and specifications" è
sempre buona cosa... magari bisognerebbe dirlo ai signori di BEA, che hanno
problemi nel comprendere questo concetto...)


 problemi nel comprendere questo concetto...)
Ok....
Con NetBeans, posso vedere il codice "Convertito" in servlet, in questo modo
vedo :
out.print(JspRuntimeLibrary.toString((((sweng.db.DataBaseLib)pageContext.fin
dAttribute("dbLib")).getTelefono())));
questo mi deriva sia dalla JSP "corretta" che da quella con Telefono.
Dopo attenta verifica, ho notato che le servlet prodotte da entrambe le
versioni sono identiche.
Se la traduzione e' uguale, in che momento avviene l'errore??? Una volta
tradotta non dovrebbe causarne piu', giusto?