Pokazywanie postów oznaczonych etykietą facelets. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą facelets. Pokaż wszystkie posty

19 sierpnia 2008

Dyskusje o znaczeniu facelets

0 komentarzy
Ugrzązłem w rozwoju wtyczki Geronimo NetBeans Plugin i testowaniu (nie)doskonałości rozwojowej wersji NetBeans 6.5, więc powiało orzeźwieniem (auć, początkowo napisałem przez 'ż'!), kiedy przeglądając listę dyskusyjną pl.comp.lang.java natrafiłem na zamierzchły już wątek JSF-facelets a pozycjonowanie i bezposredni URL, w którym Michał odpytywał Brzeziego o znaczenie facelets w świecie aplikacji JSF, szczególnie w kontekście istnienia JBoss Seam, JSF 1.2, Unified EL oraz JSTL 1.2. Nie długo trwało, kiedy trafiłem na bardzo podobną dyskusję tyle, że dotyczyła JSF Templating oraz facelets (mimo wyraźnego porównania różnych rozwiązań, wciąż dotyczyła sensu istnienia facelets) - Facelets vs. JSF Templating. To właśnie ten wątek "zmusił" mnie do pobrania specyfikacji JSR-314 JavaServer Faces 2.0, w której naocznie przekonałem się o znaczeniu facelets w rozwoju JSF 2.0 (patrz rozdział Integration with Facelets jako równouprawnionego do Integration with JSP, acz wyjątkowo skromnego w treści):

As of version 2 of this specification, JavaServer Faces implementations must support (although JSF-based applications need not utilize) using Facelets as the page description language for JSF pages.

This chapter is a place holder for the Facelets specification. Currently it is a scratch pad for spec assertions that apply to Facelets features that are not yet implemented in the current Facelets implementation.


