wiki:itmill
Last modified 7 years ago Last modified on 2011-05-12 08:48:57

Dynaamisten sovellusten kehittäminen Javalla IT Mill Toolkitin avulla

Nykyisin (2011) Vaadin

Tältä sivulta löydät ohjeita web-sovelluksen kehittämiseen ilmaista IT Mill Toolkit -kirjastoa käyttäen. Kirjasto on tarkoitettu dynaamisten web-sovellusten kehittämiseen käyttäen pelkkää Javaa.

0. Tiedot

Artikkelin on kirjoittanut kokonaisuudessaan Antoine Kalmbach. Kysymyksiä, ruusuja ja risuja voi lähettää osoitteeseen antoine.kalmbach@….

1. Johdanto

1.1 Mikä 'Toolkit'?

Suomalaisen IT Millin kehittämä IT Mill Toolkit tarjoaa niin kehittyneelle kuin vasta-aloittelevalle ohjelmoijalle yksinkertaisen tavan toteuttaa dynaamisia ja interaktiivisia web-sovelluksia. Lähtökohta on, että ohjelmoija kirjoittaa ohjelman rungon Java-koodina, jonka Toolkit muuntaa mm. JavaScriptiksi ja XHTML:ksi.

Toolkitin avulla on mahdollista kirjoittaa web-sovelluksia samalla tavalla kuin kirjoittaisi Swing- tai AWT-sovelluksia normaalissa Java-kehitysympäristössä. Käyttäjältä ei edellytetä HTML:n tuntemusta, Toolkit hoitaa ulkoasun varsinaisen toteutuksen (so. HTML:n ja JavaScript) käyttäjän huomaamatta: käyttäjän kirjoittama Java-koodi muuntuu monimutkaisten prosessien kautta sellaiseksi, että selain ymmärtää sen.

1.2 Miksi 'Toolkit'?

Dynaamisia Web-sovelluksia kehitettäessä käyttäjän vastuulle jää sekä ulkoasun että sisäisen (palvelinpuolen) suunnittelu ja toteutus. Kun ohjelmistot laajenevat, monimutkaistuvat ulkoasu ja varsinainen toiminnallisuus. Varsinainen toiminnallisuus, esimerkiksi JSP:llä toteutettu ohjelma, joka on vastuussa tiedonkeruusta, on hyvä erottaa ulkoasusta HTML.

Kun ohjelman ulkoasu edellyttää tietynlaisten (ja vain tietynlaisten) tietojen näkymistä, tietojen tulostumisesta vastaava ohjelma (esim. JSP-pätkä tai servletti) on vastuussa ulkoasun varsinaisesta tulostamisesta. Ohjelma siis generoi ulkoasun, jolloin muutettaessa ulkoasua, joudutaan muuttamaan itse ohjelmaa. Usein ohjelman vastuualueena on moni muukin asia kuin pelkkä ulkoasusta huolehtiminen, esimerkiksi tiedonkeruu ja -hallinta. Sivumalli (nk. 'template') on lähestymistapa, jossa ulkoasu on tallenettu suoraan mallina: malli sisältää tietueiden paikat HTML-dokumentissa, johon varsinainen dynaaminen sovellus (JSP, PHP tai muu) syöttää tiedot. Näin siis mallia muokattaessa muuttuu vain ja ainoastaan ulkoasu, mutta sovelluksen toiminta säilyy ennallaan.

1.3 Toolkitin toimintaperiaate

IT Mill Toolkit -kirjasto tarjoaa yksinkertaisen lähestymistavan ulkoasun eristämiselle: sen sijaan, että käyttäjä on vastuussa monimutkaisen HTML-koodin (yms.) tulostamisesta, kirjasto huolehtii siitä käyttäjän puolesta. Kirjasto muuttaa käyttäjän kirjoittaman Java-koodin suoraan vahvaksi ja dynaamiseksi JavaScript- ja HTML-koodiksi, jolloin käyttäjältä ei edellytetä HTML-tuntemusta miltei ollenkaan.

Toolkitin pohjalla piilee Googlen kehittämä Google Web Toolkit, jonka toimintaperiaate on sama: Java-koodin muuntaminen JavaScriptiksi selaimelle. IT Mill Toolkit kehittää ja parantaa tätä lähestymistapaa muokkaamalla Google Web Toolkitin tarjoamia komponentteja, nk. 'widgettejä'.

