Enrera
Mòdul 8
Iniciació a la programació en Java
  Pràctica
1
2
3
4
5
   
Exercicis
Exercicis
 
  Els JavaBeans, pastilles de java
   

A partir d' pràctica revisarem els mecanismes per a cridar programes de Java (Java Beans) des de les nostres pàgines JSP.

   
Desenvolupament de la pràctica:
   
 
  • Repassarem el concepte de Java Bean.

  • Estudiarem el magatzem de recursos WEB-INF que té qualsevol aplicació JSP.

  • Crearem una pàgina web que executa Java Beans.

  • Aprofitarem la feina per a crear una segona pàgina web "copiant i enganxant" i canviant un
    sol
    paràmetre.
 

Repasseu el codi de la pàgina web que hem creat a la pràctica anterior. Observareu que, per poc que compliquem els continguts, l'aspecte del fitxer font és bastant brut: es barreja codi Java amb codi HTML, i es fa complicat seguir la seqüència lògica del programa. Fins un cert punt és un problema inevitable i constitueix el punt més feble de la programació JSP. A la literatura informàtica, aquest fenomen rep el nom de "spaguetti code", per la il·legibilitat dels fitxers font.

Aquest és un problema que es pot controlar bastant quan és el mateix programador qui fa el disseny de les pàgines, el codi Java dels programes i les consultes SQL a les bases de dades.Però imagineu una empresa que té dissenyadors web que no saben Java i programadors de Java que no saben disseny web. La col·laboració entre els dos sectors pot fer-se realment complicada si han de compartir el mateixos fitxers JSP.

Per solucionar aquest problema es poden seguir diferents estratègies. Totes intenten que les pàgines JSP tinguin poc codi Java, que els scriptlets siguin petits o, fins i tot, inexistents i que els programadors Java puguin fer la seva part de feina escrivint classes en els seus entorns de programació habituals.

Nosaltres estudiarem la solució més senzilla: aprendrem a escriure petits programes -Java Beans- en el nostre JCreator, els quals seran cridats després per les pàgines JSP. D'aquesta forma, a les pàgines web gairebé tot serà codi HTML, i podrem crear el suport en Java amb tots els avantatges d'escriptura i depuració de l'IDE.

   

Pastilles de Java:

   

Ja sabem que Java és un llenguatge concebut per a reutilitzar codi amb facilitat i estalviar costos a les empreses productores de programes. En aquest context es va crear el concepte de Bean. Un Java Bean és un component de software independent de la plataforma, autocontingut i reusable que, a més, ha de poder ser manipulat visualment pels entorns de programació Java més complets com els de Borland o de la pròpia Sun Microsystems. És, doncs, com una peça de Mecano preparada per a enganxar-la allí on ens faci falta.

La tecnologia JSP es va dissenyar per tal de tenir una relació fàcil i natural amb els Java Beans. Per això es va crear l'acció <jsp:useBean, que els crida i manipula amb molt poc cost de codi.

Aquí no estudiarem l'arquitectura Java Bean, només escriurem algun programa que utilitza una sintaxi conforme a allò que es demana a un Java Bean i que, per tant, n'és una expressió mínima.

El nostre objectiu serà fer programes de Java que s'entenguin fàcilment amb les pàgines JSP i que retirin de la pròpia pàgina el màxim de codi Java i així fer-les més entenedores i fàcils de mantenir.

Però abans d'escriure una nova pàgina que sigui capaç de cridar un programa de Java, hem de descobrir on es desa i com gestiona codi Java una aplicació JSP.

   
El magatzem de recursos WEB-INF:
   

La nostra aplicació d'exemple viu en el directori c:/biblioteca. Aquesta carpeta és la seva arrel i la podem estendre per tots els directoris que necessitem. Sabem que si tenim una pàgina JSP en un subdirectori, per a cridar-la només ens caldrà escriure el camí al navegador web (si tenim una pàgina a c:/biblioteca/carnets/imprimir.jsp la podrem cridar des del navegador web mitjançant http://localhost/carnets/imprimir.jsp).

Aquest principi és cert en tots els casos, menys en un. Hi ha una carpeta, que el navegador no ens ensenya, que es diu WEB-INF i que penja immediatament de l'arrel. El servidor ens prohibeix l'accés perquè el seu contingut no té a veure amb la navegació per l'aplicació: és una carpeta de configuracions i recursos.

