wtorek, 13 kwietnia 2010

Spring Framework 3.0 Tutorial - cz 1 - przygotowanie projektu, witajświecie

Zanim przystąpimy do tworzenia projektu warto odpowiednio przygotować sobie zaplecze techniczne. Z racji, że w eclipse pisze znaczna część firm (przynajmniej polskich), a ja jeszcze z niego nie korzystałem w tego typu projektach postanowiłem, że to będzie dobry moment by się z nim zmierzyć.
Eclipse wyposażony zostanie dodatkowo we wtyczkę m2Eclipse która pomoże mi w zarządzaniu maven-em. Aplikacja uruchomiona zostanie na kontenerze aplikacji Tomcat, a dane przechowam w bazie PostreSQL. Z racji, że źródła umieszczane będą w zewnętrznym repozytorium opartym o GIT potrzebny jest też ten właśnie program, ja preferuję korzystać z gita poprzez konsolę, oczywiście jeśli ktoś woli można doinstalować odpowiednią wtyczkę bądź nakładkę graficzną.

Co przyda się przy tworzeniu:

Podstawowe założenia


Aplikacja składać się będzie z dwóch modułów, panelu administracyjnego dostępnego tylko i wyłącznie dla użytkowników z poziomem dostępu ADMIN oraz części otwartej do której dostęp będą mieli wszyscy internauci (za wyjątkiem obszarów które będą wymagały zalogowania się z poziomem dostępu CLIENT). Podział taki można wykonać na dwa sposoby, pierwszym jest stworzenie jednego projektu w którym dokonamy logicznego podziału widoków jak i kontrolerów na panel administracyjny oraz strefę otwartą, spring security dodatkowo zabezpieczy wejście. Wyniki składane będą przez sitemesh dzięki któremu można stworzyć oddzielny layout dla panelu administracyjnego oraz dla części otwartej. Jedynym plusem tego rozwiązania jest łatwość operowania plikami w projekcie(o ile nie jest duży), wszystko mamy w jednym miejscu dzięki czemu nie trzeba przechodzić między projektami i szukać plików jeśli tylko chcemy coś zmienić. Niestety przeciw temu rozwiązaniu jest cała reszta, kod staje się mniej czytelny, potrzebne są dodatkowe obejścia które rozdzielać będą żądania do panelu administracyjnego jak i strony klienckiej, nie możliwe jest również umieszczenie osobno części administracyjnej na np. naszym serwerze wewnętrznym. Pomimo tego, że pliki poukładane mamy w jednym projekcie co z początku może wydawać się plusem w większych projektach staje się zmorą, gdyż większa ilość plików powoduje utrudnienia w odszukaniu tego który chcemy zmodyfikować (wiem, przeżyłem to na własnej skórze).

Drugim rozwiązaniem jest stworzenie osobnych projektów dla panelu administracyjnego oraz części klienckiej. Dzięki takiemu rozwiązaniu zachowujemy pewien ład i porządek w strukturze folderów projektów oraz plikach (mniej plików mniej problemu). Dzięki rozdzieleniu plików konfiguracyjnych zyskujemy większą elastyczność oraz możliwość łatwiejszego dostosowania ustawień. Część wspólna obu projektów (klasy związane z obiektami bazy danych) trzymane są w projekcie który dołączany jest jako biblioteka. Mój wybór padł właśnie na tą metodę.

Podsumowując, utworzone zostaną 3 projekty: bookstore, bookstore-admin oraz bookstore-lib.

Zaczynamy