1.4 Toolkit toiminnassa

Toolkitin avulla on mahdollista toteuttaa erittäin dynaamisia ja interaktiivisa sovelluksia, joiden toteuttaminen perinteisin keinoin (generoimalla ulkoasu JSP:llä) on hyvin monimutkaista.

[kuvakaappaus esimerkkiohjelmasta] Kuva 1. Yksinkertaisen kerhon jäsenrekisterin toteutus

2. Toolkitin asentaminen

Jotta voit asentaa Toolkitin Eclipseen ja käyttää Toolkitia sovellusten kehittelyssä, vaaditaan sovellusympäristöltä seuraavaa:

  • Eclipse Ganymede ja Java EE
  • Apache Tomcat (väh. vers. 5.0)

Jos olet tehnyt JSP-kurssilla sovelluksia, näiden vaatimusten pitäisi täyttyä.

2.1 Asennus

2.1.1 Lataaminen

  1. Hae Toolkit osoitteesta http://www.itmill.com/downloads/itmill-toolkit.htm
  2. Pura arkisto kiintolevylle

Nyt kun sinulla on Toolkit kiintolevyllä, siirrytään seuraavaan vaiheeseen eli projektin luontiin ja testaamiseen.

2.1.2 Projektin luonti

  1. Luo uusi Dynamic Web Project (File->New->Dynamic Web Project)
  2. Anna projektille nimeksi OsoiteKirja?
  3. Valitse Target Runtime -kohtaan Apache Tomcat.
  4. Mikäli Apache Tomcatia ei ole listassa, valitse se New-nappia painamalle.
  5. Jos Tomcatia ei löydy avautuneesta ikkunasta, laita ruksi kohtaan Create a local server ja paina Next. Valitse Tomcatin asennushakemisto ja paina Finish.
  6. Paina Finish


Kuva 2. Projektin luonti

Nyt sinulla pitäisi olla projekti valmiina. Seuraavaksi tuodaan Toolkit projektiin ja tehdään testiajo.

2.1.3 Toolkitin tuonti projektiin

  1. Valitse projektistasi kansio WebContent?/WEB-INF/lib ja valitse Import. Valitse General -> File System.


Kuva 3. Tuonti

  1. Etsi Toolkitin asennushakemistosta kansio lib ja valitse tiedosto itmill-toolkit-5.3.1.jar.
  2. Paina Finish.


Kuva 4. Tuonti, vaihe kaksi: JAR-tiedoston tuonti


  1. Nyt sinulla pitäisi olla jar-tiedosto lib-kansiossa kuvan 5 mukaisesti.


Kuva 5. Tuotu JAR-tiedosto

Toolkit on tuotu projektiin, varmistetaan että se on konfiguroitu oikein katsomalla onko se tuotu myös projektiasetuksiin.

  1. Project->Properties->Java Build Path->Libraries. Valitse kohta Web App Libraries. Jar-tiedoston pitäisi löytyä sieltä. Jos tiedosto puuttuu, palaa kohtaan 1.


Nyt JAR-tiedosto on tuotu projektiin ja testiohjelma on mahdollista toteuttaa. Seuraavaksi luomme esimerkkiohjelman ja alustusparametrit palvelimelle.

2.1.4 Ohjelman luonti

Kaikki Toolkitilla tehdyt ohjelmat perivät Toolkit-kirjaston Application-luokan, joka on kirjastossa määritelty eräänlaiseksi servletin johdannaiseksi. Tehtäessä ohjelmia emme siis luo uusia servlettejä, vaan perimme Application-luokkaa.

  1. Valitse projektista hakemisto src ja valitse Class.
  2. Valitse paketiksi (package) kerho ja luokan nimeksi OsoiteKirjaApplication?.
  3. Isäntäluokaksi peritään luokka Application, jonka osoite on com.itmill.toolkit.Application.
  4. Paina Finish ja Eclipse luo uuden luokan sinulle.


Kuva 6. Luokan luonti

Syntyneen koodin pitäisi näyttää tältä:

package kerho;

import com.itmill.toolkit.Application;

public class OsoiteKirjaApplication extends Application {
    @Override
    public void init() {
		// TODO Auto-generated method stub
    }
}

Muokkaa init()-metodia seuraavasti:

public void init() {
    Window mainWindow = new Window("Kerhon osoitekirja");
    mainWindow.addComponent(new Label("Hello World!"));
    setMainWindow(mainWindow);
}

Luodessasi muuttujia Eclipse valittaa, että kyseisiä luokkia ei ole tuotu (punainen alleviivaus). Luokkien nimien kohdalla paina Ctrl-1 ja valitse 'com.itmill.toolkit.ui.Luokka' ja paina Enter.

Nyt ohjelma on valmis suoritettavaksi, seuraavaksi konfiguroidaan palvelin ajamaan projekti.

2.1.5 Ohjelman ajo

Ohjelman ajamiseksi täytyy muokata web.xml-tiedostoa, joka sisältää web-ohjelman ajo-ohjeet Tomcatille. Avaa web.xml kansiosta WebContent?/WEB-INF ja muuta kaikki sen sisältö seuraavaksi:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
  <display-name>OsoiteKirja</display-name>
  <servlet>
    <servlet-name>OsoiteKirja</servlet-name>
    <servlet-class>
        com.itmill.toolkit.terminal.gwt.server.ApplicationServlet
    </servlet-class>
    <init-param>
      <param-name>application</param-name>
      <param-value>kerho.OsoiteKirjaApplication</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>OsoiteKirja</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

Seuraavaksi valitaan Eclipsen pääikkunan alaosan valikosta sivu Servers.

  1. Mikäli Tomcat löytyy listasta (ks. kuva 7), niin avautuvasta valikosta valitse Add and Remove projects....
  2. Jos Tomcatia ei löydy listasta, lisää se kuvan 8 mukaisesti ja toimi edellisen kohdan mukaisesti. Valitse listasta Tomcat.
  3. Lisää projekti palvelimelle painamalla Add.


Kuva 7. Projektin siirto palvelimelle


Kuva 8. Palvelimen lisääminen


Kuva 9. Projekti on palvelimella'

4. Ohjelman ajaminen. Valitse samalta sivulta Tomcat-palvelin ja oikeasta laidasta paina Debug.


Kuva 10. Palvelimen käynnistäminen

Palvelin on nyt käynnistetty. Avaa selain ja mene osoitteeseen http://localhost:8080/OsoiteKirja (Huom. Palvelimen portti (:8080) saattaa riippua määrittelemästäsi porttiasetuksesta!).

Jos teit kaiken ohjeiden mukaisesti, pitäisi avautua seuraavanlainen näkymä:


Kuva 11. Sivu toiminnassa

Nyt Toolkit on valmis käytettäväksi.

2.2 Huomioitavaa

Tehdessäsi projektiin muutoksia, esimerkiksi koodiin tai muuhun, projekti l. sovellus pitää julkaista palvelimelle. Jos automaattinen julkaiseminen (Project->Build Automatically) on päällä, muuta ei tarvitse tehdä kuin käynnistää palvelin uudelleen. Jos kyseinen ominaisuus on pois päältä, projekti on aina rakennettavava (Build), painamalla Ctrl+B. Palvelinlistassa alhaalla projektin kohdalla lukee julkaisun jälkeen 'Republish', joka tarkoittaa, että projekti on julkaistu palvelimelle onnistuneesti. Käynnistä palvelin uudestaan ja päivitä sivu selaimessa.

3. Esimerkkiohjelma: Kerhon osoitekirja

Tavoitteenamme on luoda täysiverinen kerhon osoitekirja. Osoitekirjan tulee täyttää seuraavat vaatimukset:

  • Jäsenistä tallennetaan seuraavat tiedot: nimi, sähköpostiosoite, syntymäaika ja henkilötunnus
  • Jäsenien lisäys, poisto ja muokkaus
  • Tietojen oikeellisuuden varmistaminen (Henkilötunnukseksi ei voi antaa esim. 'Esko Aho')

Esimerkkiohjelma, jonka rakennamme tässä vaiheessa, tulee näyttämään täältä:

(kuva osoitekirjasta)

3.1. KerhoMember?-luokka

Ensiksi luomme luokan, jota käytämme ohjelmassa. Luokka kuvastaa yksittäistä kerhon jäsentä. Luo uusi luokka ja anna sen nimeksi KerhoMember?. Tiedoston sisällöksi tulee seuraava:

package kerho;

import java.util.Date;

public class KerhoMember {
    private String nimi;
    private String sähköpostiosoite;
    private Date syntymäaika;
    private String henkilötunnus;

