Użyteczność JSF

0

Cześć,

Generalnie jestem fanem Javy. Programowałem w JSE (SWING, NET), RIA(EJB+JWS), JavaFX i wszystko ładnie chodziło.
Teraz mam drugie czy trzecie podejście do JSF na GlassFish no i po raz kolejny masakra.
A mianowicie mam na myśli, że parę rzeczy nie chodzi zgodnie ze specyfikacją, albo niestabilnie. Dodatkowo znajduję o tych problemach info w sieci sprzed np. 3-4 lat i...
i nic, bugi nadal są, czyli nikomu nie przeszkadzają, że nie zostały naprawione? czy może po prostu nikt tego nie używa do poważnych zastosowań? Pojawia się w końcu pytanie: Czy ktoś z Was używał JSF choćby w średniej wielkości aplikacji? Bo ja właśnie się zastanawiam się czy się nie przenieść na inny framework i nie wywalić w błoto dotychczas zainwestowanego czasu w aplikację (na szczęście tylko tydzień pracy).

0

Ja uzywalem, nie warto sie meczyc, przenies sie na cos innego. Za moich czasow (rok temu) modny byl np. Wicket.

0

Powiedz proszę co tak zraziło Cię w JSF. Ja dość dużo pisałem w JSF (najpierw 1.2 i IceFaces, potem projekt zmigrowany do JSF 2.x i IceFaces compat) oraz sporo w 2.2 z PrimeFaces.

Nie takie małe projekty, jeden z nich na ponad 80k linii kodu samej Javy. Moim zdaniem pisanie w JSF jest banalnie proste, jednak krzywa uczenia jest dość długa w stosunku do innych technologii: po prostu framework ten ma dość dużo opcji, jak np. niezależy @ViewScoped w każdej zakładce, czego bardzo brakuje w ASP.NET.

Nie rozumiem w czym wicket jest lepszy od np. gołego JSF 2.2 i facelets: w tym momencie też mogę sobie dobrać customowe frameworki JavaScript i tworzyć własne komponenty jeśli mam na to umiejętności, czas i budżet.

2

Ciekawy artykuł:
http://blog.brunoborges.com.br/2013/01/reasons-to-why-im-reconsidering-jsf.html

Powiem dlaczego lubię JSF:

  1. Integracja z EJB3 out-of-box.
  2. Banalna integracja ze Spring Security (również przy CDI).
  3. PrimeFaces: dużo gotowych komponentów mocno wykorzystujących możliwości klienta.
  4. Dodatki jak np. OmniFaces pozwalające na ograniczenie JSF boilerplate jak np. wołanie do kontekstu. Do tego mnóstwo converterów.
  5. W przypadku starego, praktycznego przemysłowego projektu migrowałem IceFaces 1.8 do JSF 2.2 po zmianie JEE5 na JEE7 i wszystko działa (IceFaces, dla odmiany bardziej server-side odmiana JSF z AJAX push). Działa, rónież na CDI.
  6. Łatwość tworzenia nowych komponentów w JSF2.
  7. Jeśli chcę zbudować otwartą aplikację webowa z bookmarkable RESTful URL to się da: mogę wykorzystać PrettyFaces.
  8. Świetne wsparcie IDE.
  9. Dużo ofert pracy.
  10. Banalne tworzenie szablonów z facelets, nie to co kiedyś z JSF 1.2/ JSP (JSF 1.2 z facelet + IceFaces jest już spoko).
  11. Duża społeczność skupiona np. wokół PrimeFaces.

Wady:

  1. Dobre pół roku zajęło mi nabranie przemysłowej sprawności w JSF (łącznie z nauką, migracjami JSF 1.2, JSF 2.2 itp.).
  2. Po roku uważam, że jeszcze muszę sporo się nauczyć: jest to bardziej rozbudowane niż np. Spring MVC (ale tam nauka jest zrzucona na frameworki jak extJS czy Dojo, w praktyce moim zdaniem może trwać dłużej).
  3. Dużo pojęć: można się pogubić kiedy używać JSF Managed Beans, a kiedy CDI (do tego dochodzą zagadnienia czy mamy serwer aplikacji, czy kontener serveletow, czy integrujemy ze springiem czy jee).
  4. Nie widzę realnego ograniczenia dlaczego JSF miało by słabo się nadawać na moją nową aplikację.
  5. Istnieje dużo różnych odmian (ADF, vanilla, RichFaces, PrimeFaces, IceFaces), implementacji (Mojarra, IceFaces), co utrudnia wejście w temat.

