Tworzenie aplikacji Java EE 5 z NetBeans IDE 6.0 i GlassFish v2

Z Jacek Laskowski - Wiki Projektanta Java EE

Poprzedni artykuł Tworzenie aplikacji EJB 3.0 z GlassFish v2, Apache Maven 2 i NetBeans IDE 6.0 przedstawił proces tworzenia aplikacji EJB 3.0 z kilkoma narzędziami wspierającymi tworzenie oprogramowania zgodnego ze specyfikacją Korporacyjnej Javy (Java EE 5). Artykuł uzmysłowił mi potrzebę skrócenia czasu tworzenia aplikacji korporacyjnej do niezbędnego minimum. Postanowiłem iść dalej i spróbować stworzyć aplikację Java EE korzystając wyłącznie z pomocników (ang. wizards) dostarczanych przez NetBeans IDE 6.0. Jako aplikację do utworzenia wybrałem książkę telefoniczną bazując na przykładzie zaczerpniętym z dokumentacji serwera aplikacyjnego Apache Geronimo - Very simple Entity EJB example. Celem było zminimalizowanie koniecznych modyfikacji wykonywanych manualnie na rzecz wykorzystania możliwości środowiska graficznego NetBeans IDE 6.0 oraz technologiczne uatrakcyjnienie przykładu opisanego na wspomnianej stronie (co powinno zostać odzwierciedlone również na niej samej w kontekście użycia Apache Geronimo).

Nazewnictwo poszczególnych klas zostało zaczerpnięte z Wikipedii pod pozycją Telephone directory.

Spis treści

Oprogramowanie

Środowisko składa się z następujących narzędzi:

Zakłada się, że powyższe oprogramowanie jest zainstalowane i działa poprawnie. Instalacja oprogramowania sprowadza się do pobrania i rozpakowania paczek w wybranym katalogu.

Kompletny projekt do zaimportowania do NetBeans IDE 6.0 dostępny jest jako javaee-phonebook.zip.

Utworzenie projektu aplikacji korporacyjnej - Phonebook

Rozpoczynamy od utworzenia nowego projektu aplikacji korporacyjnej korzystając z menu File > New Project... (bądź alternatywnie: Ctrl+Shift+N) i wybieramy kategorię Enterprise, gdzie z kolei wybieramy Enterprise Application.

Grafika:javaee-netbeans6-chooseproject.PNG

Zatwierdzamy wybór przyciskiem Next >.

W okienku dialogowym New Enterprise Application w polu Project Name wpisujemy Phonebook.

Grafika:javaee-netbeans6-nameandlocation.PNG

Definicja serwera aplikacyjnego GlassFish v2 w NetBeans IDE

Wybieramy przycisk Add przy polu Server i w oknie dialogowym Add Server Instance wybieramy GlassFish V2.

Grafika:javaee-netbeans6-chooseserver.PNG

Wciskamy przycisk Next >.

W kolejnym kroku Platform Folder Location podajemy katalog domowy serwera - pole Platform Location, np. c:\apps\glassfish.

Grafika:javaee-netbeans6-platformlocation.PNG

Wciskamy przycisk Next >.

Podajemy dane uwierzytelniające użytkownika z prawami administracyjnymi (domyślnie admin/adminadmin)

Grafika:javaee-netbeans6-domainadminlogininfo.PNG

i kończymy proces wybierając przycisk Finish.

Na zakończenie powinniśmy otrzymać okienko dialogowe z wypełnionymi wszystkimi obowiązkowymi polami, m.in. Server oraz Java EE Version.

Grafika:javaee-netbeans6-newenterpriseapplicationdefined.PNG

Wciskamy przycisk Finish.

Grafika:javaee-netbeans6-projects-nojpa.PNG

Utworzenie projektu JPA - Phonebook-jpa

Poza domyślnie utworzonymi projektami dodatkowymi Phonebook-ejb oraz Phonebook-war, które składają się na naszą aplikację korporacyjną, stworzymy jeszcze jeden Phonebook-jpa zawierający encję.

Wybieramy menu File > New Project... i w okienku dialogowym wybieramy kategorię Java, w której z kolei wybieramy Java Class Library.

