ToyStore - sklep z zabawkami ( Sitemesh, JSF, Spring, Hibernate, Oracle Express )- CZĘŚĆ I I- WARSTWA WEB

Zapraszam do zapoznania się z częścią I artykułu :
ToyStore - sklep z zabawkami ( Sitemesh, JSF, Spring, Hibernate, Oracle Express )- CZĘŚĆ I - warstwa danych i biznesowa


A więc do dwóch warstw naszej aplikacji teraz podejmę próbę dopracowania trzeciej - umożliwiającej dostęp do aplikacji przy pomocy przeglądarki WWW. Jako że ostatnio przechodzę okres zauroczenia frameworkiem JSF, wybór technologii realizacji zadania nie był trudny... a wiec do rzeczy...

Konfiguracja serwletu FacesServlet i webowego kontekstu aplikacji

Framework JSF jest oparty na ogólnie znanym wzorcu projektowym MVC (Model View Controller ) nic więc dziwnego, że najważniejszym elementem jego konfiguracji jest właściwe zdefiniowanie parametrów Serwletu Rozdzielającego (Servlet Dispatcher) . W przypadku JSF nosi on nazwę FacesServlet. Jego konfiguracja odbywa się w deskryptorze rozmieszczenia - pliku /WEB-INF/web.xml.

Sama modyfikacja pliku jest bardzo prosta sprowadza się ona do kilku rzeczy:

Po pierwsze należy zdefiniować sam serwlet. Robi się to przy pomocy następującego kodu:

<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

Ponieważ nasza aplikacja ma mieć możliwość korzystania z obiektów stworzonych przez Springa należy zdefiniować jej kontekst springa, przez definicję odpowiedniego listenera:

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

Ostatnim krokiem będzie zdefiniowanie filtra, który wszystkie żądania zakończone przyrostkiem *.faces będzie przekierowywał do serwletu Faces Servlet. Wygląda on następująco:

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>

Nasz serwlet jest już gotowy do pracy... teraz czas na stworzenie pierwszego komponentu JSF.

Pierwszy scenariusz - wyświetlenie listy kategorii
Na początek chciałbym wyświetlić listę kategorii produktów, które są w bazie. Chciałbym, aby była ona prezentowana w postaci tabelki, z której to możnaby przejść do edycji kategorii, usunąć ją, dodać nową, a także obejrzeć jakie produkty do niej należą.

Wykorzystanie technologii JSF implikuje, że do realizacji tego scenariusza będziemy potrzebowali definicji dwóch rzeczy, a mianowicie:
  • strony na której zdefiniowany będzie UI kompotent odpowiedzialny za renderowanie tabelki
  • beana ( backing beana), który w architekturze MVC umiejscowiony będzie w warstwie modelu i stanowić będzie zaplecze dla komponentu UI. Jego zadaniem będzie dostarczenie danych potrzebnych do wypełnienia tabelki, jak również metod stanowiących o logice działania (więcej o beanach napisałem w artykule JSF- czyli jak ja to rozumiem...).
Nasz pierwszy backing bean - CategoryListUI
Pierwszym krokiem, który należy wykonać jest zdefiniowanie obiektu - beana, który zasili naszą tabelkę w dane i dostarczy obsługującej ją logiki. W terminologii JSF bean taki nazywa się "backing bean".

A więc umiejscawiam go w pakiecie mw.toystore.web.ui i nadaję nazw CategoryListUI.

Nasz bean będzie korzystał z kontekstu springowego i za jego pośrednictwem uzyska referencje do interfejsu biznesowego IProductManager. Aby obiekt ten został prawidłowo zaincjalizowany przy pomocy mechanizmu IoC w klasie backing beana należy zdefiniować własność tego typu, oraz metody dostępowe (setter i getter). Stosowny fragment kodu wygląda następująco:

.......
private IProductManager productManager;

public IProductManager getProductManager() {
return productManager;
}

public void setProductManager(IProductManager productManager) {
this.productManager = productManager;
}
.......

Teraz, gdy nasz komponent potrafi już sięgnąć do warstwy biznesowej można stworzyć metodę, za której pośrednictwem komponent interfejsu użytkownika (UI) leżący na stronie i skojarzony z naszym beanem uzyska dostęp do listy obiektów kategorii. Niech nazywa się ona getCategoryList(). Jej konstrukcja będzie bardzo prosta, bo ograniczy się tylko do wywołania metody z obiektu interfejsu biznesowego i zwrócenia na zewnątrz pobranej z niższych warstw aplikacji kolekcji obiektów kategorii. Nasza metoda wygląda następująco:

public List getCategories(){
return this.productManager.getCategoryList();
}

W tym momencie nasz bean potrafi zaserwować listę kategorii, posiada więc minimalną funkcjonalność. Dzięki niemu komponent interfejsu użytkownika będzie w stanie uzyskać kolekcję obiektów reprezentujących różne kategorie.

Zanim jakikolwiek komponent interfejsu użytkownika skorzysta z naszego beana musi zostać wykonana stosowna konfiguracja, która dokonuje się przez dokonanie modyfikacji w pliku /WEB-INF/faces-config.xml. Przyjrzyjmy się im trochę dokładniej.

Propagowanie beana jako Managed Bean

Przyszedł czas na integrację naszego beana z frameworkiem JSF. Odbywa się ona przez dokonanie odpowiednich wpisów w pliku konfiguracyjnym /WEB-INF/faces-config.xml.

Myślę, że można powiedzieć, że każdy backing bean, którego opiszemy w tym pliku nabywa kilka nowych cech. Przede wszystkim, nadana mu tutaj logiczna nazwa jest widoczna dla wszystkich komponentów interfejsu użytkownika. Mogą się do niego odwoływać i na podstawie uzyskanych od niego informacji renderować odpowiednie elementy interfejsu użytkownika.
Cyklem życia takiego beana zarządza już sam framework. W żadnym miejscu nie ma konieczności martwienia się o jego stworzenie i poprawną inicjalizację. Zadba o to framework. Być może dlatego po propagacji, beany uzyskują nową nazwę - managed beans.

Ale po kolei. Przyjrzyjmy się kolejnym elementom naszego pliku /WEB-INF/faces-config.xml.

Cała konfiguracja objęta jest tagami <faces-config> </faces-config>.

Przed definicją beana znajduje się wpis konfiguracyjny o specjalnym znaczeniu. Mianowicie powoduje on, że framework JSF uzyskuje dostęp także do kontekstu springowego (temat integracji frameworków Spring i JSF opisałem w artykule "Próba połączenia JSF i Spring..." ). Dzięki temu do naszego managed beana możliwe jest wstrzyknięcie obiektów zarządzanych przez kontener IoC (a więc np. naszego interfejsu biznesowego IProductManager). Stosowny fragment pliku wygląda następująco:

<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>

Definicja samego managed beana wygląda następująco:

<managed-bean>
<managed-bean-name>categoryListUI</managed-bean-name>
<managed-bean-class>mw.toystore.web.ui.CategoryListUI</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>productManager</property-name>
<value>#{productManager}</value>
</managed-property>
</managed-bean>

Powyższe wpisy powodują że stworzony zostanie managed bean
o identyfikatorze categoryListUI (pod tą nazwą będzie on widzialny dla komponentów UI). Jako klasę beana wskazałem omawianą wcześniej klasę mw.toystore.web.ui.CategoryListUI . Kolejna właściwość określa, że bean będzie przesyłany w obiekcie żądania.
Na uwagę zasługuje sekcja:

<managed-property>
<property-name>productManager</property-name>
<value>#{productManager}</value>
</managed-property>

Jak pamiętamy, klasa naszego beana ma zdefiniowaną właściwość o nazwie propertyManager, oraz dwie metody dostępowe do niej. W tym momencie zostają one wykorzystane przez framework do ich inicjalizacji. W kontekście Springa odszukany zostaje obiekt o logicznej nazwie
productManager ( id="productManager"), a następnie jego wartość zostaje wstrzyknięta do naszego beana za pomocą wywołania metody setProductManager().

Nasz bean został spropagowany, jest dostępny dla stron JSP, teraz możemy przejść do tworzenia strony JSP, na której umieszczony zostanie komponent interfejsu użytkownika, który skorzysta z danych zwróconych z naszego beana i zrenderuje dla nas stosowną dla nich tabelę.

Strona z komponentem UI - categoryList.jsp

Na początek w katalogu głównym naszej aplikacji zakładam plik cateogoryList.jsp. Chciałbym aby komponent JSF umieszczony na niej wykorzystywał zdefiniowany wcześniej managed bean i wyświetlał nazwy wszystkich kategorii. A więc potrzebna będzie tabela.