    public KerhoMember() {
        // Alustetaan kaikki tyhjiksi
        nimi = sähköpostiosoite = henkilötunnus = "";
    }

    ++ getterit ja setterit joka metodille
}

Nk. getterit ja setterit, esimerkiksi getNimi() ja setNimi(s), on helppo luoda automaattisesti Eclipsellä: valitse muuttuja ja paina Alt-Ctrl-S, valitse Generate getters and setters. Avautuvasta ikkunasta ruksaa kaikki ja laita paikaksi (Insertion point) "After henkilötunnus".

3.2 Käyttöliittymä

Luodaan käyttöliittymää ympäröivä valkoinen ruuutu käyttämällä Panel-luokkaa. Lisää seuraava koodi init()-metodin perään OsoiteKirjaApplication?-luokkaan:

        Panel panel = new Panel("Kerhon osoitekirja");
        mainWindow.addComponent(panel);

Seuraavaksi tarvitsemme lomakkeen (Form), johon voimme syöttää lisättävien jäsenten tietoja. Form-luokan ominaisuuksiin kuuluu kyky ottaa parametriksi mikä tahansa luokka ja luoda lomakkeen tietueet luokan jäsenattribuuttien perusteella. Ohjelmoijan työksi jää luokan toteuttaminen, jonka toteutimme juuri äsken. Koska lomakkeelle on annettava luokka parametriksi, lisää ohjelmaluokkaan uusi KerhoMember?-luokan muuttuja currentMember, jonka näkyvyys on yksityinen (private).

Jotta lomake osaisi käyttää kyseistä luokkaa, on sille rakennettava nk. bean-muuntaja. Bean-muuntaja ottaa parametriksi yksinkertaisen luokan, joka tunnetaan myös toiselta nimeltään POJO (Plain Old Java Object). POJO ei sisällä mitään metodeja (pl. muodostin), vain jäsenmuuttujia. KerhoMember?-luokka on siis eräs tapa toteuttaa POJO.

Bean-muuntajan luonti onnistuu seuraavasti:

        currentMember = new KerhoMember();
        BeanItem memberBean = new BeanItem(currentMember);

Luodaan lomake ja rekisteröidään sille annettu bean. Lisää ohjelmaluokkaan Form-luokan attribuutti editForm. init()-metodiin lisää seuraavat rivit:

        editForm = new Form();
        editForm.setCaption("Henkilöiden muokkaaminen");
        editForm.setItemDataSource(memberBean);

Nyt lomakkeessa on tietueet luotu valmiina, mutta painikkeet puuttuvat. Lisää ohjelmaluokkaan neljä Button-luokan muuttujaa, addButton, saveButton, deleteButton ja resetButton. Painikkeet lisätään lomakkeeseen seuraavasti:

        addButton = new Button("Lisää");
        editButton = new Button("Muokkaa");
        deleteButton = new Button("Poista");
        resetButton = new Button("Tyhjennä");
        editForm.getFooter().addComponent(addButton);
        editForm.getFooter().addComponent(editButton);
        editForm.getFooter().addComponent(deleteButton);

Ohjelman pitäisi nyt näyttää kutakuinkin tältä:

public class OsoiteKirjaApplication extends Application {
    private Window mainWindow;
    private Button addButton, saveButton, deleteButton, resetButton;
    private Form editForm;
    private KerhoMember currentMember;
    
    public void init() {
        mainWindow = new Window("Kerhon osoitekirja");
        setMainWindow(mainWindow);
        
        Panel panel = new Panel("Kerhon osoitekirja");
        mainWindow.addComponent(panel);
        
        currentMember = new KerhoMember();
        BeanItem memberBean = new BeanItem(currentMember);
        
        editForm = new Form();
        editForm.setCaption("Henkilöiden muokkaaminen");
        editForm.setItemDataSource(memberBean);
        
        addButton = new Button("Lisää");
        saveButton = new Button("Tallenna");
        deleteButton = new Button("Poista");
        resetButton = new Button("Tyhjennä");
        editForm.getFooter().addComponent(addButton);
        editForm.getFooter().addComponent(saveButton);
        editForm.getFooter().addComponent(deleteButton);
        editForm.getFooter().addComponent(resetButton);
        
        panel.addComponent(editForm);
    }
}

