środa, 6 kwietnia 2011

Własne komponenty JSF 2.0

Od dłuższego czasu chodzi mi napisanie biblioteki komponentów JSF zawierającej zestaw flash'owych wykresów FusionCharts Free. Zabierałem się już do tego kilkakrotnie ale zawsze miałem coś pilniejszego do zrobienia. Tym razem jednak zebrałem się w sobie i po lekturze książki, o której pisałem ostatnio postanowiłem przebrnąć przez problematykę tworzenia własnych bibliotek JSF. Początkowo, po wprowadzeniu wersji 2.0, myślałem o wykorzystaniu do tego celu komponentów złożonych (composite components), jednak po głębszym przemyśleniu tematu, doszedłem do wniosku, że bardziej elastyczne będzie utworzenie własnej biblioteki.
Postanowiłem zacząć od czegoś najprostszego – komponentu, który wygeneruje mi HTML'owy element DIV ze wstawionym przez aplikację kliencką tekstem. Komponent taki, może w zasadzie składać się tylko z jednaj klasy – klasy komponentu, dziedziczącej z klasy UIComponent. W praktyce stosuje się głównie dziczenie po jednej z trzech klas: UIOutput, UIInput, UIComand.
Twórcy technologii JSF założyli, że formatem wyjściowym może być nie tyko HTML (generowany domyślnie prze klasę komponentu) dlatego też, wprowadzili możliwość wydelegowania zadania wizualizacji do odrębnego mechanizmu. Ja jednak, aby nie komplikować tematu rendererów, do którego pewnie jeszcze wrócę, skupię się na podstawowym rozwiązaniu. Poniżej klasa mojego komponentu
package kuba.demo.customcomp;

import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

@FacesComponent("com.blogspot.javaspotlight.Div")
public class UIDiv extends UIOutput{

   @Override
   public void encodeBegin(FacesContext context) throws IOException {

      ResponseWriter writer = context.getResponseWriter();
      String clientId = getClientId(context);

      String compId   = (String)getAttributes().get("id");
      String divStyle = (String)getAttributes().get("style");
      String divText  = (String)getAttributes().get("divText");

      writer.startElement("div", this);

      if (compId != null){
         writer.writeAttribute("id", compId, "id");
      }else{
         writer.writeAttribute("id", clientId, null);
      }

      if (divStyle != null){
         writer.writeAttribute("style", divStyle, null);
      }

      if (divText != null){
         writer.writeText(divText, null, null);
      }

      writer.endElement("div");
   }
}

Jej zadaniem jest wygenerowanie elementu div z trzema atrybutami pochodzącymi z a aplikacji klienckiej: id, style, divText.
Warto też zwrócić uwagę na adnotację @FacesComponent("com.blogspot.javaspotlight.Div"). Zawiera ona identyfikator klasy komponentu JSF. We wcześniejszych wersjach odwzorowanie identyfikatora na klasę komponentu umieszczało się w pliku faces-config.xml






Od wersji 2.0 można używać obu metod odwzorowań.
Drugim krokiem tworzenia własnego komponentu JSF jest utworzenie w katalogu WEB-INF pliku deskryptora biblioteki zawierającego: przestrzeń nazw, nazwę znacznika i typ komponentu. Jego nazwa musi posiadać zakończenie .taglib.xml
   



























Warto zwrócić uwagę na jedną rzecz – deklarację atrybutów znacznika. Nie jest ona wymagana, klasa komponentu i tak będzie „widziała” atrybuty. Jednak bez tej deklaracji tworząc aplikację z wykorzystaniem własnej biblioteki, nie będzie ich rozpoznawać nasze środowisko programistyczne – w moim przypadku NetBeans.
Wreszcie krok trzeci – ostatni. W pliku web.xml musimy wskazać na położenie deskryptora






Teraz pozostaje już tylko użycie komponentu na stronie.













Teoretycznie to już wszystko, tylko po co nam taki komponent ? Celem bibliotek jest możliwość ich wielokrotnego wykorzystania w różnych projektach. Pozostaje jeszcze spakowanie naszego komponentu. Dopiero tutaj zaczął się problem :)
Przygotowanie komponentu JSF do dystrybucji
  1. utworzyć archiwum .jar
  2. przekopiować deskryptor .taglib.xml do katalogu META-INF
  3. w katalogu META-INF musi znajdować się plik faces-config.xml – nawet jeśli nie zawiera żadnych wpisów (tutaj właśnie utknąłem – przecież JSF 2.0 załatwia wszystko przez adnotacje i teoretycznie ten plik nie jest potrzebny. Jakże się myliłem – JEST POTRZEBNY :))
  4. plik web.xml nie jest potrzebny
Struktura biblioteki po spakowaniu powinna wyglądać następująco

Brak komentarzy:

Prześlij komentarz