Z początku nie wiedziałem jak się zabrać za jej tworzenie ale z pomocą przyszło google i artykuł Jacka Laskowskiego poświęcony tabelom w JSF. Znalazłem tam sczególowy opis znacznika <h:dataTable>

Aby uniknąć problemów z wyświetlaniem polskich znaczków rozpoczynam od ustawienia kodowania na utf-8:

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

Na początek definicja bibliotek znaczników związanych z wykorzystaniem elementów JSF:

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

Ponieważ będzie ona potrzebna na wszystkich stronach wykorzystujących komponenty JSF, wydzieliłem ją do pliku /WEB-INF/jsp/include.jsp i włączam do moich stron za pomocą dyrektywy include:

<%@ include file="/WEB-INF/jsp/include.jsp"%>

Od tej chwili do elementów JSF będę mógł odwołać się przy pomocy schematu "przedrostek_tagliba:nazwa_elementu", gdzie jako przedrostek wystąpi jeden z dwóch zdefiniowanych powyżej (f dla tagów z jsf-core i h dla tagów z jsf-html).

A więc od początku. Na szczycie hierarchii elementów JSF umieszczonych na stronie zawsze musi znaleźć się element f:view>/f:view>. Dopiero w jego wnętrzu mogą zostać umieszczone inne tagi. Definicja naszej najprostszej tabelki będzie wyglądała następująco:

<h:dataTable value="#{categoryListUI.categories}" var="category" border="1" styleClass="listtab"> <h:column> <f:facet name="header"> <f:verbatim>Name</f:verbatim> </f:facet> <h:outputText value="#{category.name}" /> </h:column> </h:dataTable>

Kluczowe znaczenie mają dwa atrybuty ustawiane na samym początku a mianowicie:
  • value - powoduje że lista obiektów, które mają zostać zaprezentowane w tabelce pobrana zostanie z obiektu o nazwie catgoryListUI (nazwa logiczna z pliku faces-config.xml), na podstawie jego własności categories . Tu należałoby wyjaśnić jedną rzecz. Mianowicie bean ten nie musi mieć własności categories, wystarczy, że tak jak w naszym przypadku będzie miał zdefiniowaną metodę getCategories().
  • var - jest to nazwa logiczna obiektu pobranego z kolekcji przy pojedynczej iteracji
Atrybut "styleClass" powoduje że zrenderowana tabelka w kodzie wynikowym przypisana będzie do klasy CSS o nazwie "listtab" (klasę tą zdefiniujemy później, przy itegracji z SiteMeshem).

Definicja pojedynczej kolumny tabeli następuje we wnętrzu tagu <h:column> </h:column>. Nie musimy oprogramowywać samej iteracji - wystarczy definicja nagłówka kolumny (<f:facet name="header"></f:facet name="header">) i wskazania pola z którego przy kolejnej iteracji powinna zostać wyciągnięta wartość wierszowa (<h:outputText value="#{category.name}" />).

A więc definicja naszej najprostszej tabeli wygląda na kompletną. Czas na uruchomienie serwera , a potem umieszczeniem na nim naszej aplikacji.

Po wpisaniu adresu: http://localhost:3333/ToyStoreJSFApp/categoryList.faces

Na ekranie pojawiła się tabelka:

A więc wygląda na to że pierwszy i kluczowy przypadek użycia naszej aplikacji został zrealizowany. Wyświetla ona tabelkę z kategoriami produktów.




21 komentarzy:

Antoni Jakubiak pisze...

Witam w sklepie z zabawkami.

Czekam na następne artykuły, szczególnie interesuje mnie integracja JSF i Sitemesh

Anonimowy pisze...

We are a group of volunteers and opening a new scheme
in our community. Your website offered us with valuable info to work on.
You have done an impressive job and our whole community will be
thankful to you.
My webpage : Food Storage

Anonimowy pisze...

I like reading an article that can make people think. Also, many thanks for permitting me to comment!
Also visit my homepage - Google Sniper 2.0 Review

Anonimowy pisze...

If you wish for to obtain a good deal from
this article then you have to apply these techniques to
your won website.
Feel free to surf my site ; rippedmusclexreviews.net

Anonimowy pisze...

This piece of writing will help the internet viewers for creating new blog or even a blog from
start to end.
My webpage Buy Viarex

Anonimowy pisze...