Els objectes que es poden trobar dins WEB-INF són els següents:

  • El fitxer de configuració web.xml. La seva presència no és imprescindible però és habitual. Conté la configuració de seguretat de l'aplicació, sistemes d'autentificació, mapejat de servlets, etc.

  • La carpeta /lib, amb les llibreries de Java, compilades i freqüentment empaquetades en fitxers .jar, que utilitza l'aplicació. Imagineu-vos que utilitzeu un programa de gestió del correu electrònic per a la vostra web, el codi del qual està empaquetat en un fitxer .jar. L'haureu de posar a /WEB-INF/lib per tal que Resin el pugui trobar.

  • La carpeta /classes. Té una funció equivalent a la carpeta /lib (contenir classes de Java), però Resin la tracta de manera diferent: a la carpeta /lib hi posarem les llibreries que ja funcionen correctament i que no s'han de revisar mai. Resin les carrega a l'iniciar l'aplicació sense més verificacions. Els continguts presents a la carpeta /classes, en canvi, són revisats periòdicament pel servidor a la recerca de versions noves. Si actualitzem una classe d'aquesta carpeta, Resin l'actualitza a l'aplicació. Si ens interessa i configurem Resin adequadament, fins i tot podem deixar-hi els fitxers font *.java en lloc dels corresponents *.class: Resin els compil·larà abans d'utilitzar-los.

Sembla clar, doncs, que el lloc on hem de deixar els fitxers dels programes que ara escriurem és a la carpeta c:/biblioteca/WEB-INF/classes. Nosaltres optarem per deixar els fitxers compil·lats *.class, no pas els fitxers font, i així utilitzarem JCreator per depurar el codi. Si us interessa que Resin compil·li el codi -insistim no és la millor opció-, li ho heu de dir en el fitxer resin.conf. Busqueu aquesta expressió a c:/resin-2.x.x/conf/resin.conf: <classpath id='WEB-INF/classes' source='WEB-INF/classes' compile='false'/> i, a l'opció compile, poseu-hi 'true'.

   
  Una pàgina web que executa Java Beans:
   

Programar JSP és una manera particular de programar Java. Malgrat que els IDEs ja van incorporant poc a poc eines per a la seva gestió, encara no existeix l'eina ideal que integri una mica de disseny de pàgines web, creació de programes de suport i depuració del conjunt pàgina JSP-Java Bean. Darrerament, però, els IDEs extensibles ja comencen a integrar eines per a la depuració de servlets i JSP -el projecte Eclipse disposa, en el moment d'escriure aquestes línies, de tres plugins per crear i depurar projectes Resin-.

Nosaltres crearem amb el nostre JCreator un projecte nou anomenat "Biblioteca", que ens deixarà el codi compilat a la carpeta /WEB-INF/classes corresponent. D'aquesta forma el cicle de creació-depuració-publicació se simplificarà bastant.

Fem el projecte per als programes de la nostra biblioteca virtual:

  • Obrim JCreator. Fem File | New... | Empty project. Al projecte li posem de nom "Biblioteca" i la localització a c:/biblioteca/WEB-INF/. Així desem el fitxeret de projecte al magatzem de recursos de l'aplicació i no es perd pel disc dur.

  • Ara obrim Project | Project Settings i comprovem que l'"Output Path" correspon a c:/biblioteca/WEB-INF/classes. Si no és així, el seleccionem. Si la carpeta no existeix al nostre disc dur, la creem i després la seleccionem. D'aquesta forma, quan compilem els programes, JCreator ens deixarà els fitxers .class allà on el servidor Resin els espera.

  • Creem el directori c:/biblioteca/WEB-INF/src, que serà el lloc on desarem els fitxers font *.java.

Ja estem a punt per a escriure codi.

Com que una biblioteca emmagatzema llibres, sembla evident que el primer que hem de fer és crear un objecte llibre. Ho farem à la Java Bean:

Amb l'expert de classes de JCreator escriviu una nova classe amb el nom Llibre i al fitxer Llibre.java, que residirà a c:/biblioteca/WEB-INF/src. El codi és aquest, observeu-ne els comentaris per a endevinar com és l'arquitectura mínima d'un Java Bean:

   
 

/**
*
* Llibre conté la informació que descriu un llibre.
* Cadascun dels atributs privats correspon a un camp de la
* taula Llibres a la nostra base de dades.
*
*/