Dodając do tego niedawno zakończoną lekturę książki Facelets Roberta Swarra (O'Reilly, March 2007), której moją recenzję można znaleźć w Book review: Facelets nie mogłem oprzeć się pokusie zdabania tematu i znalezienia odpowiedzi na pytanie, czy wciąż warto zajmować się facelets. W zasadzie to sama wzmianka w specyfikacji JSF 2.0 odpowiada na to pytanie, ale pytanie o znaczenie facelets było w kontekście obecnych technologii webowych, gdzie wciąż króluje JSF 1.2 ze wsparciem JBoss Seam (albo odwrotnie).

Pierwsza strona projektu facelets opisuje go jako Facelets is a view technology that focuses on building JSF component trees. Hmmm, pewnie nie bardzo zrozumiałe dla nowicjuszy jsfowych, więc z pomocą może przyjść dokumentacja facelets - Facelets - JavaServer Faces View Definition Framework, a szczególnie rozdział Chapter 6. Facelets Architecture - (a za nią i wspomniana książka Facelets), gdzie jego obszar działania przedstawiony jest jako:

Facelets is founded on simple principles and the API is a solid reflection of it. The framework is focused on one specific task, and that's tree creation and content interweaving-- taking an XHTML or XML document and using it as instructions to populate a tree of UIComponents. That's it.

A technicznie, sprowadza się do zarejestrowania nowego JSF ViewHandler - com.sun.facelets.FaceletViewHandler w faces-config.xml i cały świat facelets stoi otworem. Od tej pory zamiast JSP jako technologii wizualizacji interfejsu użytkownika korzystamy z XHTML, więc znaczniki JSP, które do tej pory były stosowane idą w odstawkę, a na ich miejsce należy odszukać odpowiedników faceletowych (patrz Why can't I use {JSP Tag library name here} with Facelets?). Można oczywiście stosować facelets i JSP w pojedyńczej aplikacji webowej (patrz How do I use Facelets and JSP in the same application?), więc nic straconego. facelets jest również podstawowym budowniczym widoku w JBoss Seam, więc i na tej podstawie możnaby wysnuć pewne podejrzenia o niebagatelnym znaczeniu facelets.

Ja jednak wciąż nie mogę uporać się ze znacznikami jpivot, które są dla mnie kluczowym elementem w obecnym projekcie. Powodem dla wdrożenia facelets w projekcie było przede wszystkim wsparcie dla tworzenia szablonów, dzięki którym mógłbym podzielić stronę na cześci - nagłówek, stopka, lewy/prawy panel, środek i całkowicie zapomnieć o JSF-owym f:subview i różnych temupodobnych technikach włączania podstron znanych z JSP (ala jsp:include). Książka Facelets uspokoiła mnie, że nie jestem stracony i użycie znaczników JSP dla jpivot będzie możliwe, ale wciąż zastanawiam się, jakie należy podjąć kroki, aby aplikację uruchomić wespół z jpivot i facelets. Początkowo próbowałem się z JBoss Seam, ale zdaje się, że na chwilę obecną wystarczy duet facelets oraz jpivot. Jeszcze rozważam, ile faktycznie mogę poświęcić czasu na rozwiązywanie potencjalnych błędów (kiedy wtyczka GNP czeka). A jak u Was wygląda użycie facelets? Jest dla niego miejsce?

Zagadka na koniec. Właśnie na nią wpadłem i nie mogłem kryć jej dla siebie. Do czego służy poniższa komenda?
 jlaskowski@work /cygdrive/c/apps/netbeans-nightly
$ cmd /C start netbeans-trunk-nightly-200808190201.zip
Zamiast wykonywać kilka czynności, teraz mogę "załatwić" to jedną.

25 czerwca 2008

Element jsp-property-group w JSP 2.1

1 komentarzy
Podczas rozpoznawania facelets w kontekście braku interpretowania znaczników JSP z projektu jpivot natrafiłem na pewną ciekawostkę JSP 2.1 - element jsp-property-group w deskryptorze rozmieszczenia aplikacji webowej /WEB-INF/web.xml. Jestem pewien, że jest to jeden z tych niuansów specyfikacji JSP 2.1, który potrafi położyć nawet najbardziej rozeznanych w zawiłościach specyfikacji podczas egzaminu Sun Certified Web Component Developer (SCWCD). Już kiedyś miałem okazję spotkać ten element, ale przelotnie i nigdy nie przyszło mi go zastosować.

Podczas lektury artykułu Developing applications with Facelets, JSF, and JSP z sierpnia 2006r. (!) napotkałem go ponownie.
 <jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
<is-xml>true</is-xml>
</jsp-property-group>
</jsp-config>
Za pomocą jsp-property-group można konfigurować grupy stron JSP i przypisywać im parametry konfiguracyjne. W powyższym przykładzie jsp-property-group zostało wykorzystane do wyłączenia możliwości zanurzania skryptów JSP wewnątrz stron JSP o rozszerzeniu jsp. Innymi konfiguracjami mogłoby być kodowanie stron, włączenie obsługi JSP EL (języka wyrażeń JSP - tych rozpoczynających się od $) oraz dołączanie (pod)stron przed i po wykonaniu strony. Rozszeżenie stron JSP nie musi być koniecznie jsp, ale same strony muszą być poprawnymi stronami JSP.

Zgodnie ze specyfikacją JavaServer Pages 2.1 (JSP) w JSP.3.3 JSP Property Groups (strona 78) konfiguracja stron JSP za pomocą jsp-config (rodzica jsp-property-group) dotyczy wskazanych stron spełniających wzorzec w url-pattern oraz wszystkich włączonych stron za pomocą dyrektywy include za wyjątkiem parametru konfiguracyjnego page-encoding, który dotyczy wyłącznie tych spełniających url-pattern.

Jeśli wzorzec określony w url-pattern jest identyczny ze wzorcem elementu servlet-mapping, wtedy jsp-property-group ma priorytet.

Podelementy jsp-property-group:
  • el-ignored (true/false) - wyłącza/włącza JSP EL, który przed JSP 2.0 nie był dostępny. Zmiana globalnej konfiguracji możliwa jest przez atrybut isELIgnored dyrektywy page w stronie JSP. Parametr ma wpływ na obsługę \$ oraz \#, które wyłączają specjalność znaków $ oraz #. Przy wyłączonym JSP EL są one łańcuchem 2 znaków bez specjalności \, $ czy #;
  • scripting-invalid (true/false) - wyłącza/włącza mechanizm skryptów w stronach JSP. Domyślnie skrypty są włączone;
  • page-encoding - odpowiada atrybutowi pageEncoding dyrektywy page w stronie JSP i ustawia stronę kodową na podaną. Dotyczy wyłącznie stron JSP, a nie dokumentów JSP (jspx), które są dokumentami XML, gdzie podanie strony kodowej jest obowiązkowe. Przykład w specyfikacji przedstawia konfigurację dla podzbioru stron JSP spełniających wzorzec /ja/*, czyli tych należących do strony kodowej Shift_JIS;
  • include-prelude określa ścieżkę strony (fragmentu strony JSP - jspf) w aplikacji webowej dołączanego na początku strony JSP, podobnie do dyrektywy include. W przypadku wielu elementów include-prelude ich dołączanie będzie odpowiadało kolejności występowania w jsp-property-group;
  • include-coda jest odpowiednikiem include-prelude, ale dołączenie następuje na końcu stron JSP spełniających wzorzec url-pattern w sekcji jsp-property-group.
  • is-xml (true/false) wskazuje, że strony spełniające url-pattern są dokumentami XML. Za pomocą tego elementu można określić, że domyślne rozszerzenie wskazujące strony JSP jako dokumenty XML - jspx - jest rozszerzeniem zwykłych, niexmlowych stron JSP;
  • deferred-syntax-allowed-as-literal (true/false) - wyłącza/włącza specjalne traktowanie łańcuchu #{, które od JSP 2.1 są zarezerwowane dla wyrażeń JSP EL (wartość false). Za pomocą atrybutu deferredSyntaxAllowedAsLiteral dyrektywy page można zmienić wartość tego parametru dla pojedyńczej strony JSP;
  • trim-directivewhitespaces (true/false) usuwa/pozostawia "białe" znaki w odpowiedzi strony JSP. Wpływa istotnie na rozmiar wygenerowanej klientowi strony JSP. Nie ma wpływu na dokumenty JSP (strony JSP będące dokumentami XML). Domyślna wartość false - pozostawia "białe" znaki. Możliwa zmiana konfiguracji per strona JSP za pomocą atrybutu trimDirectiveWhitespaces dyrektywy page.
Dla kompletu informacji należałoby jeszcze wspomnieć o dyrektywie page - rozdział JSP.1.10.1 The page Directive specyfikacji JavaServer Pages 2.1 (strona 44). W stronach JSP dyrektywa page reprezentowana jest za pomocą elementu <%@ page { attr="value" }* %>, podczas gdy dla dokumentów JSP <jsp:directive.page>. Możliwe jest wielokrotne użycie dyrektywy page w ramach pojedyńczej strony i mogą być umiejscowione w dowolnym miejscu strony, a mimo to wpływają na całą jednostkę kompilacji (cała strona JSP już po dołączeniu podstron). Umiejscowienie dyrektywy page z atrybutami pageEncoding oraz contentType powinno być jednakże na początku strony, aby poprawnie wyznaczyć kodowanie strony. Jeśli dyrektywa page występuje w różnych częściach strony JSP to dla identycznych parametrów musi być identyczna wartość, za wyjątkiem atrybutów import oraz pageEncoding.

Składnia dyrektywy page:
 <%@ page page_directive_attr_list %>

page_directive_attr_list ::= { language="scriptingLanguage"}
{ extends="className" }
{ import="importList" }
{ session="true|false" }
{ buffer="none|sizekb" }
{ autoFlush="true|false" }
{ isThreadSafe="true|false" }
{ info="info_text" }
{ errorPage="error_url" }
{ isErrorPage="true|false" }
{ contentType="ctinfo" }
{ pageEncoding="peinfo" }
{ isELIgnored="true|false" }
{ deferredSyntaxAllowedAsLiteral="true|false"}
{ trimDirectiveWhitespaces="true|false"}
Opis poszczególnych elementów dyrektywy page znajduje się w tabeli Table JSP.1-8 Page Directive Attributes specyfikacji JavaServer Pages 2.1 (strona 46).

Pytanie konkursowe: Za pomocą jakiego elementu deskryptora aplikacji webowej /WEB-INF/web.xml konfigurowane są parametry stron JSP? Pytanie bardziej wyrafinowane, z tych wykańczających na egzaminach, czy "ostrych" rozmowach kwalifikacyjnych: Jakie elementy jsp-property-group w web.xml mogą być nadpisane przez dyrektywę page? Miłych rozmów kwalifikacyjnych ;-)

15 października 2007

Konfiguracja aplikacji JSF ze stronami z i bez Facelets

0 komentarzy
Przez długi czas pytanie Rafała JSF || facelets na grupie pl.comp.lang.java nie dawało mi spokoju. Pytanie dotyczyło migracji aplikacji JSF do Facelets, w taki sposób, że aktualna funkcjonalność pozostałaby bez zmian (bez Facelets), podczas gdy nowe strony już korzystałyby z facelets. Pomysł polega na równoległym utrzymywaniu stron bez facelets i tworzeniu nowych z facelets. Jako, że gro czasu zajmowało mi rozpoznawanie EJB3 zostawiłem rozwiązanie problemu na później. W końcu, kiedy skończyłem prezentację konwerterów w JSF pomyślałem, że w tym tonie zabiorę się za facelets i to właśnie od tego pytania.

Kiedy już miałem odpowiedzieć, że takie rozdzielenie się nie da, aż mnie natchnęło i zacząłem kombinować z różnymi konfiguracjami mapowania servletu FacesServlet. Niestety trochę to trwało, aż natrafiłem na parametr facelets.VIEW_MAPPINGS, który wskazał mi właściwe rozwiązanie (w zasadzie to znalazłem odpowiedź w How do I use Facelets and JSP in the same application?).

Uruchomienie facelets wymaga definicji komponentu zarządzającego widokiem w faces-config.xml.

<?xml version='1.0' encoding='UTF-8'?>

<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<application>
<view-handler>
com.sun.facelets.FaceletViewHandler
</view-handler>
</application>
</faces-config>
Tutaj wszystko "po staremu". Klucz do rozwiązania leży w konfiguracji aplikacji internetowej - web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jsp</param-value>
</context-param>
<context-param>
<param-name>facelets.VIEW_MAPPINGS</param-name>
<param-value>*.xhtml</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.verifyObjects</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
Przy takiej konfiguracji wywołanie strony pod adresem /faces/welcomeJSF.jsp spowoduje wykonanie jej bez udziału facelets, który w prawdzie będzie wyzwalany, ale będzie akceptował wyłącznie strony zakończone rozszerzeniem .xhtml (parametr facelets.VIEW_MAPPINGS), np. /faces/welcomeJSF.xhtml. Inne rozszerzenia są poza zainteresowaniem facelets. Istotne jest również związanie FacesServlet poprzez mapowanie ścieżki (url-pattern ustawione na /faces/*) zamiast mapowania po rozszerzeniu.

Przykładowy projekt NetBeans IDE aplikacji internetowej korzystającej z "czystego" JSF oraz facelets dostępny jest jako jsf-zibezfacelets-webapp.zip.