Grafika:javaee-netbeans6-javaclasslibrary.PNG

Wciskamy przycisk Next >.

W oknie dialogowym New Java Class Library - Name and Location wpisujemy:

  • Project Name: Phonebook-jpa
  • Project Location: katalog aplikacji korporacyjnej zdefiniowanej w poprzednim kroku (wystarczy do ścieżki w polu Project Location dodać Phonebook). Uprości to znacząco późniejszą administrację i ewentualną dystrybucję projektu aplikacji.
Grafika:javaee-netbeans6-javaclasslibrary-nameandlocation.PNG

Wciskamy przycisk Finish.

Grafika:javaee-netbeans6-projects-withjpa.PNG

Utworzenie encji - Subscriber

Do utworzenia encji Subscriber korzystamy z menu kontekstowego New > Entity Class... w projekcie Phonebook-jpa.

Grafika:javaee-netbeans6-newentityclass.PNG

W oknie dialogowym New Entity Class - Name and Location definiujemy:

  • Class Name: Subscriber
  • Package: org.apache.geronimo.samples.phonebook
Grafika:javaee-netbeans6-newentityclass-nameandlocation.PNG

Definicja jednostki utrwalania - persistence.xml

Wciskamy przycisk Create Persistence Unit..., gdzie wybieramy jdbc:derby://localhost:1527/sample [app on APP] jako Database Connection oraz Drop and Create w Table Generation Strategy.

Grafika:javaee-netbeans6-createpersistenceunit.PNG

Wciskamy przycisk Create.

Po tym kroku komunikat dotyczący braku konfiguracji JPA znika, więc wciskamy przycisk Finish.

Grafika:javaee-netbeans6-pudefined.PNG

Użycie encji w środowisku serwera aplikacyjnego Java EE 5 wymaga modyfikacji pliku persistence.xml, gdyż ten utworzony przez NetBeans IDE 6.0 zakłada użycie JPA w trybie poza serwerem.

Otwieramy plik persistence.xml, który znajduje się pod węzłem Phonebook-jpa > Source Packages > META-INF. Wybieramy widok XML (domyślnie plik prezentowany jest w widoku Design).

Grafika:javaee-netbeans6-xmlview.PNG

Modyfikujemy plik persistence.xml tak, aby zawierał następującą treść:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">
    <persistence-unit name="Phonebook-jpaPU">
        <jta-data-source>jdbc/sample</jta-data-source>
        <properties>
            <property name="toplink.ddl-generation" value="drop-and-create-tables"/>
        </properties>
    </persistence-unit>
</persistence>

Dodanie pól trwałych encji - name i phoneNumber

Do klasy encji dodajemy dwa dodatkowe pola trwałe - name oraz phoneNumber.

private String name;
private String phoneNumber;

Z menu kontekstowego klasy (prawy przycisk myszy) wybieramy Refactor > Encapsulate Fields... (jeśli w czasie wybrania menu kursor znajdował się na polu to jego metody ustawiająca i odczytująca zostaną automatycznie zaznaczone w oknie dialogowym tworzenia metod).

Grafika:javaee-netbeans6-encapsulatefields.PNG

i zaznaczamy pola przy getName, setName oraz getPhoneNumber i setPhoneNumber.

Grafika:javaee-netbeans6-gettersandsetters.PNG

Zatwierdzamy wybór przez wciśnięcie przycisku Refactor.

Definicja nazwanego zapytania - Subscriber.findAll

Zgodnie z wytycznymi odnośnie nazewnictwa zapytań nazwanych (ang. named queries) opisanych w dokumencie Using Named Queries poprzedzamy nazwę zapytania nazwą encji, do której należy, tj. Subscriber.findAll.

@NamedQuery(name = "Subscriber.findAll", query = "SELECT s FROM Subscriber s")

Komunikat błędu związany z niedostępnością typu NamedQuery rozwiązujemy przez menu kontekstowe Fix Imports (alternatywnie Ctrl+Shift+I).

Utworzenie konstruktorów encji