public class Llibre {

/*
* Observeu que tots els atributs d'un Bean són privats. El Bean és
* una caixa fosca. Només publiquem els atributs que ens interessen
* els mètodes get() i set()
*/


    private int id;
    private String autor;
    private String titol;
    private String editorial;
    private String data;
    private boolean enprestec;

/*
* Aquí tenim el constructor per defecte. En un Bean el constructor
* no rep mai paràmetres d'entrada. Així qualsevol programa que
* utilitzi Beans sap que els podrà instanciar sense paràmetres
*/


    public Llibre() {
    }

/*
* aquí va tota la llista de mètodes set() (setters)
* Els set ens serveixen per assignar valor als atributs d'un Bean.
* Els IDES disposen d'eines per a crear grups get() i set()
* automàticament per a tots els atributs privats dels Beans.
* El nostre JCreator només ho fa en la versió de pagament. (uns 30€)
*/


    public void setId (int id) {
        this.id = id;
    }

    public void setAutor (String autor) {
        this.autor = autor;
    }

    public void setTitol (String titol) {
        this.titol = titol;
    }

    public void setEditorial (String editorial) {
        this.editorial = editorial;
    }

    public void setData (String data) {
        this.data = data;
    }

    public void setEnprestec (boolean enprestec) {
        this.enprestec = enprestec;
    }

/*
I aquí tota la llista de mètodes get() (getters).
* els get() ens serveixen per saber el valor dels atributs
*
*/

    public int getId () {
        return (this.id);
    }

    public String getAutor () {
        return (this.autor);
    }

    public String getTitol () {
        return (this.titol);
    }


    public String getEditorial () {
        return (this.editorial);
    }

    public String getData () {
        return (this.data);
    }

    public boolean getEnprestec () {
        return (this.enprestec);
    }

}

   
 

Compilem el codi i, si tot ha sortit bé, comprovem que tenim un fitxer Llibres.java a c:/biblioteca/WEB-INF/src i un fitxer Llibres.class a c:/biblioteca/WEB-INF/classes. Ara tothom que parli Java ja sap com és un llibre.

La pàgina que farem ens ha de donar la llista de llibres que hi ha a la nostra base de dades. Ara farem el nucli del programa, una aplicació que connecta amb la base de dades llibres.mdb i que, quan li ho demanem, ens tornarà una matriu d'objectes "Llibre" ordenats alfabèticament. Aquesta matriu és la llista que sortirà a la nostra pàgina web.

Escriviu el programa GestioLlibres.java a c:/biblioteca/WEB-INF/src. Compileu-lo a l'acabar:

   
 

import java.sql.*;

public class GestioLlibres {

    private Connection connexio;