Kuten huomataan, ilmestyi paneeliin lomake. Tietueet ovat kuitenkin väärässä järjestyksessä, mutta tämän korjaaminen on yksinkertaista. Tee luokkaan jäsenmuuttuja ord, joka on tyyppiä Vector<String> ja lisää init()-metodiin seuraava koodi:

        ord = new Vector<String>();
        ord.add("nimi");
        ord.add("henkilötunnus");
        ord.add("syntymäaika");
        ord.add("sähköpostiosoite");
        editForm.setVisibleItemProperties(ord);

Nyt tietueet ovat kauniissa aakkosjärjestyksessä kuvan 12 mukaisesti.


Kuva 12. Ohjelma ajettuna

3.3 Tietojen varastointi

Osoitekirjassa käytetään tietojen tallentamiseen taulukkoa. Taulukko kuvastaa tietokantaa, johon uudet ja vanhat jäsenet tallennetaan. Toolkitissa on tähänkin valmis komponentti, Table.

3.3.1 Taulukon luonti

Suuri osa toolkitin komponenenteista noudattaa nk. tietomallia (engl. data model). Esimerkkiohjelmassa tämä tarkoittaa lomaketta, joka ottaa tietueiden nimet ja arvot objekteista (POJO), niin ettei ohjelmoijan tarvitse itse huolehtia komponenttien ulkoasusta.

Table ei tässäkään tee poikkeusta. Table sisältää ns. containerin, johon tallentuvat kaikki sen tiedot. Tähän voi käyttää BeanItemContainer?-luokkaa, joka ei vielä ole mukana varsinaisessa Toolkitin versiossa, se löytyy tiedostosta BeanItemContainer?.java, joka löytyy sivun lopusta. Tuo luokka projektiin ja luokka on valmis käytettäväksi.

package kerho;
import com.itmill.toolkit.data.util.BeanItemContainer;

public class MemberContainer extends BeanItemContainer<KerhoMember> {
      public MemberContainer() throws InstantiationException, IllegalAccessException {
            super(KerhoMember.class);
      }
}

Kyseinen koodinpätkä perii BeanItemContainer?-luokan, antaen sille tyyppiparametriksi KerhoMember?. Luokka on nyt valmis käytettäväksi taulukossa. Muokataan OsoiteKirjaApplication?-luokkaa ja lisätään siihen seuraava attribuutti getterin kanssa:

    private MemberContainer container;
    
    public MemberContainer getContainer() {
        return container;
    }

Seuraavaksi toteutamme oman versiomme Table-luokasta. Luo uusi luokka nimeltä MemberList?.

package kerho;

import com.itmill.toolkit.ui.Table;

public class MemberList extends Table {
    public MemberList(OsoiteKirjaApplication oka) {
        setSizeFull();
        setContainerDataSource(oka.getContainer());
    }
}