Dla uproszczenia pracy z encją tworzymy dodatkowy konstruktor, który przyjmuje parametry name oraz phoneNumber. Wymaganiem specyfikacji JPA jest dostępność domyślnego konstruktora bezparametrowego, więc jeśli tworzymy nowy parametryzowany konstruktor musimy również zdefiniować konstruktor bezparametrowy.

Z menu kontekstowego klasy encji (w ramach edytora klasy Subscriber.java wciskamy prawy przycisk myszy) wybieramy Insert Code... (alternatywnie Alt+Insert).

Grafika:javaee-netbeans6-insertcode.PNG

Z menu wybieramy Constructor....

Grafika:javaee-netbeans6-insertcode-constructor.PNG

W kolejnym oknie dialogowym Generate Constructor zaznaczamy pola przy name oraz phoneNumber.

Grafika:javaee-netbeans6-generateconstructor.PNG

Zatwierdzamy wciskając przycisk Generate.

Powtarzamy czynność, jednakże w oknie dialogowym Generate Constructor nie zaznaczamy żadnych pól, a jedynie wciskamy przycisk Generate (kombinacja klawiszy: Alt+Insert, Enter, Enter). W ten sposób utworzymy konstruktor bezparametrowy.

Encja Subscriber w całej okazałości

Ostatecznie nasza klasa encji Subscriber prezentuje się następująco:

package org.apache.geronimo.samples.phonebook;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;

@Entity
@NamedQuery(name = "Subscriber.findAll", query = "SELECT s FROM Subscriber s")
public class Subscriber implements Serializable {

    private static final long serialVersionUID = 1L;
    private Long id;
    private String name;
    private String phoneNumber;

    public Subscriber() {
    }

    public Subscriber(String name, String phoneNumber) {
        this.name = name;
        this.phoneNumber = phoneNumber;
    }

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

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

Utworzenie sesyjnego ziarna EJB - Phonebook

Zaznaczamy projekt Phonebook-ejb i wybieramy z menu kontekstowego (dostępnego pod prawym klawiszem myszki) New > Session Bean....

Grafika:javaee-netbeans6-newsessionbean.PNG

W okienku dialogowym New Session Bean - Name and Location wpisujemy:

  • EJB Name: Phonebook
  • Package: org.apache.geronimo.samples.phonebook
Grafika:javaee-netbeans6-ejbnameandlocation.PNG

Zatwierdzamy wciskając przycisk Finish.

Deklaracja zależności projektowej - Phonebook-jpa

Nasze ziarno EJB będzie korzystało z encji Subscriber oraz jednostki utrwalania Phonebook-jpaPU, które są dostępne w ramach projektu Phonebook-jpa. Dodajemy zależność projektu Phonebook-ejb od projektu Phonebook-jpa. Zaznaczamy węzeł Libraries w projekcie Phonebook-ejb i z menu kontekstowego wybieramy Add Project....

Grafika:javaee-netbeans6-ejbaddproject.PNG

Wskazujemy na projekt Phonebook-jpa.

Grafika:javaee-netbeans6-phonebookejb-deps.PNG

Deklaracja zarządcy encji Phonebook-jpaPU

Definiujemy pole em dla kontekstu trwałego Phonebook-jpaPU ziarna. Dodajemy poniższy kod do klasy PhonebookBean.

@PersistenceContext(unitName = "Phonebook-jpaPU")
protected EntityManager em;

Pojawi się błąd związany z niedostępnością odpowiednich deklaracji (importów) pakietów. Wybieramy z menu kontekstowego klasy (dostępnego pod prawym klawiszem myszy) Fix Imports.

Grafika:javaee-netbeans6-fiximports.PNG

Utworzenie metody biznesowej - createSubscriber

Zgodnie z komentarzem w klasie PhonebookBean

// Add business logic below. (Right-click in editor and choose
// "EJB Methods > Add Business Method" or "Web Service > Add Operation")

korzystamy z menu kontekstowego EJB Methods > Add Business Method.

Grafika:javaee-netbeans6-addbusinessmethod.PNG

W polach podajemy następujące wartości:

  • Name: createSubscriber
  • Return Type: Subscriber

i dodajemy dwa parametry wejściowe za pomocą przycisku Add.

Grafika:javaee-netbeans6-createSubscriber.PNG

Zatwierdzamy przyciskiem OK.

Wypełniamy ciało metody createSubscriber następującą treścią:

public Subscriber createSubscriber(String name, String phoneNumber) {
    Subscriber subscriber = new Subscriber(name, phoneNumber);
    em.persist(subscriber);
    return subscriber;
}

Utworzenie metody biznesowej - getSubscribers

Podobnie jak miało to miejsce w przypadku tworzenia metody createSubscriber korzystamy z menu kontekstowego EJB Methods > Add Business Method, gdzie w formatce Add Business Method... podajemy:

  • Name: getSubscribers
  • Return Type: List<Subscriber>
Grafika:javaee-netbeans6-getSubscribers.PNG

Zatwierdzamy przyciskiem OK.

Wciskamy Ctrl+Shift+I (menu kontekstowe Fix Imports), aby zlikwidować błąd związany z brakiem importu dla typu List<Subscriber>.

Grafika:javaee-netbeans6-fiximportswindow.PNG

Wciskamy przycisk OK.

Modyfikujemy treść metody getSubscribers, aby prezentowała się następująco:

public List<Subscriber> getSubscribers() {
    return (List<Subscriber>) em.createNamedQuery("Subscriber.findAll").getResultList();
}

Kończymy wybierając menu Source > Fix Code... stojąc kursorem na właśnie wprowadzonej linii (bądź alternatywnie wciskając Alt+Enter).

Grafika:javaee-netbeans6-fixcode.PNG

i wybieramy pozycję Suppress Warning - unchecked.

Przechodzimy do interfejsu lokalnego PhonebookLocal, gdzie wykonujemy Fix Imports.

PhonebookBean w całej okazałości

Klasa ziarna PhonebookBean powinna prezentować się następująco:

package org.apache.geronimo.samples.phonebook;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class PhonebookBean implements PhonebookLocal {

    @PersistenceContext(unitName = "Phonebook-jpaPU")
    protected EntityManager em;

    public Subscriber createSubscriber(String name, String phoneNumber) {
        Subscriber subscriber = new Subscriber(name, phoneNumber);
        em.persist(subscriber);
        return subscriber;
    }

    @SuppressWarnings("unchecked")
    public List<Subscriber> getSubscribers() {
        return (List<Subscriber>) em.createNamedQuery("Subscriber.findAll").getResultList();
    }
}

PhonebookLocal w całej okazałości

Lokalny interfejs biznesowy PhonebookLocal powinien prezentować się następująco:

package org.apache.geronimo.samples.phonebook;

import java.util.List;
import javax.ejb.Local;

@Local
public interface PhonebookLocal {

    Subscriber createSubscriber(String name, String phoneNumber);

    List<Subscriber> getSubscribers();
}

Dodanie biblioteki JSF do projektu Phonebook-war

Z menu kontekstowego projektu Phonebook-war (dostępnym pod prawym klawiszem myszy) wybieramy Properties.

Grafika:javaee-netbeans6-phonebook-war-properties.PNG

W panelu Project Properties - Phonebook-war wybieramy Frameworks.

Grafika:javaee-netbeans6-frameworks.PNG

Wciskamy przycisk Add...

W oknie dialogowym Add a Framework zaznaczamy JavaServer Faces.

Grafika:javaee-netbeans6-javaserverfaces.PNG

Wciskamy przycisk OK.

Grafika:javaee-netbeans6-usedframeworks.PNG

Zatwierdzamy przyciskiem OK.

Utworzenie ziarna zarządzanego JSF - PhonebookAgent

Do prezentacji danych będzie nam potrzebne ziarno zarządzane (ang. managed bean) - PhonebookAgent, który wywołania metod będzie po prostu delegował do swojego odpowiednika ziarna EJB PhonebookBean.

Z menu kontekstowego projektu Phonebook-war wybieramy New > Other...

Grafika:javaee-netbeans6-warother.PNG

W oknie dialogowym New File wybieramy kategorię Java Server Faces a następnie JSF Managed Bean.

Grafika:javaee-netbeans6-choosefiletype-jsf.PNG

Wciskamy przycisk Next >.

Formatkę wypełniamy następującymi wartościami:

  • Class Name: PhonebookAgent
  • Package: org.apache.geronimo.samples.phonebook
Grafika:javaee-netbeans6-newjsfmanagedbean-nameandlocation.PNG

Kończymy przyciskiem Finish.

Dodanie zależności ziarna EJB PhonebookBean do ziarna zarządzanego PhonebookAgent

Z menu kontekstowego wybieramy Enterprise Resources > Call Enterprise Bean.

Grafika:javaee-netbeans6-callejb.PNG

Wybieramy jedyne dostępne ziarno PhonebookBean.

Grafika:javaee-netbeans6-callejb-selectbean.PNG

i wciskamy przycisk OK.

Właściwości zarządzanego ziarna - name oraz phoneNumber

Modyfikujemy klasę PhonebookAgent o 2 nowe pola name oraz phoneNumber, które będą odpowiadały (logicznie) polom w encji Subscriber.

private String name;
private String phoneNumber;

Generujemy dla nich metody modyfikującą i odczytującą poprzez menu kontekstowe Insert Code... (alternatywnie Alt+Insert) i wybierając Getter and Setter....

Grafika:javaee-netbeans6-getterandsetter.PNG

lub alternatywnie poprzez menu kontekstowe Refactor > Encapsulate Fields.... Wybór należy do Ciebie. Ostatecznie powinny powstać metody para setName() i getName() oraz setPhoneNumber() i getPhoneNumber().

public class PhonebookAgent {

    ...
    private String name;
    private String phoneNumber;
    ...

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

Metoda PhonebookAgent.create()

Dodajemy metodę create() do ziarna zarządzanego PhonebookAgent. Metoda będzie wywoływana z formularza i wywołanie wydeleguje do ziarna EJB PhonebookBean, które zostało przekazane przez mechanizm wstrzeliwania zależności udostępniony w serwerze aplikacyjnym Java EE 5 przez adnotację @EJB.

public String create() {
    phonebookBean.createSubscriber(getName(), getPhoneNumber());
    return null;
}

Metoda zwraca null, co w JSF oznacza ponowne wyświetlenie strony, z której metoda-akcja create() była wywołana.

Metoda PhonebookAgent.getSubscribers()

Podobnie jak z metodą create(), metoda getSubscribers() jest odpowiednikiem metody getSubscribers() w ziarnie EJB PhonebookBean i do niej zostanie wydelegowane wywołanie.

public List<Subscriber> getSubscribers() {
    return phonebookBean.getSubscribers();
}

Komunikat błędu związany z niedostępnością typu List rozwiązujemy przez kombinację klawiszy Ctrl+Shift+I bądź menu kontekstowe Fix Imports. Błędy związane z brakiem dostępu do klasy Subscriber rozwiążemy w kolejnym kroku.

Dodanie projektu encji Phonebook-jpa jako zależności projektowej

Zaznaczamy węzeł Libraries w projekcie Phonebook-war i poprzez menu kontekstowe Add Project... dodajemy zależność projektową Phonebook-jpa (dokładniej katalog, w którym projekt Phonebook-jpa występuje).

Grafika:javaee-netbeans6-phonebookwar-deps.PNG

Dodanie zależności rozwiązuje problem niedostępności klasy Subscriber.

Klasa PhonebookAgent w pełnej okazałości

Klasa PhonebookAgent powinna prezentować się następująco:

package org.apache.geronimo.samples.phonebook;

import java.util.List;
import javax.ejb.EJB;

public class PhonebookAgent {

    @EJB
    private PhonebookLocal phonebookBean;
    private String name;
    private String phoneNumber;

    public PhonebookAgent() {
    }

    public String create() {
        phonebookBean.createSubscriber(getName(), getPhoneNumber());
        return null;
    }

