Strony błędów w JSF i co z tego wynikło

Jak pisałem w poprzednim wpisie – na poważnie rozpocząłem deployment aplikacji napisanej w JSF na serwerze hostingowym. Siłą rzeczy powiedzenia programistów “u mnie działa” nie wzięły się znikąd – fakt – u mnie działa, na serwerze już jednak niekoniecznie.

Ostatnio link do mojego bloga pojawia się w masie miejsc. Wzrost ilości odwiedzin jest łatwo widoczny – stąd też nie wszyscy mogą być świadomi, iż do tej pory nie miałem większych problemów z hostowaniem swojej aplikacji napisanej w GrailsHowToJava. Jednakże dorzucenie na serwer kolejnego programistycznego projektu – ProgramBash zaowocowało pewnymi komplikacjami, które zajęły mnie przez ostatnie dni.

Pierwsza rzecz warta wzmianki to fakt, iż oszalał mi NetBeans. Moja sprawdzona wersja 6.5.1 zaczęła w pewnym momencie (pomimo braku zmian w kodzie) wyrzucać przy deploymencie na lokalnym Tomcacie wyjątek o niemożliwości dostania się do elementów layoutu w katalogu WEB-INF i wpadała w kaskadę wyjątków, która skutecznie zabierała 100% procesora i trzeba było zabijać proces IDE i serwera. Z konieczności zatem zdecydowałem się na zmiany, które zaowocowały instalacją wersji 6.7.1 – na razie działa stabilnie, oby tak dalej.

Pisałem również wcześniej, iż w tym projekcie użyję Postgresa. Jednakże zanim doczekam się go na serwerze pewnie jeszcze trochę minie – zatem z konieczności development toczy się na starym dobrym MySQL. I nie byłoby w tym nic strasznego gdyby nie fakt, iż o ile HowToJava pięknie sobie z bazą radzi, o tyle ProgramBash zaczął “wysiadać”. Konkretnie aplikacja wyrzucała wyjątki mówiące o zakończeniu połączenia.

Wyruszyłem na mały research. Uzbrojony w nowe IDE mogłem zabrać się za rozwiązywanie problemu, który dość często uniemożliwiał spojrzenie na aplikację, gdyż dostawało się komunikat błędu. Zapuściłem się w otchłań internetu z wujkiem Google i oto co się okazało – Hibernate standardowo musi zostać stuningowany, aby nadawał się do celów produkcyjnych (szkoda tylko, że moja mądra książka o Hibernate jakoś o tym nie wspomina). Oto urywek z dokumentacji:

Hibernate’s own connection pooling algorithm is, however, quite rudimentary. It is intended to help you get started and is not intended for use in a production system, or even for performance testing. You should use a third party pool for best performance and stability.

No dobra, zatem trzeba pomyśleć co z tym fantem zrobić. Ano okazuje się, że należy zainteresować się dostarczanym wraz z Hibernate pakietem/biblioteką o nazwie C3P0. Nadpisuje ona domyślne ustawienia connection pools i umożliwia zabawę na bardziej wymyślnym placu zabaw. Zatem do naszego pliku hibernate.cfg.xml należy dorzucić następujący fragment kodu:

    <property name="hibernate.c3p0.min_size">5</property>
    <property name="hibernate.c3p0.max_size">20</property>
    <property name="hibernate.c3p0.timeout">300</property>
    <property name="hibernate.c3p0.max_statements">50</property>
    <property name="hibernate.c3p0.idle_test_period">3000</property>
    <property name="current_session_context_class">thread</property> 

I w ten sposób problemy z niestabilnością połączenia rozwiązują się w mgnieniu oka. Hibernate ponoć tę bibliotekę posiada – jednakże w wersji dostarczanej przez NetBeans jakoś jej nie podpięto. Zatem trzeba dodać kolejnego JARa do naszych bibliotek w aplikacji.

Deployment i działa. Póki co 🙂 Jednakże wraz z wyrzucaniem błędów w połączeniu naszła mnie myśl o zmianie wyświetlanej strony błędów. Wszak wyrzucenie StackTrace użytkownikowi końcowemu nie jest raczej zachowaniem pożądanym. Rzecz jasna wziąłem się za poprawę tego stanu rzeczy.

Sprawa wydawała się prosta. Obsługę błędów w JSF można rozwiązać na dwa sposoby. Albo dodać stosowne dyrektywy do strony widoku (dobre chyba w rozwiązaniach typu HelloWorld), albo też zadeklarować rzecz w deskryptorze wdrożenia. Oto jak wygląda plik web.xml po utworzeniu projektu w JSF:

 <error-page>
        <exception-type>javax.faces.FacesException</exception-type>
         <location>/servlet/ExceptionHandlerServlet</location>
    </error-page>

    <error-page>
        <exception-type>javax.servlet.ServletException</exception-type>
        <location>/servlet/ExceptionHandlerServlet</location>
    </error-page>
    <error-page>
        <exception-type>java.io.IOException</exception-type>
        <location>/servlet/ExceptionHandlerServlet</location>
    </error-page>
    
    <error-page>
        <exception-type>com.sun.rave.web.ui.appbase.ApplicationException</exception-type>
        <location>/servlet/ExceptionHandlerServlet</location>
    </error-page>

    <servlet-mapping>
        <servlet-name>ExceptionHandlerServlet</servlet-name>
        <url-pattern>/error/ExceptionHandler</url-pattern>
    </servlet-mapping>

   <servlet>
        <servlet-name>ExceptionHandlerServlet</servlet-name>
        <servlet-class>com.sun.errorhandler.ExceptionHandler</servlet-class>
              <init-param>
            <param-name>errorHost</param-name>
            <param-value>localhost</param-value>
        </init-param>
        <init-param>
            <param-name>errorPort</param-name>
            <param-value>24444</param-value>
        </init-param>
    </servlet>

I w tym momencie wszystkie błędy są obsługiwane przez standardowe widoki JSF. By zmienić ten stan rzeczy najprościej jest po prostu utworzyć stronę widoku (HTML, JSP) i podlinkować do niej obsługę błędów poprzez odpowiednie nadanie wartości parametru location. Powinno to wyglądać zatem tak:

<error-page>
        <exception-type>com.sun.rave.web.ui.appbase.ApplicationException</exception-type>
        <location>/error.html</location>
    </error-page>

I w ten sposób wyszczególniony wyjątek będzie obsługiwany przez naszą stronę. Najlepiej jest zdefiniować jedną stronę błędów, a pod nią podpiąć wszystkie błędy. Najlepiej zatem tak:

<error-page>
        <exception-type>java.lang.Throwable</exception-type>
        <location>/error.html</location>
    </error-page>

I życie od razu staje się przyjemniejsze. Istnieje też druga wersja – można wyszczególnić kod błędu (konkretnie kodów HTTP). Czyli by ładnie obsłużyć stronę 404 (nie znaleziono zasobu) można zrobić coś takiego:

<error-page>
        <error-code>404</error-code>
        <location>/error404.html</location>
    </error-page>

I w taki oto sposób ProgramBash przybliżył się do działającej aplikacji. Mam nadzieję, że w przyszłym wpisie zajmę się już czymś bardziej konkretnym – wstępnie myślę o rejestracji i logowaniu. Na otarcie łez można rzucić okiem na użycie RichFaces klikając na link O AUTORZE.

Advertisements

3 thoughts on “Strony błędów w JSF i co z tego wynikło

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s