I have to thank you for the efforts you have put in penning this
blog. I really hope to view the same high-grade blog posts from you in the future as well.
In truth, your creative writing abilities has inspired me to get my own blog now ;)
Here is my webpage : Dark Skin Spots

Anonimowy pisze...

Excellent goods from you, man. I've consider your stuff prior to and you're simply extremely magnificent.
I really like what you have got right here, really
like what you are stating and the best way wherein you assert it.
You are making it entertaining and you continue to take care of to stay it wise.

I can not wait to read much more from you. That is
really a tremendous site.
Also see my site: Weight Loss Patch

Anonimowy pisze...

I loved as much as you will receive carried out
right here. The sketch is tasteful, your authored material stylish.
nonetheless, you command get got an edginess over that you wish be delivering the following.
unwell unquestionably come further formerly again since exactly the same nearly very often inside case you
shield this hike.
Check out my website ... Raspberry Ketones

Anonimowy pisze...

I love your blog.. very nice colors & theme. Did you design this website yourself or did you hire someone to do it for you?
Plz answer back as I'm looking to create my own blog and would like to find out where u got this from. appreciate it
Feel free to visit my website ... Garcinia Cambogia

Anonimowy pisze...

I'm really impressed with your writing skills and also with the layout on your blog. Is this a paid theme or did you customize it yourself? Either way keep up the nice quality writing, it is rare to see a great blog like this one today.
My site - Night Skin Care

Anonimowy pisze...

Way cool! Some very valid points! I appreciate you writing this write-up and also the rest of the website is really good.
Here is my homepage ; Ultra Slim Patch Reviews

Anonimowy pisze...

Hi there, I found your site by the use of Google even
as searching for a related topic, your website got here up,
it seems great. I've bookmarked it in my google bookmarks.
Hello there, just became alert to your blog through Google, and located that it's truly
informative. I am gonna watch out for brussels. I will appreciate in case you continue this in
future. Many people will likely be benefited out of your writing.
Cheers!
Also visit my site ; Auravie Review

Anonimowy pisze...

Hello! Quick question that's totally off topic. Do you know how to make your site mobile friendly? My website looks weird when browsing from my iphone 4. I'm
trying to find a template or plugin that might be able to
correct this problem. If you have any recommendations, please share.
Many thanks!
Here is my weblog ; Cash For Surveys

Anonimowy pisze...

Thank you for the good writeup. It in fact was a amusement account it.
Look advanced to far added agreeable from you! However, how could we communicate?
My web site :: Blacktop Paving MN

Anonimowy pisze...

I'm curious to find out what blog platform you happen to be using? I'm
having some small security problems with my latest blog and I would
like to find something more safe. Do you have any solutions?
Also visit my web blog - Raspberry Ketone Review

Anonimowy pisze...

great points altogether, you simply received a
logo new reader. What may you suggest about your submit that you
simply made some days in the past? Any positive?
Look at my web site ... Androsolve

Anonimowy pisze...

I drop a leave a response each time I especially enjoy a
article on a website or I have something to add to the conversation.

Usually it is a result of the sincerness communicated in the
post I looked at. And on this post "ToyStore - sklep z zabawkami ( Sitemesh, JSF, Spring, Hibernate, Oracle Express )- CZ�Ś� I I- WARSTWA WEB".
I was actually moved enough to drop a comment :) I
actually do have some questions for you if you do not mind.

Is it only me or does it appear like a few of the remarks look like coming from
brain dead individuals? :-P And, if you are posting at other places,
I would like to follow you. Could you list the complete urls of all your public
pages like your linkedin profile, Facebook page or twitter feed?



my weblog ... http://auraviereview.net

Anonimowy pisze...

My brother recommended I may like this website.
He used to be entirely right. This publish truly made my day.
You can not consider simply how much time I had spent for this information!
Thank you!

my web page; Pure Raspberry Ketones

Anonimowy pisze...

Currently it sounds like Drupal is the preferred blogging platform available right
now. (from what I've read) Is that what you are using on your blog?

Have a look at my webpage: http://mitoslimreviews.net

Anonimowy pisze...

Greetings! This is my first comment here so I just wanted to give
a quick shout out and tell you I truly enjoy reading your articles.
Can you suggest any other blogs/websites/forums that go over the same subjects?
Appreciate it!

Here is my homepage Home Staging Company

Anonimowy pisze...

I am regular reader, how are you everybody?
This paragraph posted at this web page is in fact fastidious.


Feel free to visit my webpage: kliknij