Projekt zaczniemy od stworzenia prostej strony a'la Witaj Świecie!. Aby zacząć całą zabawę otwieramy Eclipse i tworzymy nowy projekt typu "Dynamic Web Project" (File -> New -> Project... -> Web -> Dynamic Web Project). Następnie wpisujemy nazwę projektu i klikamy finish.
Gdy nasz projekt zostanie utworzony musimy dodać do niego obsługę mavena. Jeśli mamy zainstalowaną wtyczkę m2Eclipse wystarczy kliknąć prawym klawiszem myszy na nasz projekt i wybrać odpowiednio Maven -> Enable Dependency Managment. Plugin doda do naszego projektu plik pom.xml, który zawiera wszelkie informacje potrzebne dla maven-a. W strukturze projektu możemy zauważyć folder WebContent który zawierać będzie pliki konfiguracyjne, tłumaczące, pliki jsp oraz wszystko co potrzebne do wyświetlania wyników. Ponieważ nazwa folderu nie przypadła mi do gustu zamieniłem ją na war (co będziecie mogli zobaczyć po pobraniu projektu).


Dodawanie zależności


Pierwszą rzeczą jaką robię w nowo utworzonym projekcie jest dodanie podstawowych zależności. Z mojej strony są to takie biblioteki jak sitemesh 3 (UWAGA! - wydanie alpha, mam nadzieję, że działa), spring-web, spring-context, czy też spring-webmvc; czyli wszystko co potrzebne na dobry początek.
Na koniec dodaję biblioteki JUnit oraz Mockito które posłużą do testowania aplikacji. Ponieważ biblioteki te nie będą nam potrzebne w działającej aplikacji, warto zaznaczyć w ich zakresie (ang. scope) opcje "test" dzięki czemu będą dołączane tylko podczas testów.


Konfiguracja


Podstawowa konfiguracja obejmuje dwa pliki, najważniejszy web.xml oraz podstawowa konfiguracja spring-a i głównych servletów w pliku web-servlet.xmlPlik web.xml jest jak najbardziej zwyczajny, podana jest lokalizacja pliku web-servlet.xml, skonfigurowane zostały listenery, a także servlety wraz z mapowaniem.

web.xml:

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

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

id="b0ok" version="2.5">

<display-name>bookstore</display-name>

<!--

wskazujemy lokalizacje plikow konfiguracyjnych

-->

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

/WEB-INF/web-servlet.xml

</param-value>

</context-param>

<listener>

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

</listener>

<!--

tworzymy servlet ktory obslugiwac bedzie nasze zapytania

-->

<servlet>

<servlet-name>web</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

</servlet>

<!--

ustalamy ze nasz servlet obslugiwac bedzie tylko zapytania konczace

sie rozszerzeniem *.html

-->

<servlet-mapping>

<servlet-name>web</servlet-name>

<url-pattern>*.html</url-pattern>

</servlet-mapping>

<!--

ustalamy, jakie pliki beda ladowane gdy aplikacja dostanie zapyanie

"/" (np. http://example.com/)

-->

<welcome-file-list>

<welcome-file>redirect.jsp</welcome-file>

</welcome-file-list>

</web-app>

Dodatkowo wskazaliśmy plik który jest ładowany, gdy serwer otrzyma żądanie "/" (czyli strona startowa), w tym przypadku jest to załadowanie pliku redirect.jsp który przekieruje nas na stronę główną:

redirect.jsp:

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

<jsp:forward page="/index.html" />

Update 1:
Jak trafnie zauważył
Chlebik (zob. komentarz), zamiast redirect.jsp możemy śmiało napisać "index.html" wtedy spring wykona akcję przeznaczoną dla żądania "/", przy czym, należy dodać plik index.html do głównego katalogu (war/webContent) aplikacji, może być nawet pusty, ważne by spring wiedział, że jest. Za podpowiedź dziękuję.

Plik web-servlet.xml na początek wskażemy gdzie aplikacja ma szukać kontrolerów, oraz zaznaczymy, że będzie ona działała w oparciu o adnotacje.
web-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.darekzon.bookstore.controller" />
<context:annotation-config />
<context:spring-configured />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

W sekcji <context:component-scan> wskazujemy, który pakiet ma być skanowany w poszukiwaniu kontrolerów (klas z adnotacją @Controller), jeśli chcemy możemy wskazać więcej jak jeden pakiet przy czym trzeba pamiętać, że nazwy klas muszę się różnić, więc jeśli mamy IndexController w naszym pakiecie to w pakiecie com.darekzon.bookstore.controller musimy umieścić Index2Controller.

Ach, no i ostatni blok wskazuje gdzie spring ma szukać plików jsp za pomocą których generować będzie wyniki.

Pierwszy kontroler


Aplikacja skonfigurowana, pierwszy kontroler będzie wyświetlał legendarny napis "Witaj świecie!". Sam kontroler jest wyjątkowo prosty, posiada tylko jedną metodę, która zwraca obiekt typu "ModelAndView" przechowujący nazwę widoku do wyrenderowania. Kontroler zapisany jest w pliku IndexController.java (konwencja nazewnicza nie jest obowiązkowa) a jego zawartość przedstawia się jak poniżej:

package com.darekzon.bookstore.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

@RequestMapping(value = "/index")
public ModelAndView index(){
ModelAndView mav = new ModelAndView("index/index");

return mav;
}

}