    public GestioLlibres() throws SQLException,
                                  ClassNotFoundException {
        String Urldades = "jdbc:odbc:biblioteca";
        String usuari = "";
        String clau = "";
            try {
                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                this.connexio =
                         DriverManager.getConnection(Urldades,"","");
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
    }

/*
* Amb enprestec indiquem si volem la llista de tots els llibres
* de la biblioteca o només els que estan en préstec
* true - Només els que estan en préstec.
* false - tots els llibres
*/

    public Llibre[] getLlibres( boolean enprestec ) {

        // un vector és una llista que pot rebre qualsevol objecte
        // crearem un vector per a posar-lo la llista de llibres

        java.util.Vector v = new java.util.Vector();

            try {
                Statement pregunta = connexio.createStatement();
                ResultSet resposta = null;
                // Aquí decidim si li demanem a la taula tots els
                // llibres o només els que estan en préstec.

                    if (enprestec) {
                        resposta=pregunta.executeQuery("select * "+
                                                       "from "+
                                                       "Llibres "+
                                                       "where "+
                                                       "enprestec "+
                                                       "order by "+
                                                       "titol");
                    } else {
                        resposta=pregunta.executeQuery("select * "+
                                                       "from "+
                                                       "Llibres "+
                                                       "order by "+
                                                       "titol");
                    }
                // Definim un objecte llibre per tal de
                // carregar les dades de la base de dades.

                Llibre unllibre = null;

                    while (resposta.next()) {
                        unllibre = new Llibre();
                        unllibre.setId(resposta.getInt("id"));
                        unllibre.setAutor(
                                        resposta.getString("autor"));
                        unllibre.setEditorial(
                                    resposta.getString("editorial"));
                        unllibre.setTitol(
                                        resposta.getString("titol"));
                        unllibre.setEnprestec(
                                   resposta.getBoolean("enprestec"));
                        // Afegim el llibre al vector
                        v.add(unllibre);
                    }

                pregunta.close();
                connexio.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }

        // Ara que sabem el nombre de registres que ha de tenir
        // ja podem crear la matriu de llibres

        Llibre[] totsllibres = new Llibre[v.size()];

        // Omplim la matriu de llibres amb el contingut del vector
        // d'objectes Llibre. Atenció: s'ha de fer casting!! per
        // dir-li al compilador quin tipus d'objecte conté el
        // vector

            for (int n=0; n<v.size(); n++) {
                totsllibres[n]=(Llibre)v.get(n);
            }

        return totsllibres;
    }

}

   
 

Pràcticament, ja està feta tota la feina. A la pàgina JSP li quedarà molt poc a fer i el seu aspecte serà molt senzill.

Com s'ho fa la pàgina JSP per activar els programes Java i accedir a la seva informació?. A través de l'acció <jsp:useBean. Observeu i escriviu el codi de la pàgina web amb l'inventari de llibres de la nostra biblioteca. Poseu-li de nom llibres.jsp i deixeu-lo a la carpeta c:/biblioteca:

   
 

<jsp:useBean id="biblioteca" scope="page" class="GestioLlibres"/>
<%
Llibre[] elsllibres = biblioteca.getLlibres(false);
%>

<html>

<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body bgcolor="#FFFFFF" text="#000000">
<p align="center"><font face="Arial, Helvetica, sans-serif" size="2"><b>LLISTA DE LLIBRES DISPONIBLES A LA BIBLIOTECA</b>
</font></p>
<p>&nbsp;</p>
<% if (elsllibres!=null) for (int n=0; n<elsllibres.length; n++) { %>
  <%=elsllibres[n].getAutor()%>;<b><%=elsllibres[n].getTitol()%></b>
 <br>
<% } %>
</body>

</html>

   
  Si no hem fet errades, a l'engegar Resin i cridar http://localhost/llibres.jsp obtindrem la següent llista de llibres:
   
 
   
 

Què hem fet?

  • La clau rau a l' expressió que hem posat a dalt de tot de la pàgina JSP:

    <jsp:useBean id="biblioteca" scope="page" class="GestioLlibres"/>

    Amb aquesta
    expressió li hem dit al servidor que busqui la classe GestioLlibres a /WEB-INF/classes, que en crei una instància, que li posi de nom "biblioteca" i que l'abast d'aquest programa es circumscrigui a la pàgina actual.

    Al crear la
    instància de GestioLlibres, la connexió amb la base de dades s'ha fet automàticament, perquè s'ha executat el codi que hi ha en el mètode constructor de la classe GestioLlibres().
  • Més avall li demanem al nostre Java Bean, que, per la pàgina, és conegut amb el nom de "biblioteca", que ens retorni la llista de llibres que hi ha a la base de dades:

            <%
               Llibre[] elsllibres = biblioteca.getLlibres(false);
            %>

    Declaro una matriu de llibres, Llibre[], després la carrego amb el mètode getLlibres()del programa. El paràmetre és false perquè no vull que em filtri els llibres que són en préstec.

  • Finalment em creo un scriptlet que em vagi construïnt el llistat a la pàgina web:

    <% if (elsllibres!=null) for (int n=0; n<elsllibres.length; n++) { %>
        <%=elsllibres[n].getAutor()%>;
        <b><%=elsllibres[n].getTitol()%></b><br>
    <% } %>

En aquest moment podem aprofitar els nostres esforços i construir la pàgina JSP que ens llistarà els llibres que són en préstec.

Ja no hem de codificar res, només hem de copiar el contingut de la pàgina llibres.jsp i desar-lo en un altre fitxer que es digui enprestec.jsp i també posar-lo a c:/biblioteca

L'únic canvi que ens cal fer a la pàgina és el títol i el paràmetre que li passem a biblioteca.getLlibres().

En lloc d'escriure

Llibre[] elsllibres = biblioteca.getLlibres(false)

escriurem

Llibre[] elsllibres = biblioteca.getLlibres(true);

Engeguem Resin i anem a http://localhost/enprestec.jsp. El resultat ha de ser aquest:

   
 

A la pràctica següent aprendrem a aprofitar les capacitats de rebre i enviar informació de les pàgines web per tal de fer actualitzacions a la nostra base de dades.

   
   
   
 
Amunt