Tak naprawdę nie zamierzam uczyć się nowych frameworków webowych, a skupić się na poznaniu jQuery, CSS, HTML5 i tworzeniu własnych komponentów dla JSF. Jako realną alternatywę wartą poznania uważam AngularJS dla zupełnie innego typu aplikacji, z którymi komunikował się będę za pomocą REST (tworząc np. transakcyjny backend w EJB) i to zamierzam zainwestować swój czas w przyszłości obok dalszej nauki JSF.

0

Napisałem:

implementacji (Mojarra, IceFaces)
miałem na myśli (Mojarra, MyFaces).
http://myfaces.apache.org/

0
mk761203 napisał(a):

(...) Czy ktoś z Was używał JSF choćby w średniej wielkości aplikacji?

Firma, w której byłem - tak.

Do głównych zalet JSF należy dodać, że ten framework wchodzi w skład standardu JEE.

1

Aktualnie w firmie mamy średniej wielkości aplikację w JSF + primeface i muszę przyznać, że nie ma tragedii....
Oczywiście jak klient sobie życzy aby np w tabelce była możliwość sortowania po wielu kolumnach a np primefaces nie daje takich możliwości to to jest wtedy dramat
Oczywiście graficy rwą włosy z głowy aby to wystylować....ale dają rade.

Jak coś moge podać linka na priv do aplikacji

Dla mnie najlepszy zestaw to
Spring MVC + Freemearker +Bootstrap
lub Spring Rest + AngularJS + Bootstrap
lub Play Framowrk + AngularJS + Bootstrap

Żadnych scopów, powalonych cyklów życia, VIewExpiredException, wielokrotnych wołania geterów z modelu ..ble

0

@Szczery:

  1. Jakiej wersji PrimeFaces używacie?
  2. Integrujecie z JEE czy ze Springiem?
  3. Co do AngularJS, skąd bieżecie gotowe komponenty? Jak będę miał chwilę chcę sobie zbudować proof-of-concept i tak zastanawiam się czy jest coś gotowego porównywalnego do:
    http://www.primefaces.org/showcase/
    Spodziewam się raczej drobnych elementów w stylu jQueryUI.
  4. Jak zabezpiecza się aplikacje AngularJS (w moim proof-of-concept chcę postawić na SSL + basic authentication)?
0
  1. Primefaces 3.4.x
  2. GUI: JSF + CDI, Biznes: Spring
  3. AngularUI + NgGrid + Bootstrap
  4. Dokładnie jak piszesz. Dokładasz do anuglara interceptor http/https który jaki widzi ze kod błędu to 401 to pokazuje strone logowania
0

Ad 2. A więc się da. Kiedyś muszę spróbować takiej konfigurajcji. Zwłaszcza, że w planach mam pisanie aplikacji proof-of-concept, aby pobieżnie zapoznać się z możliwościami Hadoop, a z tego co widzę Spring-Data to ładnie wspiera.
Zastanawiam się jeszcze nad wariantem TomEE, gdyż tam podobno łatwo rozwiązali integracje Spring -> OpenEJB, ale jeszcze nie testowałem.

Co do JSF Scopes: jak zaczynałem pracę miałem z tym straszny problem i często źle ich używałem. Jednak w tej chwili uważam, że to bardzo wygodny mechanizm, zwłaszcza że to tak naprawdę nakładka na standardowe scopes dostępne w Servletach. Do tego możliwość łatwego dependency injection pozwala na pisanie bardzo ładnego, modułowego kodu, zgodnie z zasadą pojedynczej odpowiedzialności. Zarządzanie sesją jest łatwe: jak trzeba można usunąć z niej co trzeba. I tak sesji używa się raczej rzadko, najczęściej wykorzystuje się @ViewScoped. Flash też jest dostępny, jak trzeba np. przekazać obiekt między dwoma redirectami i dostęp do niego jest banalny (Faces.getFlash()). Z reguły mam tak, że dla bardzo skomplikowanego widoku mam np. 10 różnych Managed Beans i każdy zajmuje się innym przypadkiem użycia (np. jak jest skomplikowany widok). Kod jest elegancki, modułowy, łatwy w utrzymaniu. Ale początki były trudne.

Co do stylizowania, przerabiałem to z IceFace 1.8, które wygląda obrzydliwie. To się spokojnie da zrobić, wystarczy potworzyć odpowiednie klasy CSS i mieć osobę, która potrafi to robić. Jeśli style to za mało da się podłączyć jQuery i zbudować customową funkcjonalność. W PrimeFaces jest już dużo łatwiej: jQuery jest dostępne out-of-box, a pisanie logiki walidacji, nawet zgodnej z BeanValidation po stronie klienta jest łatwe.