Warto tutaj zwrócić uwagę na 3 rzeczy:
  1. Każdy kontroler powinien mieć adnotację @Controller, dzięki temu spring podczas skanowania pakietów (zob. konfigurację web-servlet.xml ↑)
  2. Spring szuka metody którą ma wykonać na podstawie adnotacji @RequestMapping, w naszym przypadku czeka aż wywołamy żądanie "/index",  warto dodać, że nie można dodać dwóch metod z tą samą wartością tej adnotacji (podczas uruchamiania wyskoczy wyjątek)
  3. W tym przypadku zwracamy obiekt ModelAndView który zawiera nazwę pliku widoków który posłuży do renderowania wyników, plik widoku powinien znajdować się w folderze /views/index/index.jsp, czyli według ustawień w pliku web-servlet.xml oraz wartości zwracanej przez metodę.

Kontroler gotowy, pora na widok który będzie renderowany, ponieważ będzie to wyświetlenie tekstu "Witaj świecie!" plik ten nie jest skomplikowany (kolejne na pewno wniosą coś nowego w tej kwestii), a jego zawartość przedstawia się następująco:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<title>Index</title>
</head>
<body>
Witaj świecie!
</body>
</html>

Tu tłumaczyć raczej nic nie trzeba, no może poza faktem pisania kodu całej strony w wyniku, ale o tym za chwilę.

Sitemesh i konfiguracja szablonów


Sitemesh to ciekawy projekt dzięki któremu znacznie ułatwimy sobie zabawę z wyglądem strony, jego głównym zadaniem jest sklejanie widoków wygenerowanych przez "aplikację" z ogólnym szablonem, oraz doklejanie części wspólnych między widokami (np. mamy oddzielny layout dla strony głównej, kontaktu oraz reszty serwisu, przy czym menu jest takie samo).


W projekcie użyję najnowszej (3.0alpha-1) wersji sitemesh-a, ponieważ nie jest to jeszcze stabilna wersja (nawet nie beta), zalecam do poważnych projektów używać wersję 2.4 dostępną pod starą stroną projektu.

Konfiguracja sitemesh-a może odbywać się na dwa sposoby: klasa Java rozszerzająca klasę ConfigurableSiteMeshFilter lub plik XML, ponieważ z niewiadomych przyczyn konfiguracja przez XML mi nie działa skupię się na konfigurowaniu z wykorzystaniem JAVY.

W pliku web.xml musimy dodać filtry które będą go uruchamiać dla każdego żądania (przynajmniej w moim przypadku), wskazując przy tym naszą klasę konfigurującą, kod wygląda następująco:

<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.darekzon.bookstore.filter.Sitemesh</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Zaś klasa Sitemesh konfigurująca ma postać:

public class Sitemeshextends ConfigurableSiteMeshFilter {
@Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/views/layout/default.jsp");
}
}

Działanie proste, przechwytujemy wyniki żądań wysłanych do aplikacji, i "kompilujemy" je z dekoratorem z pliku "/views/layout/default.jsp" (UWAGA! powinno podawać się pliki z rozszerzeniami innymi od tych zdefiniowanych w filtrach w pliku web.xml - w moim wypadku .html).