    public List<Subscriber> getSubscribers() {
        return phonebookBean.getSubscribers();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

Utworzenie strony domowej aplikacji JSF - phonebook.jsp

Rozpoczniemy od porządków w już istniejących stronach JSP. Najpierw usuniemy stronę index.jsp, która dostępna jest pod węzłem Phonebook-war > Web Pages.

Grafika:javaee-netbeans6-indexjspdelete.PNG

UWAGA: Jeśli pojawi się komunikat o niemożności usunięcia pliku, spróbuj jeszcze raz. Można również skorzystać z alternatywnego sposobu - za pomocą klawisza Delete.

Następnym krokiem w naszych porządkach jest zmiana nazwy strony welcomeJSF.jsp na phonebook.jsp za pomocą menu kontekstowego Rename... (alternatywnie klawisz F2).

Modyfikujemy zawartość strony phonebook.jsp tak, aby treść strony była następująca:

<%@page pageEncoding="UTF-8" contentType="text/html"%>

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Phone book</title>
    </head>
    <body>
        <f:view>
        <h:form>
            Name: <h:inputText value="#{PhonebookAgent.name}" />
            Phone number: <h:inputText value="#{PhonebookAgent.phoneNumber}" />
            <h:commandButton value="Create" action="#{PhonebookAgent.create}" />       
        </h:form>
        <HR>
        <h:dataTable value="#{PhonebookAgent.subscribers}" var="subscriber" border="1">
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Name" />
                </f:facet>
                <h:outputText value="#{subscriber.name}" />
            </h:column>
            <h:column>
                <f:facet name="header">
                    <h:outputText value="Phone number" />
                </f:facet>
                <h:outputText value="#{subscriber.phoneNumber}" />
            </h:column>
        </h:dataTable>
        </f:view>    
    </body>
</html>

Uruchomienie

Uruchomienie aplikacji zaczniemy od modyfikacji ustawień projektu głównego Phonebook. Zaznaczamy węzeł projektu Phonebook i otwieramy właściwości projektu przez menu kontekstowe Properties.

Wybieramy Run i wypełniamy Relative URL wartością /faces/phonebook.jsp.

Grafika:javaee-netbeans6-phonebook-run.PNG

Zatwierdzamy zmiany przyciskiem OK.

Wybieramy menu kontekstowe Build, a po poprawnym zbudowaniu projektu wybieramy menu Run.

Grafika:javaee-netbeans6-phonebook-run-final.PNG

Podczas wykonania polecenia Run następuje uruchomienie serwera GlassFish oraz bazy danych Java DB. Poprawne uruchomienie kończy się poniższym komunikatem w oknie Phonebook (run).

...
Building jar: C:\Documents and Settings\jlaskowski\My Documents\NetBeansProjects\Phonebook\dist\Phonebook.ear
post-dist:
dist:
pre-run-deploy:
Initial deploying Phonebook to C:\Documents and Settings\jlaskowski\My Documents\NetBeansProjects\Phonebook\dist\gfdeploy
Completed initial distribution of Phonebook
Start registering the project's server resources
Finished registering server resources
moduleID=Phonebook
deployment started : 0%
deployment finished : 100%
Deploying application in domain completed successfully
Trying to create reference for application in target server  completed successfully
Trying to start application in target server  completed successfully
Deployment of application Phonebook  completed successfully
Enable of Phonebook in target server completed successfully
Enable of application in all targets  completed successfully
All operations completed successfully
post-run-deploy:
run-deploy:
Browsing: http://localhost:8080/Phonebook-war/faces/phonebook.jsp
run-display-browser:
run-ac:
run:
BUILD SUCCESSFUL (total time: 1 minute 33 seconds)

oraz uruchomieniem okna przeglądarki z adresem http://localhost:8080/Phonebook-war/faces/phonebook.jsp.

Grafika:javaee-netbeans6-phonebook-browser.PNG

Teraz pozostaje uaktrakcyjnienie interfejsu użytkownika o kontrolki graficzne JSF i dodanie gadżetów ajaksowych. Decyzję pozostawiam Tobie! Z zainteresowaniem przeczytam dokonania w tej materii, więc jeśli masz pomysły na potencjalne rozszerzenia, skontaktuj się ze mną. Miłego programowania z Korporacyjną Javą!

Osobiste