W tej chwili jest już PrimeFaces 5.0, a całość rozwija się bardzo dynamicznie: wciąż dodają nowe opcje i dopracowywują stare.

0

jak zaczynałem zabawe z javą enterprise to na pierwszy ogień, zaraz po servletach itd. poszedł JSF. faktycznie troche mnie irytował, ale mam wrażenie, że każdego tak na początku :P może po czasie sie człowiek przyzwyczaja

a tak btw mam pytanie:
wtedy jak zaczynałem, wybieralem miedzy JSF a Vaadinem; słyszałem, że GWT (na ktorym oparty jest vaadin) jest lipne do granic, dlatego pytam co byscie na chwile obecna wybrali, gdybyscie chcieli poznać nowy frontend-framework, JSF czy Vaadina?

0

Używałem w jednym z banków i w sofcie connectora duża firma-bank. Pomysł dobry, ale wykonanie koślawe. Jedyna zaleta, że jest w tym dużo softu popisane zatem będzie pracy na lata.

Obecnie klepię apkę, gdzie mamy Springa + klienta okienkowego w C#, ale jak miałbym go zamienić na webowego to zapewne angular.

0

Wracając to wątku głównego - generalnie nie musicie mnie przekonywać co do JSF, jest jaki jest, ale dla mnie jest czymś naturalnym do kompletu w JEE, więc z chęcią bym skorzystał.
Bug, ktory z łatwością można zreprodukować GF4.0(build 89):

<h:form>
    <h:inputText value="#{bean.text}"/>
    <h:commandButton value="Submit"/>
</h:form>
@ManagedBean
@RequestScoped
public class Bean implements Serializable {

    private String text;

    private void printUic() {
        UIComponent uic = UIComponent.getCurrentComponent(FacesContext.getCurrentInstance());
        System.out.println(uic.getClass());
    }

    public String getText() {
        printUic();
        return text;
    }

    public void setText(String text) {
        printUic();
        this.text = text;
    }
}

W momencie wywołania gettera printUic printuje "class javax.faces.component.html.HtmlInputText" a setter "class javax.faces.component.html.HtmlBody".
Jak widać getter zwraca prawidłowo komponent, który go wywołuje, a setter zwraca parenta.
Wiedza o samym komponencie nie jest mi potrzebna, ale wołam na nim później getAttributes(), bo przechowuje tam dane kontekstowe, żeby wiedzieć, z którego pola w gridzie przychodzi dany set/get.
Używam GF4.0 standardowo była w nim mojarra 2.2.0 zrobiłem upgrade do 2.2.8-01 i nic sie nie zmieniło, testowałem też na ManagedBeans i CDI i jest tak samo. Problem jest opisywany w sieci już w 2010.
Może przetestuje jeszcze myFaces, jak na razie tej implementacji nie dotykałem.

Na w/w znalazłem workaround, więc OK, ale dziwi mnie dlaczego pomimo upływu 4ech lat, nie jest to nadal nafiksowane, i stąd się wzięło pytanie "czy ktoś używa JSF?" :)

Mam jeszcze jeden, dużo bardziej upierdliwy, problem, ale nie udało mi się go łatwo zreprodukować.

0

Nie rozumiem po co serializowac request scope, skoro zostanie i tak odtworzony przy nastepnym kliknieciu? To ma sens dla ViewScoped (jak chcesz przechowywac stan widoku) lub w SessionScope.

Kod który przedstawiłeś wydaje mi się dość krzywy (jakiś workaround?), raczej tak się nie pisze w JSF (przynajmniej my nie potrzebowaliśmy odwoływać się do koponentów w ten dziwny sposób).

Dlaczego nie chcesz używać zwykłych bindingów? Ja w ten sposób rozwiązywałem z którego komponentu w gridzie przychodzi element (przed servlet 3.0): customowe metody UIHtmlDataTable. W JSF 2.2 zamaist tego często po prostu wołam metody w EL z parametrem, bindingow uzywam rzadziej (bo sa IMO mniej czytelne), ale zdarza sie, gdy z jakiegos powodu chce odwolac sie do konkretnego komponentu z modelu.

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;

@ManagedBean
@RequestScoped
public class Bean {
 
    private String text;
    private UIComponent uiText;
 
    private void printUic() {
        System.out.println(uiText.getClass());
    }

    public UIComponent getUiText() {
        return uiText;
    }

    public void setUiText(UIComponent uiText) {
        this.uiText = uiText;
    }
 
    public String getText() {
        printUic();
        return text;
    }
 