W tej chwili dekorator wygląda następująco:

<!doctype html>
<html lang="pl" dir="ltr">
<head>
<title><sitemesh:write property='title' /> - BookStore</title>
<link rel="stylesheet" href="/resource/style/default.css" />
<sitemesh:write property='head' />
</head>
<body>
<sitemesh:write property='body' />
</body>
</html>

Podczas renderowania sitemesh otwiera dekorator oraz plik wynikowy kontrolera oraz je scala (nie chodzi o język programowania), w miejscu tagu <sitemesh:write property='title' /> wstawia wartość tagu <title> wyrenderowanego wyniku, w miejsce tagu <sitemesh:write property='head' /> wartość tagu head (za wyjątkiem title), a tam gdzie pyta o <sitemesh:write property='body' />, wszystko co znajduje się w body. Proste, a co ważne wygodne.

CDN...


W następnej części zajmiemy się panelem administracyjnym oraz jego zabezpieczeniem, stworzymy również cały layout tego panelu wykorzystując bardziej zaawansowane techniki dostarczane przez JSP i Sitemesh.Tymczasem zapraszam do pozostawiania komentarzy, wszelkie postaram się wziąć pod uwagę.

Jak pobrać projekt


Projekt został umieszczony na serwerach GitHub.com. Adres bezpośredni do projektu: https://github.com/darek/bookstore.
Dodatkowo zostało uruchomione repozytorium GIT dla wszystkich chętnych i dostępny jest pod adresem: git://github.com/darek/bookstore.git





1. Diagram pobrany ze strony http://www.sitemesh.org/overview.html