MemberList?-luokka asettaa omaksi tietolähteekseen juuri luodun MemberList?-luokan. Seuraavaksi riittää että lisätään MemberList?-luokka ohjelmaan. Luo uusi MemberList?-luokan jäsenmuuttuja nimeltä memberTable ja lisää seuraava koodi init()-metodin loppuun.

        try {
            container = new MemberContainer();
            memberList = new MemberList(this);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        
        panel.addComponent(memberList);

Seuraavaksi aja ohjelma. Nyt sivulle on ilmestynyt taulukko, johon ei toistaiseksi voi lisätä mitään. Seuraavassa osassa muokkaamme lomaketta niin, että voimme lisätä ja poistaa jäseniä taulukosta.


Kuva 13. Ohjelma käynnissä taulukoineen

3.3.2 Tietojen lisääminen taulukkoon

Painikkeiden toiminta on oleellista ohjelman toiminnalle. Button-luokassa on nk. event listener -ominaisuus, mikä tarkoittaa kutakuinkin sitä, että nappia painettaessa kutsutaan ennalta määriteltyä toimintoa. Metodit rekisteröidään jokaiselle painikkeelle erikseen.

Esimerkkiohjelmassa ja Toolkitissa edellämainittu toteutetaan seuraavasti:

  1. Toteutetaan interface Button.ClickListener
  2. Toteutetaan interfacen määräämä buttonClick()-metodi.

buttonClick-metodi voisi näyttää seuraavalta:

    public void buttonClick(ClickEvent event) {
        Button source = event.getButton();
        
        if (source == addButton) {
            // Painettiin addButtonia
        }
    }

Toimi siis askelten 1. ja 2. mukaisesti: muokkaa ohjelmaluokan määrittelyä seuraavasti:

public class OsoiteKirjaApplication extends Application implements Button.ClickListener {

Nyt Eclipse valittaa, että ei buttonClick-metodia ei ole toteutettu. Paina Ctrl-1 ja Eclipse generoi metodin. Jäsenene lisääminen taulukkoon tapahtuu seuraavasti:

  1. Koska Form-luokka käyttää tietorakeenteenaan currentMember-muuttujaa, se varastoi tiedot sinne.
  2. Lisättäessä taulukkoon uusia rivejä haetaan currentMember-muuttujasta tiedot ja generoidaan uusi rivi taulukkoon.

Muokkaa buttonClick-metodia seuraavasti:

public void buttonClick(ClickEvent event) {
        Button source = event.getButton();
        
        if (source == addButton) {
            KerhoMember newMember = new KerhoMember();
            editForm.setItemDataSource(new BeanItem(newMember));
        } else if (source == resetButton) {
            editForm.discard();
            editForm.setItemDataSource(null);
        }
    }

Rekisteröidään napinpainallus event listeneriin (seuraava koodi init-metodiin):

        addButton.addListener((Button.ClickListener) this);
        deleteButton.addListener((Button.ClickListener) this);
        saveButton.addListener((Button.ClickListener) this);
        resetButton.addListener((Button.ClickListener) this);

Nyt kun painat Tyhjennä-nappia, katoaa lomake tyystin ja tulee takaisin kun painat Lisää. Seuraavaksi toteutetaan tiedon lisäys Tallenna-napista. Muokkaa buttonClick-metodia:

    public void buttonClick(ClickEvent event) {
        Button source = event.getButton();
        if (source == addButton) {
            currentMember = new KerhoMember();
            editForm.setItemDataSource(new BeanItem(currentMember));
            editForm.setVisibleItemProperties(ord);
        } else if (source == saveButton) {
            KerhoMember newMember = new KerhoMember();
            newMember.setNimi(currentMember.getNimi());
            newMember.setSähköpostiosoite(currentMember.getSähköpostiosoite());
            newMember.setHenkilötunnus(currentMember.getHenkilötunnus());
            newMember.setSyntymäaika(currentMember.getSyntymäaika());
            container.addBeanItem(newMember);
            currentMember = new KerhoMember();
            editForm.setItemDataSource(null);
        } else if (source == resetButton) {
            editForm.discard();
            editForm.setItemDataSource(null);
        }
    }

Kokeile ohjelmaa ja henkilöiden lisäystä.


Kuva 14. Henkilöiden lisäys

3.3.3 Taulukkorivien valitseminen

Valitaksemme taulukosta rivejä täytyy Table-oliolle antaa Propery.ValueChangeListener event listener. Muokkaa ohjelmaluokan koodia seuraavasti:

public class OsoiteKirjaApplication extends Application implements Button.ClickListener, Property.ValueChangeListener {

Nyt ohjelman loppuun pitäisi ilmestyä valueChange-metodi. Toistaiseksi mitään ei tapahdu, sillä taulukkoa ei ole asetettu reagoimaan valintoihin. Lisää seuraava koodi MemberList?-luokan muodostimen loppuun:

            setSelectable(true);
            setImmediate(true);
            addListener((Property.ValueChangeListener) app);
            setNullSelectionAllowed(false);

Nyt muokkaa ohjelman valueChange-metodia:

    public void valueChange(ValueChangeEvent event) {
        Property prop = event.getProperty();
        if (prop == memberList) {
            Item item = memberList.getItem(memberList.getValue());
            editForm.setItemDataSource(item);
        }
    }

Nyt kun ajat ohjelman, painamalla listasta nimeä voit muokata sitä ja tallenna-nappia painamalla tiedot tallentuvat listaan. Poiston toteuttaminen ei ole sen monimutkaisempaa. Muokkaa buttonClick-metodia:

    public void buttonClick(ClickEvent event) {
        Button source = event.getButton();
        
        [Entiset else/if rakenteet]
        
        else if (source == deleteButton) {
            memberList.removeItem(memberList.getValue());
            editForm.discard();
            editForm.setItemDataSource(null);
        }
    }

3.4 Tiedon oikeellisuuden varmistus

Tällä hetkellä tietoa voi syöttää sovellukseen ihan missä muodossa vain, esimerkiksi henkilötunnukseksi voi antaa "Aku Ankka", ja tietueet voi jättää kokonaan tyhjäksi, minkä ansiosta taulukkoon voi syntyä tyhjiä rivejä. Ei-toivottu käyttötapa voidaan estää asettamalla tietueille vaatimuksia, jotka määrittelevät että niitä ei voi jättää tyhjiksi. Seuraavan koodi lisätään init-metodin loppuun:

        // Käydään joka kenttä läpi ja asetetaan vaadituksi
        for (String field : ord) {
            editForm.getField(field).setRequired(true);
            editForm.getField(field).setRequiredError("'" + field + "' on pakollinen!");
        }
        // Asetetaan lomake tarkistamaan syöte välittömästi
        // Nyt jos tietue jätetään tyhjäksi, tulee virheviesti
        editForm.setImmediate(true);
        editForm.setValidationVisible(true);

3.4.1 Syötteen tarkistus

Toolkit tarjoaa nk. validaattorin eli tarkistaja-rajapinnan tietueiden syötteiden tarkistamiseksi. Henkilötunnusta varten tarvitsemme tarkistuksen, joka antaa virheen mikäli henkilötunnus ei ole muotoa "AAAAAAXBB" jossa X on mikä tahansa merkki, A ja B numeroita. Sen kummempaa tarkistusta henkilötunnukselle ei tehdä, riittää että käyttäjä antaa 10-merkkisen merkkijonon. Tarkistaja luodaan Validator-luokalla. Jälleen, lisää koodia init()-metodiin.

        Validator hetuValidator = new Validator() {
            // Onko merkkijono
            public boolean isValid(Object value) {
                if (value == null || !(value instanceof String)) {
                    return false;
                }
                // Täsmää kuuteen numeroon, merkkiin ja kolmeen numeroon
                // Esim. 012345X123
                return ((String) value).matches("\\d{6}.\\d{3}");
            }

            // Tämä poikkeus heitetään mikäli syöte on virheellinen
            // Kutsuu edellistä metodia
            public void validate(Object value) throws InvalidValueException {
                if (!isValid(value)) {
                    throw new InvalidValueException("Virheellinen henkilötunnus!");
                }
            }
        };

        editForm.getField("henkilötunnus").addValidator(hetuValidator);


Kuva 15. Tarkistaja käynnissä. Huomaa, miten lomakkeeseen tulee myös virheviesti siitä, että nimeä ei annettu.

Lomakkeen tiedot tallentuvat taulukkoon Tallenna-nappia painettaessa. Tämä johtuu siitä, että buttonClick-metodissa ei tarkistettu oliko lomakkeessa virheitä tai ei. Muokataan metodia:

         else if (source == saveButton) {
            if (editForm.isValid()) {
                KerhoMember newMember = new KerhoMember();
                newMember.setNimi(currentMember.getNimi());
                newMember.setSähköpostiosoite(currentMember.getSähköpostiosoite());
                newMember.setHenkilötunnus(currentMember.getHenkilötunnus());
                newMember.setSyntymäaika(currentMember.getSyntymäaika());
                container.addBeanItem(newMember);
                currentMember = new KerhoMember();
                editForm.setItemDataSource(null);
            }
        }

Nyt painettaessa virheellisellä syötteellä Tallenna-painiketta mitään ei tapahdu. Lomake kumminkin "tuhoutuu" kun tieto tallennetaan onnistuneesti, minkä ansiosta kaikki tarkistajat katoavat tyystin. Seuraavassa luvussa korjataan asia.

3.5 MemberForm-luokan teko

Koska lomakkeen uudistus edellyttää tarkistajien uudelleenluontia joka kerralla, on fiksumpaa luoda kokonaan omatekoinen lomakeluokka, joka peritään Form-luokasta. Luo luokka MemberForm? ja peri se Form-luokasta.

package kerho;

import com.itmill.toolkit.data.Validator;
import com.itmill.toolkit.ui.Form;

public class MemberForm extends Form {
    private Validator hetuValidator;
    
    public MemberForm() {
        setCaption("Henkilöiden muokkaus");
    }
}

3.5.1 MemberFormin toiminnot

Attachments