    public void setText(String text) {
        printUic();
        this.text = text;
    }
}
        <h:form>
            <h:inputText value="#{bean.text}"
                         binding="#{bean.uiText}"/>
            <h:commandButton value="Submit"/>
        </h:form>
0

Co do serializacji, to faktycznie nie jest tu potrzebna, ale też nie ma żadnego wpływu na przykład (trafiła do przykładu przez przypadek).

Rozumiem, że każdy problem można rozwiązać na kilka sposobów, ale i tak uważam, że to co napisałem powinno działać. Jedyne co mnie przekonuje to to, że być może mało kto stosuje taki flow jak ja i stąd to nigdy nie zostało nafiksowane, niemniej to był tylko przykład, żeby pozakać że nie działa zgodnie z oczekiwaniem.
A jakbyś rozwiązał taki przykład, w którym czytam z atrribsów i to nie będzie działało właśnie z powodu opisanego w moim poprzednim poście:

<h:panelGrid columns="#{c.selectedBranches.size()+1}">
    <c:forEach items="#{c.users}" var="user">
        <h:outputText value="#{user}" converter="UserDataConverter"/>
        <f:attribute name="user" value="#{user}"/>
        <c:forEach items="#{c.selectedBranches}" var="branch">
            <h:panelGroup>
                <p:selectManyButton value="#{c.permisions}" converter="RepoConverter">
                    <f:attribute name="branch" value="#{branch}"/>
                    <f:attribute name="user" value="#{user}"/>
                    <f:selectItems value="#{branch.repos}" var="repo" itemLabel="#{repo.shortName}"/>
                </p:selectManyButton>
            </h:panelGroup>
        </c:forEach>    
    </c:forEach>
</h:panelGrid>

Jakbyś to przerobił na podejście z bindingsami, pytam tu konkretnie o selectManyButton, który występuje po kilka razy w każdym wierszu tabeli?
Mam tutaj f:attribute, żeby w momencie gdy jest wywoływany setter od selectManyButton wiedzieć, z którego wiersza i kolumny został wywołany. Ilość wierszy i kolumn jest dynamiczna.
Może po prostu źle do tego podchodze...

1

Prawda jest taka, że żaden produkt open-source nie jest idealny: ale JSF jest bardzo często używany, więc naprawdę krytyczne bugi są łatane (co nie znaczy, że zawsze mogłoby być lepiej).

Załaduj jeszcze plik z modelem to spróbuje to u siebie uruchomić (proteza jakaś zahardkodowana lista zamiast bazy). Takiego przypadku nigdy nie robiłem, ale chętnie rzucę okiem.

Na pierwszy rzut oka nie podoba mi się jedna rzecz: tagi z przestrzeni c. Raczej nie powinno ich się używać z JSF poniewż cykl życia JSF i JSTL to nie jest to samo. Jak chcę wykonać taką pętle to zawsze używam ui:repeat z przestrzeni facelets. Od tego bym zaczął.

http://www.ninthavenue.com.au/jsf-c-foreach-vs-ui-repeat

0

@student911 dzięki za przypomnienie odnośnie przestrzeni c:, w sumie tak jak pisałem miałem przerwę i po powrocie do JSF jakoś napatoczyły mi się złe tagi (i w ten sposób popełniłem szkolny błąd), po przejściu na ui:repeat, drugi z problemów, który miałem (nieopisany tutaj) odszedł w niepamięć.

Co do f:attribute to jest bug i tyle, będę to ticketował.

Oprócz tego znalazłem że jako alternatywę dla f:attribute mógłbym użyć binding dla h:dataTable i również uzyskać dynamiczną tabelę. Ale to rozwiązanie zakręcone w mojej o cenie i błedogenne, więc pozostałem przy ui:repeat i f:attribute z małym workaroundem, do czasu gdy naprawią f:attribute :

<p:selectManyButton value="#{c.permisions}" converter="RepoConverter">
    <f:attribute name="branch" value="#{branch}"/>
    <f:attribute name="user" value="#{user}"/>
    <f:selectItems value="#{branch.repos}" var="repo" itemLabel="#{repo.shortName}"/>
</p:selectManyButton>

trzeba zamienić na:

<h:panelGroup>
    <f:attribute name="branch" value="#{branch}"/>
    <f:attribute name="user" value="#{user}"/>
    <p:selectManyButton value="#{c.permisions}" converter="RepoConverter">
        <f:attribute name="branch" value="#{branch}"/>
        <f:attribute name="user" value="#{user}"/>
        <f:selectItems value="#{branch.repos}" var="repo" itemLabel="#{repo.shortName}"/>
    </p:selectManyButton>
</h:panelGroup>

1 użytkowników online, w tym zalogowanych: 0, gości: 1