47 komentarzy:

  1. Elegancko, dokladnie cos takiego tworze u siebie (jak juz pisalem w komentarzu do poprzedniego wpisu). Dodam, ze mozna inaczej zrobic sztuczke z plikem startowym (zapraszam pod koniec tego wpisu - http://chlebik.wordpress.com/2010/04/12/scjptester-w-wersji-helloworld/ ), zas z kolei bardzo fajnym pomyslem jest uzywanie adnotacji do ogarniecia kontrolerow, musze na ten temat wiecej doczytac.

    OdpowiedzUsuń
  2. Dzięki wielkie. Nareszcie coś łopatologicznie wytłumaczone :). Jak dla początkującego programisty JEE po prostu rewelacja. Oby kolejne części były tak samo (albo jeszcze lepiej :)) opisane.

    OdpowiedzUsuń
  3. @Chlebik
    Dzięki, przetestuję w domu i poprawię

    @Piotr Kosmowski
    Planuję zachować dotychczasową formę tutoriala, może użyję kilku mądrzejszych wyrazów, ale nie więcej


    -
    Swoją drogą, zastanawiam się czy nie użyć do panelu administracyjnego frameworka vaadin, kusi, ale to jeszcze zobaczę.

    OdpowiedzUsuń
  4. Super , polska blogosfera nie zawodzi :) jak tylko skończę studia i magisterkę to biorę się m.in za ten framework :P mam już dość php ;)

    OdpowiedzUsuń
  5. [...] Spring Framework 3.0 Tutorial – cz 1 – przygotowanie projektu, witaj świecie [...]

    OdpowiedzUsuń
  6. [...] pierwszej części tutorialu wspomniałem iż Sitemesh służy do składania stron w całość, dzięki niemu możemy [...]

    OdpowiedzUsuń
  7. [...] http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie [...]

    OdpowiedzUsuń
  8. [...] wiadomości z tego serwisu Follow us on Twitter 72 śledzących RSS Feed 375 czytelników Spring Framework 3.0 Tutorial – cz 1 – przygotowanie projektu, witaj świecie 1 głosuj! Zanim przystąpimy do tworzenia projektu warto odpowiednio przygotować sobie [...]

    OdpowiedzUsuń
  9. Mam pytanie.
    W katalogu war (zmienionym z WebContent) trzymasz WEB-INF i "resztę".
    Jak mi parę razy udało się coś stworzyć, to zawsze trzymałem WEB-INF w src/main/webapp/WEB-INF. Czy to ma jakieś znaczenie czy to tylko konwencja? Chyba to nie ma znaczenia że używałem pluginu Tomcata w Eclipsie żeby szybko deployować i podglądać wyniki? Oczywiście tak samo był to Dynamic Web Project z Mavenem.
    Dzięki!

    OdpowiedzUsuń
  10. To raczej koncepcja, prawdopodobnie spotkałem się z nią w jakiejś publikacji, mi pasuje, bo nie muszę grzebać po folderach by znaleźć WEB-INF

    OdpowiedzUsuń
  11. Super początek! Z niecierpliwością czekam na następne części!

    OdpowiedzUsuń
  12. Witam,
    Czy może ktoś podać jakie paczki są wymagane dla poszczególnych projektów?

    OdpowiedzUsuń
  13. Wszystko jest w konfiguracji Maven-a (pom.xml)

    OdpowiedzUsuń
  14. Jeśli ktoś by miał problem z błędem: The requested resource () is not available."

    Polecam stronę. http://www.mkyong.com/spring/spring-error-classnotfoundexception-org-springframework-web-context-contextloaderlistener/

    OdpowiedzUsuń
  15. Witam,
    mam problem z sitemesh:write i atrybutem property. Generalnie próbuje wstawić kilka tagów w kod szablonu np , jednak wygląda na to, że sitemesh nie chce łyknąć property innego niż standardowe tagi html takie jak title, body czy head. Spotkałeś się może z czymś takim?

    pozdrawiam

    OdpowiedzUsuń
  16. Zjadło tag - sitemesh:write property='content' (generalnie tag jest wklejony w diva o id="content"

    OdpowiedzUsuń
  17. Witam. Na poczatku podziękowania dla autora za artykuł. Jestem początkujący w tym temacie. Mam, prawdopodobnie błahy problem. Eclipse nie widzi u mnie znacznika . Dokładnie chodzi o częśc kodu:


    sitemesh
    com.darekzon.bookstore.filter.Sitemesh


    sitemesh
    /*

    OdpowiedzUsuń
  18. Jak możesz podeślij więcej mailem :)

    OdpowiedzUsuń
  19. Coś chyba się nie kompiluje. Gdzie mam wrzucić Springa?

    OdpowiedzUsuń
  20. [...] http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie [...]

    OdpowiedzUsuń
  21. przydałyby się linki na końcu artykułu, prowadzące do kolejnych części

    OdpowiedzUsuń
  22. racja, już dawno o tym myślałem :) zapewne pojawią się jak tylko znajdę choć chwilę czasu

    OdpowiedzUsuń
  23. Nie mam pojęcia co źle robię ale nie chce mi się uruchomić.
    HTTP Status 404 -

    --------------------------------------------------------------------------------

    type Status report

    message

    description The requested resource () is not available.


    --------------------------------------------------------------------------------

    Apache Tomcat/6.0.32

    Ściągnąłem Eclipse na nowo dodałem wtyczkę. Tworzę nowy projekt konwertuję na projekt Maven, zmieniam na wersję Javy 1.5. Kopiuję pliki z githuba i uruchamiam(0 błędów parę jakiś warringów).

    OdpowiedzUsuń
  24. Wrzuć konfiguracje log4j i sprawdź co pokaże

    OdpowiedzUsuń
  25. Korzystam z Eclipse 3.7, który rzekomo ma zainstalowane m2Eclipse, problem w tym, że klikając prawym przyciskiem myszy nie mam opcji 'Maven' dopiero zaczynam z JEE więc proszę o wyrozumiałość :)

    OdpowiedzUsuń
  26. Jeśli masz poprawnie zainstalowanego mavena (w ustawieniach eclipse-a powinna być zakładka maven) wystarczy w oknie "Project Explorer" kliknąć prawym klawiszem na projekt i wybrać "Configure -> Convert to Maven Project"

    Być może potrzeba będzie zainstalować Maven-a w systemie (choć może został dostarczony razem z eclipsem)

    OdpowiedzUsuń
  27. Czesc,
    mi z kolei nie dziala jak dodam sitemesh, dostaje: "java.lang.ClassNotFoundException: com.bookstore.filter.Sitemesh"

    w web.xml mam zas:


    sitemesh
    com.bookstore.filter.Sitemesh


    sitemesh
    /*



    No i oczywiscie mam paczke: com.bookstore.filter a w niej klase Sitmesh

    Ktos moze wie o co chodzi? czemu jej nie widzi?

    pzdr

    OdpowiedzUsuń
  28. Jeśli pojawia się ClassNotFoundException to niemal pewne jest złe ustawienie Classpath.

    OdpowiedzUsuń
  29. Uwierz mi, ze sprawdzilam to 10 razy. Sciezka do mojego Sitemesh:
    src/com/bookstore/filter/Sitemesh.java
    Zas w web.xml, wg Twojego przykladu:

    "
    sitemesh
    com.bookstore.filter.Sitemesh


    sitemesh
    /*
    "

    Zresza, wrzucilam te klase do default (czyli po prostu do src) i w web.xml podmienilam linijke z filter-class na:
    "Sitemesh"

    i znow: 'java.lang.ClassNotFoundException: Sitemesh"

    cos tu jest nie tak, moze ta definicja w web.xml jest niewystarczajaca?

    Swoja droga ja w ogole nie moglam odpalic aplikacji poki nie dodalam
    "
    contextConfigLocation
    /WEB-INF/web-servlet.xml
    "

    OdpowiedzUsuń
  30. java.lang.ClassNotFoundException to informacja, że aplikacja nie mogła znaleźć danej klasy w ścieżkach które ma zdefiniowane, sprawdź czy ona rzeczywiście istnieje w folderze serwera aplikacji (tj czy jest plik Sitemesh.class) bo być może wszystko łądnie wygląda w eclipse ale po skompilowaniu pliki trafiają gdzieś indziej. zapraszam również do kontaktu mailowego (zakładka w menu)

    OdpowiedzUsuń
  31. hej,
    no ja wlasnie chyba mam problem z eclipse i 'export do war'. Znalazlam inny tutorial jak stworzyc projekt mvn dynamic project - teraz sie ladnie kompiluje i wszystko wyglada ok. Chyba nie zrobie Ci konkurencji podajac tutaj linka:

    http://www.objectdb.com/tutorial/jpa/eclipse/spring/project

    Chodzi o sam poczatek, u mnie sie kaszani cos jak zrobie 'Dynamic Web Project' i 'Enable Maven Dependency'. Ale jak stworzylam projekt w eclipse wg tego przykladu to struktura katalogow i wszystko wyglada ok, i mam nadz ze bedzie - sprobuje teraz przerobic Twoj przyklad.

    pzdr!

    OdpowiedzUsuń
  32. @Misty

    cieszę się, że już wszystko działa :) rozumiem, że zaliczenie przedmiotu? :P

    OdpowiedzUsuń
  33. hej :) no wlasnie nie do konca dziala-mianowicie nie dziala mi ciagle ten Sitemesh - nie rzuca wyjatkow aplikacja zadnych, ale po prostu nie ma styli, jest widoczny czysty html. Pisalam do Ciebie proszac o bezposredni kontakt mailowy-ale chyba nie doszlo?
    Nie jest to zaliczenie przedmiotu, a raczej doksztalcanie sie :)

    OdpowiedzUsuń
  34. Przyznam szczerze ze sie poddalam. Staralam sie przejsc kolejne kroki, ale po prostu ciagle cos sie kaszanilo. W pom.xml czepialo sie o cos co chwile (wpierw skopiowalam Twojego pom'a, a potem dodawalam wszystko recznie), wpierw mi dolaczyl ladnie klasy z lib'a, potem ich nie widzial - jedna wielka kaszana. Po paru h prob-odpuscilam, sciagnelam Twoj projekt i sprobowalam odpalic. Zaimportowalam do eclipse bookstore-lib i bookstore-admin, po maven install otrzymalam:

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.0.2:war (default-war) on project bookstore: Could not explode webapp... /war/META-INF/MANIFEST.MF (No such file or directory) -> [Help 1]

    Zapewne umiesciles dzialajace zrodla, wiec moze mi podpowiesz - jak ja moge to odpalic?
    Probowalam tez (mimo err z mvn install) odpalic na serwerze (poprzez eclipse Run As) i przekierowalo mnie na adres:
    http://localhost:8081/0.0.1/

    nie mam pojecia skad to 0.0.1

    jakas podpowiedz?

    OdpowiedzUsuń
  35. Witam,

    Świetny artykuł, dobrze napisany. Miałem nadzieję, że ruszę z nim w końcu przygodę ze springiem. Dodatkowo to że jest po polsku to w ogóle super. Niestety podobnie jak misty nie potrafię ominąć problemu z Sitemesh class not found error. Pomijająć jednak całą konfigurację sitemesha (komentując ją) nic się nie dzieję po odpaleniu aplikacji na serwerze. Errorów brak jednak kupe WArnów, między innymi :

    WARNING: No mapping found for HTTP request with URI [/bookstore/] in DispatcherServlet with name 'web'

    czy ma to coś do rzeczy ? jak ruszyć dalej ?

    OdpowiedzUsuń
  36. Postaram się sprawdzić jeszcze raz czy aplikacja dobrze działa i ew. zaktualizuję wpisy, niestety ten tutorial nie będzie dalej rozwijany, z powodu braku czasu muszę go zarzucić. Jeśli jednak chodzi o springa to nadal będę o nim pisał, jednak jako przykłady przedstawiane będą małe aplikacje które można napisać w maksymalnie kilka dni.

    Odnośnie błędu "no mapping found" to najprościej można to wytłumaczyć tym, że spring nie znalazł żadnej metody której adnotacja @RequestMapping zawiera wpis /bookstore czyli spring nie wie jaką metodę ma wywołać dla danego url.

    Z tego co widzę, Spring próbuje znaleźć adres /bookstore/ co może oznaczać dwie rzeczy:
    1. masz źle skonfigurowanego springa dla tomcata (kontekst springa wskazuje że znajduje się on pod adresem "/" podczas gdy znajduje się pod "/bookstore"
    2. nie ma akcji dla indeksu (czyli akcji dla adresu "/")

    OdpowiedzUsuń
  37. Niestety bardzo słaby tutorial. Mówię ogółem o wszystkich częściach. Dlaczego?
    Zdecydowanie NIE JEST to tutorial dla początkujących. Miałem okazję zacząć uczyć się z niego i przez to straciłem przez to dużo czasu. 1 część jeszcze ujdzie, za to 2 totalnie niezrozumiała dla beginnera, dalej przerwałem. Dużo kroków pominięte, dziwna komunikacja z bazą, źle opisana, ogólnie namieszane okropnie. Nie wierzę, że ktokolwiek dotrwał do jego

    OdpowiedzUsuń
  38. wow, w końcu coś przez co mogę przejść na początek nauki springa w eclipsie. :)

    Dzięki wielkie :)

    OdpowiedzUsuń
  39. Dziękuję za opinię, sam doszedłem do wniosku, że następnym razem zamiast dużego tutoriala lepiej zrobić kilka małych opartych o niewielkie projekty, łatwiej to opisać na blogu, a i kod źródłowy milej czytać

    OdpowiedzUsuń
  40. swietne wprowadzenie,
    mam pare pytan
    1. Jak pobrany projekt z git uruchomic (bez eclipse)?
    2. bookstore (mvn clean install) tworzy jar a nie war, dlaczego?
    3. READMY jest puste dlaczego?

    OdpowiedzUsuń
  41. Witam.

    Mam problem z etapem tworzenia tej klasy Sitemeshextends, pozostałe podpunkty przeszedłem bez problemowo, dodałem wpis o filtrach. Rozumiem że mam stworzyć paczkę "com.darekzon.bookstore.filter" w niej stworzyć klasę Sitemesh.java o zawartości:


    public class Sitemeshextends ConfigurableSiteMeshFilter {
    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
    builder.addDecoratorPath("/*", "/views/layout/default.jsp");
    }
    }

    próbowałem poprawić na:

    public class Sitemesh extends ConfigurableSiteMeshFilter {
    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
    builder.addDecoratorPath("/*", "/views/layout/default.jsp");
    }
    }

    Przyznam się że zapoczątkuje w JEE w Javie programuje od 3 lat wiec rozumiem zawartość plików,
    ale w tym etapie zgłupiałem mógłby mi ktoś wskazać kierunek.

    Aplikacja nie chcę się uruchomić ponieważ w wyżej wymienionej klasie są błędy że nie znaleziono klasy ConfigurableSiteMeshFilter i dodam że używam sitemesh 2.4.2

    Pozdrawiam

    OdpowiedzUsuń
  42. ja tez mam problem z klasa Sitemesh Java:

    Multiple markers at this line
    - The type javax.servlet.Filter cannot be resolved. It is indirectly referenced from required .class
    files
    - The hierarchy of the type Sitemesh is inconsistent


    a zawartość sitemesh skopiowałem z pobranych plików:
    package com.darekzon.bookstore.filter;

    import org.sitemesh.config.ConfigurableSiteMeshFilter;
    import org.sitemesh.builder.*;

    public class Sitemesh extends ConfigurableSiteMeshFilter{
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
    builder.addDecoratorPath("/*", "/views/layout/default.jsp");
    builder.setMimeTypes("text/html");

    }
    }




    filtry wszystko dodane w najlepszym porzadeczku. struktura katologowa tak jak na tutorialu i w pobranych plikach

    OdpowiedzUsuń
  43. Patryk, spróbuj dodać do pom.xml następującą zależność:

    javax.servlet
    javax.servlet-api
    3.1-b02


    Powinno rozwiązać Twój problem.

    OdpowiedzUsuń
  44. Wrzuce pare rzeczy, ktore tutorial pominal...

    1) Należy dodać do Deployment Assembly 'Maven Dependency'.
    ( prawy przycisk na projekt -> Properties -> Deployment Assembly)
    Innaczej podczas uruchomienia aplikacji na Tomcacie nie będą widoczne liby springa.

    2) Jeśli nie znajduję matcha (mimo zdefiniowania odpowiedniego kontollera) to nalezy dodac do build path ( prawy przycisk na projekt -> build path) katalog, w ktorym znajduje sie pakiet z naszymi klasami (na ogol src). Co najwazniejsze nlezy mu wskazac miejsce gdzie maja ladowac skomplikowane klasy. Musi to byc 'war/WEB-INF/classes'.

    OdpowiedzUsuń
  45. od1)

    java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

    http://stackoverflow.com/questions/6210757/java-lang-classnotfoundexception-org-springframework-web-context-contextloaderl

    OdpowiedzUsuń
  46. Anonimowy: Dzięki za wskazówki dla czytających, ja zupełnie o nich zapomniałem. Zastanawiam się przez to, czy teraz wrzucając pliki do repozytorium wrzucać wszystko łącznie z konfiguracją IDE czy zostawić tak jak jest tylko poszerzyć opis. Jak uważacie?
    Moim zdaniem lepiej będzie poszerzyć ew. opis, no i ja korzystam od jakiegoś czasu z IntelliJ Idea.

    OdpowiedzUsuń
    Odpowiedzi
    1. Moim zdaniem wystarczy uzupenić opis. :)

      Usuń