<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>dev garden</title>
	
	<link>http://darekzon.com</link>
	<description>when technology meets nature</description>
	<lastBuildDate>Thu, 02 Sep 2010 19:02:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/darekzon" /><feedburner:info uri="darekzon" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>1&amp;1 w Polsce, czyżby hosting killer? niekoniecznie</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/nHuLdp3S31g/11-w-polsce-czyzby-hosting-killer-niekoniecznie</link>
		<comments>http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie#comments</comments>
		<pubDate>Thu, 02 Sep 2010 19:02:35 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1006</guid>
		<description><![CDATA[Tuż przed weekendem na łamach jednej z&#160;e-gazet (nie pamiętam której) przeczytałem o&#160;rozpoczęciu działalności na terenie Polski przez hostingowego giganta jakim jest 1&#38;1. Na pierwszy rzut oka można się tylko cieszyć wreszcie jakiś duży hostingowy gracz wkracza na polski rynek wprowadzając powiew świeżości w&#160;zgniliznę polskich ofert. Na start 1&#38;1 przygotował nie lada gratkę, zupełnie za darmo [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://darekzon.com/wp-content/uploads/2010/09/logo11.jpeg" rel="lightbox[1006]"><img class="size-thumbnail wp-image-1011 alignleft" title="logo11" src="http://darekzon.com/wp-content/uploads/2010/09/logo11-150x150.jpg" alt="" width="150" height="150" /></a>Tuż przed weekendem na łamach jednej z&nbsp;e-gazet (nie pamiętam której) przeczytałem o&nbsp;rozpoczęciu działalności na terenie Polski przez hostingowego giganta jakim jest 1&amp;1. Na pierwszy rzut oka można się tylko cieszyć wreszcie jakiś duży hostingowy gracz wkracza na polski rynek wprowadzając powiew świeżości w&nbsp;zgniliznę polskich ofert. Na start 1&amp;1 przygotował nie lada gratkę, zupełnie za darmo oferuje <strong>10GB pojemności, 3TB transferu miesięcznie i&nbsp; domenę &#8220;.pl&#8221; w&nbsp;pakiecie 2 letnim</strong>; bez haczyków ani małych druczków (2 razy regulamin przeczytałem) . Zachęcony powyższą ofertą postanowiłem się sprawdzić co oferuje zagraniczny gigant, i&nbsp;tu zaczynają się schody. <span id="more-1006"></span>Do rejestracji wymagane są nasze pełne dane teleadresowe + pesel. Problem sprawia formularz adresowy w&nbsp;którym pole telefon jest źle opisane (format wprowadzania danych jest nieintuicyjny) pomogło wprowadzenie numeru telefonu (komórkowego) w&nbsp;formacie &#8220;3cyfry / reszta&#8221;. Po rejestracji dostajemy 4 cyfrowy numer który musimy wpisać podczas autoryzacji odbywającej się telefonicznie (dzwoni do Ciebie automat i&nbsp;prosi o&nbsp;wpisanie numeru). Również ta autoryzacja sprawia problemy. Za pierwszym razem automat rozłączył się tuż po odebraniu przeze mnie telefonu, za drugim razem miał problem z&nbsp;rozpoznaniem wpisywanego przeze mnie kodu, ale na szczęście się udało.</p>
<p>Po poprawnej autoryzacji dostałem dane dostępowe do konta i&nbsp;tu pierwszy szok. Już przed oczami przechodziły mi obrazy stawiania nowych portali, przenoszenia bloga oraz domen, a&nbsp;także udostępnienia kilku większych plików znajomym. Jednak to co zastałem okazało się totalną klapą. Panel administracyjny przypomina usługi hostingowe z&nbsp;których korzystałem 10 lat temu; <strong>archaiczny, niewygodny, z&nbsp;niewielką ilością opcji</strong> które są źle poustawiane lub ukryte w&nbsp;nieintuicyjnym miejscu. Najważniejszą bolączką był <strong>brak możliwości podpięcia zewnętrznych domen </strong>do systemu (np. z&nbsp;dnsów OVH) co skutecznie odstraszyło mnie od tego usługodawcy. <strong>Problemy są również z&nbsp;przesyłaniem plików</strong>, serwery często zrywają transfer co skutecznie utrudnia wgrywanie. Nie wiem jak działanie serwisów po udało im się mnie skutecznie odstraszyć. Po niecałych kilkunastu minutach stwierdziłem, że to nie dla mnie i&nbsp;postanowiłem już nie korzystać z&nbsp;ich usług.</p>
<p>Czy w&nbsp;związku z&nbsp;tym powinno się wystrzegać tej firmy? Myślę, że nie. Jeśli po upływie 2 lat firma nadal będzie oferować niskie ceny mogą być dobrą alternatywą dla niewymagających użytkowników, Ci którzy mają firmowe strony powinni uciekać jak najdalej. Brak polskiego wsparcia (dzwonisz do call center za granicą) oraz niska jakość usług (mało opcji, zrywanie połączeń) są wystarczającymi argumentami przeciw 1&amp;1.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;title=1%261+w+Polsce%2C+czy%C5%BCby+hosting+killer%3F+niekoniecznie" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;t=1%261+w+Polsce%2C+czy%C5%BCby+hosting+killer%3F+niekoniecznie" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;n=1%261+w+Polsce%2C+czy%C5%BCby+hosting+killer%3F+niekoniecznie&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;title=1%261+w+Polsce%2C+czy%C5%BCby+hosting+killer%3F+niekoniecznie" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie&amp;title=1%261+w+Polsce%2C+czy%C5%BCby+hosting+killer%3F+niekoniecznie&amp;description=Tu%C5%BC%20przed%20weekendem%20na%20%C5%82amach%20jednej%20z%20e-gazet%20%28nie%20pami%C4%99tam%20kt%C3%B3rej%29%20przeczyta%C5%82em%20o%20rozpocz%C4%99ciu%20dzia%C5%82alno%C5%9Bci%20na%20terenie%20Polski%20przez%20hostingowego%20giganta%20jakim%20jest%201%26amp%3B1.%20Na%20pierwszy%20rzut%20oka%20mo%C5%BCna%20si%C4%99%20tylko%20cieszy%C4%87%20wreszcie%20jaki%C5%9B%20du%C5%BCy%20hostingowy%20gracz%20wkracza%20na%20polski%20rynek%20wprowad" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/POVREHPWMs2dPVmPwjVk_gGZgCc/0/da"><img src="http://feedads.g.doubleclick.net/~a/POVREHPWMs2dPVmPwjVk_gGZgCc/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/POVREHPWMs2dPVmPwjVk_gGZgCc/1/da"><img src="http://feedads.g.doubleclick.net/~a/POVREHPWMs2dPVmPwjVk_gGZgCc/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/nHuLdp3S31g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/09/11-w-polsce-czyzby-hosting-killer-niekoniecznie</feedburner:origLink></item>
		<item>
		<title>Recenzja: Java EE 6. Programowanie aplikacji WWW</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/vB9QkjGOVRU/recenzja-java-ee-6-programowanie-aplikacji-www</link>
		<comments>http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www#comments</comments>
		<pubDate>Wed, 25 Aug 2010 20:12:12 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Książki]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[książka]]></category>
		<category><![CDATA[recenzja]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=966</guid>
		<description><![CDATA[Największą bolączką osób chcących rozpocząć swoją przygodę z&#160;korporacyjną Javą jest a&#160;raczej był brak jakiejkolwiek książki dla początkujących. Był ponieważ od całkiem niedawna wszyscy chcący zapoznać się z&#160;podstawami tej technologii mogą nabyć książkę &#8220;Java EE 6. Programowanie aplikacji WWW&#8221; której autor Krzysztof Rychlicki-Kicior przenosi nas w&#160;świat Javy EE. Książka pomimo niewielkiej liczby stron (lekko powyżej 200) [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="Java EE 6. Programowanie aplikacji WWW" src="http://helion.pl/okladki/125x163/javee6.jpg" alt="" width="125" height="163" /> Największą bolączką osób chcących rozpocząć swoją przygodę z&nbsp;korporacyjną Javą jest a&nbsp;raczej był brak jakiejkolwiek książki dla początkujących. Był ponieważ od całkiem niedawna wszyscy chcący zapoznać się z&nbsp;podstawami tej technologii mogą nabyć książkę &#8220;Java EE 6. Programowanie aplikacji WWW&#8221; której autor Krzysztof Rychlicki-Kicior przenosi nas w&nbsp;świat Javy EE. Książka pomimo niewielkiej liczby stron (lekko powyżej 200) omawia wszystkie podstawowe aspekty programowania w&nbsp;korporacyjnej Javie oraz technologie wykorzystywane podczas tworzenia takich aplikacji, przedstawia nawet dwa w&nbsp;miarę kompletne przykłady. <span id="more-966"></span>Można by powiedzieć, że książka idealnie zapełni lukę jednak tak nie jest. Pozycję tą można głównie polecić tym, którzy zainteresowani są w&nbsp;szczególności technologią JSF bo właśnie jej poświęcono większość książki. Ci którzy wolą korzystać z&nbsp;innych technologii zadowolą się jedynie pierwszymi rozdziałami, oraz ostatnim rozdziałem poświęconym dostępowi do bazy danych. Kolejnym (moim zdaniem większym) minusem książki jest jej charakter, podczas czytania dochodzimy w&nbsp;końcu do wrażenia, że nie czytamy nic innego jak obszerny tutorial. Jednym, takie rozwiązanie może przypaść do gustu, moim zdaniem tutorialowa forma (w tym wydaniu) źle wpływa na czytelność książki, szczególnie denerwującym (jak dla mnie) był opis integracji netbeans&lt;=&gt;tomcat (która jest na tyle prosta, że można ją pominąć kierując do wyszukiwarki), czy też zrzuty ekranu prezentujące środowisko Netbeans (bez specjalnej potrzeby), zabrakło natomiast diagramów UML prezentujących zasady działania danego zagadnienia.<br />
Przechodząc do sedna sprawy, moim zdaniem:</p>
<p><strong>Za książką:</strong></p>
<ol>
<li>dobrze (choć mało wyczerpująco) opisane techniki oraz technologie J2EE,</li>
<li>proste oraz możliwie kompletne przykłady,</li>
<li>przystępny język oraz cena książki,</li>
</ol>
<p><strong>Przeciw książce</strong>:</p>
<ol>
<li>tutorialowa forma książki,</li>
<li>niepotrzebne obszerne (zrzuty) opisy prostych czynności nie związanych bezpośrednio z&nbsp;technologią j2ee (integracja netbeans&lt;=&gt;tomcat, tworzenie projektu w&nbsp;netbeans),</li>
<li>źle sformatowane kody źródłowe (w ostatnich rozdziałach, gdzie tworzone są encje z&nbsp;zapytaniami nazwanymi kod zlewa się co utrudnia analizę),</li>
<li>za dużo o&nbsp;JSF jednak wciąż za mało by mieć mocne podstawy z&nbsp;tej technologii,</li>
<li>powtarzalność (w pewnym momencie mamy wrażenie, że autor się powtarza, szczególnie odnośnie przykładowego kodu)</li>
<li>słowo &#8220;Magikonwersja&#8221; (nie lubię takich tworów, za Potterem też nie przepadam)</li>
</ol>
<p>Czy pomimo tylu minusów warto kupić książkę? Na to pytanie odpowiedzieć musi sobie każdy z&nbsp;osobna. Zapewne książka przydatna będzie zupełnym laikom którzy nie wiedzą nic odnośnie korporacyjnej javie, a&nbsp;chcieliby zacząć coś w&nbsp;niej robić.Również studenci znajdą w&nbsp;tej książce wiele interesujących informacji, a&nbsp;to za sprawą przystępnego treściwego języka oraz szeregu przykładów które dobrze przedstawiają omawiane tematy. Jeśli natomiast tworzyłeś już projekty w&nbsp;J2EE ta książka może jedynie nieznacznie uzupełnić Twoją wiedzę, czy jest sens ją kupować ocenisz sam.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;title=Recenzja%3A+Java+EE+6.+Programowanie+aplikacji+WWW" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;t=Recenzja%3A+Java+EE+6.+Programowanie+aplikacji+WWW" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;n=Recenzja%3A+Java+EE+6.+Programowanie+aplikacji+WWW&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;title=Recenzja%3A+Java+EE+6.+Programowanie+aplikacji+WWW" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www&amp;title=Recenzja%3A+Java+EE+6.+Programowanie+aplikacji+WWW&amp;description=%20Najwi%C4%99ksz%C4%85%20bol%C4%85czk%C4%85%20os%C3%B3b%20chc%C4%85cych%20rozpocz%C4%85%C4%87%20swoj%C4%85%20przygod%C4%99%20z%20korporacyjn%C4%85%20Jav%C4%85%20jest%20a%20raczej%20by%C5%82%20brak%20jakiejkolwiek%20ksi%C4%85%C5%BCki%20dla%20pocz%C4%85tkuj%C4%85cych.%20By%C5%82%20poniewa%C5%BC%20od%20ca%C5%82kiem%20niedawna%20wszyscy%20chc%C4%85cy%20zapozna%C4%87%20si%C4%99%20z%20podstawami%20tej%20technologii%20mog%C4%85%20naby%C4%87%20ksi%C4%85%C5%BCk%C4%99%20%22Java%20EE%206.%20Progra" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/JdMXbCEpQA6EcGvnugR_NS90idI/0/da"><img src="http://feedads.g.doubleclick.net/~a/JdMXbCEpQA6EcGvnugR_NS90idI/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/JdMXbCEpQA6EcGvnugR_NS90idI/1/da"><img src="http://feedads.g.doubleclick.net/~a/JdMXbCEpQA6EcGvnugR_NS90idI/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/vB9QkjGOVRU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/08/recenzja-java-ee-6-programowanie-aplikacji-www</feedburner:origLink></item>
		<item>
		<title>Szkolenie ze Springa w Krakowie</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/4ioj0m3OPzg/szkolenie-ze-springa-w-krakowie</link>
		<comments>http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie#comments</comments>
		<pubDate>Wed, 25 Aug 2010 15:41:45 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Konferencje]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[szkolenie]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=959</guid>
		<description><![CDATA[W dniach 7-10 grudnia 2010 odbędzie się w&#160;Krakowie szkolenie z&#160;technologii Spring (w wersji 3.0). Prócz samego rdzenia tej technologii szkolenie obejmować będzie takie zagadnienia jak  Spring MVC, Spring AOP, Spring IOC, Spring JavaConfig, Spring Security, SpringSource Tool Suit i&#160;inne. Pełne zestawienie można pobrać w&#160;formacie pdf. Dodatkowo rejestrując się do 4 września możliwe jest wykorzystanie kodu [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-961 alignleft" title="Spring Source" src="http://darekzon.com/wp-content/uploads/2010/08/Logo_Spring_252x150.png" alt="Spring Source" width="252" height="150" /></p>
<p>W dniach 7-10 grudnia 2010 odbędzie się w&nbsp;Krakowie szkolenie z&nbsp;technologii Spring (w wersji 3.0). Prócz samego rdzenia tej technologii szkolenie obejmować będzie takie zagadnienia jak  Spring MVC, Spring AOP, Spring IOC, Spring JavaConfig, Spring Security, SpringSource Tool Suit i&nbsp;inne. Pełne zestawienie można <a title="Informacje o&nbsp;szkoleniu Spring" href="http://mylearn.vmware.com/descriptions/Core%20Spring%20Datasheet.pdf" target="_blank">pobrać w&nbsp;formacie pdf</a>.<br /> Dodatkowo rejestrując się do 4 września możliwe jest wykorzystanie kodu promocyjnego <strong>springup</strong> który skutkować będzie 15% rabatem. Jeśli na kurs wybieramy się z&nbsp;kolegą/koleżanką czeka nas rabat 10%, jeśli to będzie większa grupa, można liczyć na 20% rabat.  Po więcej informacji odsyłam na <a title="Kurs Spring w&nbsp;Krakowie" href="http://mylearn.vmware.com/mgrReg/courses.cfm?ui=S2&amp;a=one&amp;id_subject=17750" target="_blank">stronę kursu</a>.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;title=Szkolenie+ze+Springa+w+Krakowie" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;t=Szkolenie+ze+Springa+w+Krakowie" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;n=Szkolenie+ze+Springa+w+Krakowie&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;title=Szkolenie+ze+Springa+w+Krakowie" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie&amp;title=Szkolenie+ze+Springa+w+Krakowie&amp;description=%20W%20dniach%207-10%20grudnia%202010%20odb%C4%99dzie%20si%C4%99%20w%20Krakowie%20szkolenie%20z%20technologii%20Spring%20%28w%20wersji%203.0%29.%20Pr%C3%B3cz%20samego%20rdzenia%20tej%20technologii%20szkolenie%20obejmowa%C4%87%20b%C4%99dzie%20takie%20zagadnienia%20jak%20%C2%A0Spring%20MVC%2C%20Spring%20AOP%2C%20Spring%20IOC%2C%20Spring%20JavaConfig%2C%20Spring%20Security%2C%20SpringSource%20Tool%20Suit%20i%20inne.%20Pe%C5%82n" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/Mwwr1UYNfd2yDzvL2KHaOIQ9fK4/0/da"><img src="http://feedads.g.doubleclick.net/~a/Mwwr1UYNfd2yDzvL2KHaOIQ9fK4/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Mwwr1UYNfd2yDzvL2KHaOIQ9fK4/1/da"><img src="http://feedads.g.doubleclick.net/~a/Mwwr1UYNfd2yDzvL2KHaOIQ9fK4/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/4ioj0m3OPzg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/08/szkolenie-ze-springa-w-krakowie</feedburner:origLink></item>
		<item>
		<title>Recenzja: “Java. Efektywne programowanie. Wydanie II”</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/XaR8pJiETuk/recenzja-java-efektywne-programowanie-wydanie-ii</link>
		<comments>http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii#comments</comments>
		<pubDate>Tue, 20 Jul 2010 22:23:38 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Książki]]></category>
		<category><![CDATA[książka]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=939</guid>
		<description><![CDATA[Kilka dni temu zakończyłem lekturę książki &#8220;Java. Efektywne programowanie. Wydanie II&#8221;. Z&#160;początku sceptycznie podchodziłem do wydania jako zbiór zasad które warto wykorzystać podczas pisania, no bo co nowego można napisać. Jednak już po kilku pierwszych tematach zdałem sobie sprawę, że książka warta jest każdej wydanej złotówki. Autor w&#160;78 tematach omawia zasady tworzenia obiektów, klas, metod, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="Java. Efektywne programowanie. Wydanie II" src="http://helion.pl/okladki/125x163/javep2.jpg" alt="" width="125" height="163" /></p>
<p>Kilka dni temu zakończyłem lekturę książki &#8220;Java. Efektywne programowanie. Wydanie II&#8221;. Z&nbsp;początku sceptycznie podchodziłem do wydania jako zbiór zasad które warto wykorzystać podczas pisania, no bo co nowego można napisać. Jednak już po kilku pierwszych tematach zdałem sobie sprawę, że książka warta jest każdej wydanej złotówki.<br />
Autor w&nbsp;78 tematach omawia zasady tworzenia obiektów, klas, metod, interfejsów, korzystania z&nbsp;typów ogólnych, wyliczeń, adnotacji, oraz zasady programowania, obsługi wyjątków czy też współbieżności i&nbsp;serializacji. <span id="more-939"></span>Tematy opisane są zwięźle i&nbsp;klarownie, a&nbsp;tam gdzie to potrzebne autor przedstawia kod źródłowy z&nbsp;ew. modyfikacjami jakie należy nanieść by program był czytelny i&nbsp;co ważne działał poprawnie. Kod źródłowy jest dokładnie opisany, wraz z&nbsp;wytknięciem błędów, po czym autor wprowadza modyfikacje dokładnie je prezentując. Takie rozwiązanie pozwala łatwiej zrozumieć zamysł autora oraz lepiej przyswoić sobie rozwiązanie. Co ważne, książka była ciekawa (choć w&nbsp;kilku momentach nużąca) co pozwoliło mi w&nbsp;szybkim czasie przebrnąć przez wszystkie strony.</p>
<p>Niestety, nie ma rzeczy idealnych, w&nbsp;książce irytuje mnie częste wykorzystywanie słowa &#8220;klienty&#8221; (poprawne, ale mnie denerwuje, można by tu chyba użyć bardziej popularnego słowa &#8220;klienci&#8221;), czasami zdarza się, że bardziej rozbudowane zdania wydają się bez sensu, lub są trudne w&nbsp;zrozumieniu, nie wiem czy jest to problem tłumaczenia, czy może autor używa na tyle specyficznego języka, na szczęście zdarzyło się to dosłownie kilka razy.</p>
<p>Szczerze polecam.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;title=Recenzja%3A+%22Java.+Efektywne+programowanie.+Wydanie+II%22" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;t=Recenzja%3A+%22Java.+Efektywne+programowanie.+Wydanie+II%22" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;n=Recenzja%3A+%22Java.+Efektywne+programowanie.+Wydanie+II%22&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;title=Recenzja%3A+%22Java.+Efektywne+programowanie.+Wydanie+II%22" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii&amp;title=Recenzja%3A+%22Java.+Efektywne+programowanie.+Wydanie+II%22&amp;description=%0D%0A%0D%0AKilka%20dni%20temu%20zako%C5%84czy%C5%82em%20lektur%C4%99%20ksi%C4%85%C5%BCki%20%22Java.%20Efektywne%20programowanie.%20Wydanie%20II%22.%20Z%20pocz%C4%85tku%20sceptycznie%20podchodzi%C5%82em%20do%20wydania%20jako%20zbi%C3%B3r%20zasad%20kt%C3%B3re%20warto%20wykorzysta%C4%87%20podczas%20pisania%2C%20no%20bo%20co%20nowego%20mo%C5%BCna%20napisa%C4%87.%20Jednak%20ju%C5%BC%20po%20kilku%20pierwszych%20tematach%20zda%C5%82em%20sobie%20spraw" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/g5a9rs_H-csnudR-u6ES_FeI05c/0/da"><img src="http://feedads.g.doubleclick.net/~a/g5a9rs_H-csnudR-u6ES_FeI05c/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/g5a9rs_H-csnudR-u6ES_FeI05c/1/da"><img src="http://feedads.g.doubleclick.net/~a/g5a9rs_H-csnudR-u6ES_FeI05c/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/XaR8pJiETuk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/07/recenzja-java-efektywne-programowanie-wydanie-ii</feedburner:origLink></item>
		<item>
		<title>GuruPlug – krótkie info + instalacja na dysku USB</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/A1_4fbWRN2g/guruplug-krotkie-info-instalacja-na-dysku-usb</link>
		<comments>http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb#comments</comments>
		<pubDate>Fri, 04 Jun 2010 10:55:51 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Różne]]></category>
		<category><![CDATA[guruplug]]></category>
		<category><![CDATA[plugcomputer]]></category>
		<category><![CDATA[sheevaplug]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=925</guid>
		<description><![CDATA[Idealnie 1 czerwca dostałem paczkę zawierającą komputer GuruPlug. Czym jest GuruPlug? Jest to mały (9,5&#215;6,3&#215;4,5cm) komputer posiadający 1.2Ghz procesor i&#160;512MB RAM oraz 2 porty USB, 1Gb ethernet, wifi i&#160;bluetooth (istnieją jeszcze 2 wersje Server Plus oraz Display różniące się wyjściami). Zakupiłem to urządzenie bo potrzebowałem małego i&#160;cichego (bez wentylatorów) urządzenia które spełniać będzie rolę NFS-a, [...]]]></description>
			<content:encoded><![CDATA[<p>Idealnie 1 czerwca dostałem paczkę zawierającą komputer <a title="GuruPlug - opis" href="http://plugcomputer.org/plugwiki/index.php/GuruPlug" target="_blank">GuruPlug</a>. Czym jest GuruPlug? Jest to mały (9,5&#215;6,3&#215;4,5cm) komputer posiadający 1.2Ghz procesor i&nbsp;512MB RAM oraz 2 porty USB, 1Gb ethernet, wifi i&nbsp;bluetooth (istnieją jeszcze 2 wersje Server Plus oraz Display różniące się wyjściami). Zakupiłem to urządzenie bo potrzebowałem małego i&nbsp;cichego (bez wentylatorów) urządzenia które spełniać będzie rolę NFS-a, repozytorium GIT oraz serwera testowego dla aplikacji napisanych w&nbsp;języku Ruby.<br />
Ponieważ urządzenie zamówiłem w&nbsp;formie przed sprzedażowej dostałem również tzw. JTag który jest wymagany aby połączyć się z&nbsp;GP poprzez serial port. Jedynym mankamentem jaki zauważyłem dotychczas jest mała ilość miejsca w&nbsp;pamięci NAND (pamięć masowa 512MB, na której jest już zainstalowany Debian lenny), przez co musimy uważać co instalujemy. Rozwiązaniem jest zainstalowanie systemu na zewnętrznym dysku twardym co daje nam dodatkową korzyść w&nbsp;postaci przyśpieszenia działania systemu (pamięć NAND wydaje się tu dość wolna). Niestety instalacja systemu nie należy do najłatwiejszych i&nbsp;jak napisałem wcześniej wymaga dodatkowego urządzenia w&nbsp;postaci JTaga.<span id="more-925"></span></p>
<h3>Instalacja</h3>
<p>Podczas instalowania korzystałem z&nbsp;3 instrukcji oraz własnych eksperymentów. Wszystko składa się na kilka kroków (linki na końcu wpisu). W&nbsp;moim wypadku użyłem dysku zewnętrznego Seagate® Expansion™ o&nbsp;rozmiarze 1TB.</p>
<p>1) Aktualizujemy UBoot w&nbsp;urządzeniu korzystając z&nbsp;instrukcji pod linkiem nr 4.</p>
<p>2) Przygotowujemy instalator oraz instalujemy system korzystając z&nbsp;instrukcji pod adresem nr 2.</p>
<blockquote><p><strong>Uwagi</strong>:</p>
<p>a) W&nbsp;kroku <strong>Running the installer</strong> prócz stworzenia obrazu musiałem  również stworzyć dodatkowych użytkowników, gdyż sam instalator pomimo  użycia odpowiednich opcji nie zrobił tego</p>
<p>b) trzeba zapamiętać pod jakimi nazwami są nasze partycje, u&nbsp;mnie było to odpowiedni <strong>/dev/sda1</strong> dla <strong>/boot</strong> oraz <strong>/dev/sda6</strong> dla <strong>/</strong></p>
<p>c) nie trzeba wysyłać stworzonych obrazów na zewnętrzny serwer.</p>
<p>d) Ponieważ jest to instalacja dla kart SD nie wykonujemy ostatniego kroku  &#8220;<strong>Make the plug bootable</strong>&#8220;</p></blockquote>
<p>3) Po zainstalowaniu systemu, przygotowaniu obrazów startowych oraz dodaniu użytkowników, zrestartowałem urządzenie i&nbsp;przeszedłem do Uboot-a gdzie trzeba było skonfigurować start systemu co jest opisane pod linkiem <strong>3</strong>, ponieważ system miał startować z&nbsp;dysku usb należy najpierw znaleźć urządzenia, potem załadować obrazy, wskazać punkt montowania dla <strong>root</strong> a&nbsp;potem wystartować system, w&nbsp;moim wypadku polecenia ustawiające opcje startu wyglądały nastepująco:</p>
<pre class="brush: bash;">

setenv bootargs_console 'root=/dev/sda6 console=ttyS0,115200'
setenv bootcmd_usb 'usb start; ext2load usb 0:1 0x01100000 /uInitrd; ext2load usb 0:1 0x00800000 /uImage;'
setenv bootcmd 'setenv bootargs $(bootargs_console);run bootcmd_usb; bootm 0x00800000 0x01100000; reset'
saveenv
</pre>
<blockquote><p><strong>Uwaga</strong>!</p>
<p>Przed ostatnia linia zawiera polecenie <strong>reset</strong> które notabene powoduje zresetowanie/reboot całego urządzenia, jednak w&nbsp;tym wypadku polecenie to zostanie wykonane tylko i&nbsp;wyłącznie jeśli nie uda się boot-owanie systemu, jest to miejmy nadzieję tylko tymczasowe rozwiązanie do problemu który polega na losowym (co drugi raz) niewykrywaniu dysku USB więc jeśli dysk nie zostanie wykryty robimy reset i&nbsp;wykrywamy podobnie i&nbsp;tak w&nbsp;kółko aż zaskoczy.</p></blockquote>
<p>4) Wykonujemy polecenie <strong>reset</strong> i&nbsp;startujemy system, powinno to potrwać ok minuty.</p>
<h3>Co zauważyłem po kilku dniach używania:</h3>
<p>1) Wiele osób narzeka na wysoką temperaturę swojego urządzenia (głównie wersja rozszerzona Server Plus), jakkolwiek nie mam termometru by to sprawdzić wygląda na to, że moje urządzenie jest wolne od wad, jest ciepłe, ale bez przesady, można dotykać, przytulać się, co kto lubi.</p>
<p>2) Instalacja na zewnętrznym dysku pomimo tego, że jest kłopotliwa drastycznie zwiększa wydajność całego systemu</p>
<p>3) Pozainstalowaniu Nginx-a, bazy PosgreSQL, mt-daap (strumieniowanie audio), mediatomb (serwer multimedialny dla mojej PS3), repozytorium git-a (+ gitosis) mam jeszcze dużo pamięci ram, wystarczy na tomcata i&nbsp;jeszcze nawet zostanie.</p>
<p>4) Port gigabitowy nie działa, podłączając kabel sieci 1Gb urządzenie się resetuje, na szczęście mam router 100Mb więc nie ma problemu</p>
<p>Zdjęcia nie będzie, bo GuruPlug wylądował pod łóżkiem i&nbsp;ciężko się do niego dostać.</p>
<div id="attachment_932" class="wp-caption alignleft" style="width: 160px"><a href="http://darekzon.com/wp-content/uploads/2010/06/guruplug_jtag.jpg" rel="lightbox[925]"><img class="size-thumbnail wp-image-932" title="Urządzenie GuruPlug JTag" src="http://darekzon.com/wp-content/uploads/2010/06/guruplug_jtag-150x150.jpg" alt="Urządzenie GuruPlug JTag" width="150" height="150" /></a><p class="wp-caption-text">Urządzenie GuruPlug JTag</p></div>
<hr class="clear" />
<h3>Linki</h3>
<p>1) Jeśli uda wam się coś zepsuć (programowo) w&nbsp;waszym GuruPlugu polecam stronę:<br />
<a title="Jak naprawić GuruPlug" href="http://plugcomputer.org/plugwiki/index.php/Reflashing_images_on_the_GuruPlug">http://plugcomputer.org/plugwiki/index.php/Reflashing_images_on_the_GuruPlug</a></p>
<p>2) Instalacja Debiana na urządzeniu Guruplug (karta SD):<br />
<a title="Instalacja Debiana na urządzeniu Guruplug (karta SD):" href="http://bzed.de/posts/2010/05/installing_debian_on_the_guruplug_server_plus/" target="_blank">http://bzed.de/posts/2010/05/installing_debian_on_the_guruplug_server_plus/</a></p>
<p>3) Instalacja Debiana na urządzeniu Shevaplug (dysk USB):<br />
<a title="Instalacja Debiana na urządzeniu Shevaplug (dysk USB):" href="http://www.cyrius.com/debian/kirkwood/sheevaplug/install.html" target="_blank">http://www.cyrius.com/debian/kirkwood/sheevaplug/install.html</a></p>
<p>4) Aktualizacja Uboot<br />
<a title="GuruPlug - aktualizajca UBoot" href="http://www.cyrius.com/debian/kirkwood/sheevaplug/uboot-upgrade.html" target="_blank">http://www.cyrius.com/debian/kirkwood/sheevaplug/uboot-upgrade.html</a></p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;title=GuruPlug+-+kr%C3%B3tkie+info+%2B+instalacja+na+dysku+USB" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;t=GuruPlug+-+kr%C3%B3tkie+info+%2B+instalacja+na+dysku+USB" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;n=GuruPlug+-+kr%C3%B3tkie+info+%2B+instalacja+na+dysku+USB&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;title=GuruPlug+-+kr%C3%B3tkie+info+%2B+instalacja+na+dysku+USB" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb&amp;title=GuruPlug+-+kr%C3%B3tkie+info+%2B+instalacja+na+dysku+USB&amp;description=Idealnie%201%20czerwca%20dosta%C5%82em%20paczk%C4%99%20zawieraj%C4%85c%C4%85%20komputer%20GuruPlug.%20Czym%20jest%20GuruPlug%3F%20Jest%20to%20ma%C5%82y%20%289%2C5x6%2C3x4%2C5cm%29%20komputer%20posiadaj%C4%85cy%201.2Ghz%20procesor%20i%20512MB%20RAM%20oraz%202%20porty%20USB%2C%201Gb%20ethernet%2C%20wifi%20i%20bluetooth%20%28istniej%C4%85%20jeszcze%202%20wersje%20Server%20Plus%20oraz%20Display%20r%C3%B3%C5%BCni%C4%85ce%20si%C4%99%20wyj%C5%9Bciami%29" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/qzMKJqedzNhVt6gDIK9R-M7D11s/0/da"><img src="http://feedads.g.doubleclick.net/~a/qzMKJqedzNhVt6gDIK9R-M7D11s/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/qzMKJqedzNhVt6gDIK9R-M7D11s/1/da"><img src="http://feedads.g.doubleclick.net/~a/qzMKJqedzNhVt6gDIK9R-M7D11s/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/A1_4fbWRN2g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/06/guruplug-krotkie-info-instalacja-na-dysku-usb</feedburner:origLink></item>
		<item>
		<title>Spring Framework 3.0 Tutorial – cz 4 – sitemesh, menu, atrybuty kontekstu</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/sBQYLIjZxYY/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu</link>
		<comments>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu#comments</comments>
		<pubDate>Wed, 19 May 2010 19:48:13 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Projektowanie aplikacji]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[sitemesh 3]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=898</guid>
		<description><![CDATA[Jak zapowiedziałem w&#160;poprzednim poście tym razem pobawimy się Sitemesh-em i&#160;atrybutami kontekstowymi w&#160;JSP, więc będzie to wpis raczej krótki. Skupimy się na rozdzieleniu szablonów (layoutu) aplikacji na 2 części. Pierwszy szblon zastosujemy do panelu administracyjnego, wyświetlać będzie listy, formularze i&#160;dane, a&#160;także umieści na każdej stronie menu administracyjne. Drugi szablon będzie wykorzystywany jedynie podczas logowania i&#160;prócz formularza  [...]]]></description>
			<content:encoded><![CDATA[<p>Jak zapowiedziałem w&nbsp;<a title="Spring Framework 3.0 Tutorial – cz 3 – spring security" href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-–-cz-3-–-spring-security" target="_blank">poprzednim poście</a> tym razem pobawimy się Sitemesh-em i&nbsp;atrybutami kontekstowymi w&nbsp;JSP, więc będzie to wpis raczej krótki. Skupimy się na rozdzieleniu szablonów (layoutu) aplikacji na 2 części. Pierwszy szblon zastosujemy do panelu administracyjnego, wyświetlać będzie listy, formularze i&nbsp;dane, a&nbsp;także umieści na każdej stronie menu administracyjne. Drugi szablon będzie wykorzystywany jedynie podczas logowania i&nbsp;prócz formularza  nie będzie zawierał nic więcej. Oczywiście jeśli ktoś chce może śmiało dodać więcej szablonów, np. specjalna strona dla obsługi zamówień która zawiera oddzielne menu, czy też<span id="more-898"></span></p>
<p>W <a title=" « Spring Framework 3.0 Tutorial – wstęp Spring Framework 3.0 Tutorial – cz 2 – baza danych, walidacja, wiadomości, encje, hibernate » Spring Framework 3.0 Tutorial – cz 1 – przygotowanie projektu, witaj świecie " href="http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie" target="_blank">pierwszej części tutorialu</a> wspomniałem iż Sitemesh służy do składania stron w&nbsp;całość, dzięki niemu możemy stworzyć szablon strony, do którego będziemy doklejać wyniki stron co skutecznie  ułatwia tworzenie widoków. Co prawda biblioteka ta potrafi więcej (w wersji 2.x) ale z&nbsp;racji, że korzystamy z&nbsp;wersji alpha lepiej używać jedynie podstawowych funkcjonalności (przynajmniej w&nbsp;tej chwili).</p>
<h3>Rozdzielamy szablony</h3>
<p>Sitemesh-a skonfigurowaliśmy w&nbsp;pierwszej części tuorialu, miał on za zadanie składać główny szablon (default.jsp) z&nbsp;widokami wyników wygenerowanymi przez aplikację, teraz zajmiemy się rozdzieleniem szablonów dla widoku logowania oraz dla pozostałej części aplikacji. Jak wiadomo, konfigurację Sitemesh-a trzymamy w&nbsp;klasie <strong>com.darekzon.bookstore.filter.Sitemesh</strong>, i&nbsp;aktualnie zawiera wpis mówiący, że każdy wyniki ma być &#8220;wklejony&#8221; do szablony <strong>default.jsp. </strong>Aby utworzyć dodatkowy szablon wystarczy dopisać regułę która dla żądania <strong>/login.html</strong> będzie stosować inny szablon. Całość wygląda następująco:</p>
<pre class="brush: java;">

package com.darekzon.bookstore.filter;

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

public class Sitemesh extends ConfigurableSiteMeshFilter {
 protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
 builder.addDecoratorPath(&quot;/login.html&quot;, &quot;/views/layout/login.jsp&quot;);
 builder.addDecoratorPath(&quot;/*&quot;, &quot;/views/layout/default.jsp&quot;);
 }

}
</pre>
<p>W powyższym zapisie ważna jest kolejność wpisów (odwrotny zapis przysłaniałby nam szablon <strong>login.jsp </strong>dla wywołania strony logowania.</p>
<p>Teraz wystarczy stworzyć odpowiedni plik (np. bazując na wcześniejszym szablonie) i&nbsp;gotowe, zapytanie o&nbsp;stronę <strong>/login.html</strong> otrzyma własną stronę wynikową.</p>
<h3>Tworzymy menu administracyjne</h3>
<p>Teraz zajmiemy się tworzeniem menu, czynność z&nbsp;pozoru prosta, wystarczy wpisać kilka tagów i&nbsp;gotowe, jak jednak sprawić by nasze menu rozpoznawało gdzie aktualnie się znajdujemy i&nbsp;na bazie tego zaznaczało w&nbsp;menu naszą pozycję? W&nbsp;poprzednim projekcie używałem Sitemesh 2.x który w&nbsp;łatwy sposób odczytywał metatagi stron dzięki czemu łatwo można było określić naszą pozycję, niestety w&nbsp;wersji 3 nie działa to jak trzeba, a&nbsp;na pewno nie jest to w&nbsp;żaden sposób udokumentowane, więc trzeba sobie poradzić w&nbsp;inny sposób. Rozwiązaniem jakie wymyśliłem, jest ustawianie atrybutów strony w&nbsp;zależności od tego gdzie jesteśmy. Jak to działa?</p>
<p>Jak wszyscy wiemy, każda akcja posiada własny plik za pomącą którego generowany jest widok, w&nbsp;każdym z&nbsp;tych plików wstawiamy zapis:</p>
<pre class="brush: java;">

&lt;%
 pageContext.setAttribute(&quot;moduleName&quot;,&quot;content&quot;, PageContext.REQUEST_SCOPE);
 pageContext.setAttribute(&quot;pageName&quot;,&quot;index&quot;, PageContext.REQUEST_SCOPE);
%&gt;
</pre>
<p>Powyższy kod, ustawił nam w&nbsp;pliku widoku 2 atrybuty, <strong>moduleName</strong> która oznaczać będzie w&nbsp;jakiej grupie znajduje się strona oraz <strong>pageName</strong> która oznacza jaka strona jest generowana, <strong>PageContext.REQUEST_SCOPE</strong> mówi aplikacji, że atrybuty będą widoczne tylko w&nbsp;zakresie aktualnego żądania (więcej nam nie trzeba).</p>
<p>Zabieramy się za tworzenie menu, ponieważ menu. Możemy je stworzyć w&nbsp;pliku szablonu albo w&nbsp;oddzielnym pliku który dołączymy do naszego szablonu, ponieważ nie lubię chaosu, wybieram rozwiązanie drugie.<br />
Tworzymy plik <strong>navigation.jsp</strong> (w folderze includes) oraz dołączamy go do naszego szablonu <strong>default.jsp</strong> dyrektywą:</p>
<pre class="brush: xml;">

&lt;%@ include file=&quot;../includes/navigation.jsp&quot; %&gt;
</pre>
<p>Dołączony plik ma za zadanie odczytać atrybuty ustawione w&nbsp;widokach (patrz wyżej) oraz oznaczenie grupy i&nbsp;podstron klasą <strong>active</strong> gdy są one aktywne, dzięki czemu będziemy mogli za pomącą CSS-a odpowiednio pokazywać i&nbsp;ukrywać nasze menu. Nasze menu zbudowane będzie z&nbsp;zagnieżdżonych list nieuporządkowanych według struktury:</p>
<pre class="brush: xml;">

&lt;ul&gt;
  &lt;li&gt;GRUPA
    &lt;ul&gt;
      &lt;li&gt;PODSTRONA&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>Plik ten prezentuje się następująco:</p>
<pre class="brush: xml;">
&lt;%@ taglib prefix=&quot;tag&quot; uri=&quot;http://www.springframework.org/tags&quot; %&gt;
&lt;%
 String moduleName = (String) pageContext.getAttribute(&quot;moduleName&quot;,PageContext.REQUEST_SCOPE);
 String pageName = (String) pageContext.getAttribute(&quot;pageName&quot;,PageContext.REQUEST_SCOPE);
%&gt;&lt;br /&gt;
&lt;nav&gt;
 &lt;ul&gt;
 &lt;li class=&quot;&lt;% if(moduleName==&quot;content&quot;){ out.print(&quot;active&quot;); } %&gt;&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/content.html&quot;&gt;
 &lt;tag:message code=&quot;menu.content&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;li class=&quot;&lt;% if(moduleName==&quot;catalog&quot;){ out.print(&quot;active&quot;); } %&gt;&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/catalog.html&quot;&gt;
 &lt;tag:message code=&quot;menu.catalog&quot; /&gt;
 &lt;/a&gt;
 &lt;ul&gt;
 &lt;li class=&quot;&lt;% if(moduleName==&quot;categories&quot;){ out.print(&quot;active&quot;); } %&gt;&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/catalog/categories.html&quot;&gt;
 &lt;tag:message code=&quot;menu.categories&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;li&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/catalog/books.html&quot;&gt;
 &lt;tag:message code=&quot;menu.books&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
 &lt;li class=&quot;&lt;% if(moduleName==&quot;order&quot;){ out.print(&quot;active&quot;); } %&gt;&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/orders.html&quot;&gt;
 &lt;tag:message code=&quot;menu.orders&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;li class=&quot;&lt;% if(moduleName==&quot;client&quot;){ out.print(&quot;active&quot;); } %&gt;&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/clients.html&quot;&gt;
 &lt;tag:message code=&quot;menu.clients&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;li&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/settings.html&quot;&gt;
 &lt;tag:message code=&quot;menu.settings&quot; /&gt;
 &lt;/a&gt;
 &lt;ul&gt;
 &lt;li&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/settings/administrators.html&quot;&gt;
 &lt;tag:message code=&quot;menu.administrators&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;
 &lt;/li&gt;
 &lt;li class=&quot;logout&quot;&gt;
 &lt;a href=&quot;&lt;%= request.getContextPath() %&gt;/wyloguj.html&quot;&gt;
 &lt;tag:message code=&quot;menu.logout&quot; /&gt;
 &lt;/a&gt;
 &lt;/li&gt;
 &lt;/ul&gt;
&lt;/nav&gt;
</pre>
<p>Plik dołącza bibliotekę tagów wykorzystywaną do obsługi wiadomości, oraz odczytuje wcześniej ustawione atrybuty zapisując je do zmiennych. W&nbsp;kolejnych pozycjach menu następuje sprawdzenie aktualnej pozycji.<br />
Gdy <strong>moduleName</strong> jest równe wymaganej wartości zostaje ustawiona klasa <strong>active</strong>, to samo tyczy się zmiennej <strong>pageName. </strong>Dzięki takiemu rozwiązaniu mamy nasze &#8220;dynamiczne&#8221; menu.</p>
<p>Jeśli ktoś zna lepsze rozwiązanie z&nbsp;chęcią je poznam.</p>
<p>PS. Jeśli chodzi o&nbsp;zapis <strong>request.getContextPath()</strong> to zwraca  nam on ścieżkę wywołania aplikacji, tzn. jeśli nasza aplikacja działała  by w&nbsp;folderze <strong>bookstore </strong>a jej uruchomienie wiązałoby się z&nbsp; wpisanie adresu <strong>http://example.com/bookstore/</strong> to <strong>getContextPath()</strong> zwróci nam ciąg <strong>/bookstore</strong>, dzięki czemu wszystkie linki będą  poprawnie obsłużone bez względu na to, czy nasza aplikacja jest  uruchomiona na własnej domenie, czy też działa &#8220;w folderze&#8221;.</p>
<h3>Jak pobrać projekt</h3>
<blockquote><p>Projekt został umieszczony na serwerach <a href="http://kenai.com/" target="_blank">Kenai.com</a>. Adres bezpośredni do projektu: <a href="http://kenai.com/projects/summer-bookstore" target="_blank">http://kenai.com/projects/summer-bookstore</a>.<br />
Dodatkowo zostało uruchomione repozytorium <strong>GIT</strong> dla wszystkich chętnych i&nbsp;dostępny jest pod adresem: <a href="git://kenai.com/summer-bookstore~books0re-source " target="_blank">git://kenai.com/summer-bookstore~books0re-source</a></p>
<p>Projekt umieszczony jest również w&nbsp;repozytorium Github pod adresem: <a href="http://github.com/darek/bookstore" target="_blank">http://github.com/darek/bookstore</a></p></blockquote>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+4+%E2%80%93+sitemesh%2C+menu%2C+atrybuty+kontekstu" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;t=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+4+%E2%80%93+sitemesh%2C+menu%2C+atrybuty+kontekstu" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-–-cz-4-–-sitemesh-menu-atrybuty-kontekstu/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;n=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+4+%E2%80%93+sitemesh%2C+menu%2C+atrybuty+kontekstu&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+4+%E2%80%93+sitemesh%2C+menu%2C+atrybuty+kontekstu" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+4+%E2%80%93+sitemesh%2C+menu%2C+atrybuty+kontekstu&amp;description=Jak%20zapowiedzia%C5%82em%20w%20poprzednim%20po%C5%9Bcie%20tym%20razem%20pobawimy%20si%C4%99%20Sitemesh-em%20i%20atrybutami%20kontekstowymi%20w%20JSP%2C%20wi%C4%99c%20b%C4%99dzie%20to%20wpis%20raczej%20kr%C3%B3tki.%20Skupimy%20si%C4%99%20na%20rozdzieleniu%20szablon%C3%B3w%20%28layoutu%29%20aplikacji%20na%202%20cz%C4%99%C5%9Bci.%20Pierwszy%20szblon%20zastosujemy%20do%20panelu%20administracyjnego%2C%20wy%C5%9Bwietla%C4%87%20b%C4%99dzi" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/Bu9yQyusPXoownSJgjZ2raKrIYA/0/da"><img src="http://feedads.g.doubleclick.net/~a/Bu9yQyusPXoownSJgjZ2raKrIYA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Bu9yQyusPXoownSJgjZ2raKrIYA/1/da"><img src="http://feedads.g.doubleclick.net/~a/Bu9yQyusPXoownSJgjZ2raKrIYA/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/sBQYLIjZxYY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-4-%e2%80%93-sitemesh-menu-atrybuty-kontekstu</feedburner:origLink></item>
		<item>
		<title>Spring Framework 3.0 Tutorial – cz 3 – spring security</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/XRfn7n6_ax8/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security</link>
		<comments>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security#comments</comments>
		<pubDate>Tue, 18 May 2010 15:02:11 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring security]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=819</guid>
		<description><![CDATA[W drugiej części tutorialu udało nam się stworzyć mechanizm dodawania administratorów do naszego panelu, byłoby nierozsądne by każdy użytkownik miał do niego dostęp, dlatego w&#160;tej części zajmiemy się mechanizmem kontroli dostępu do naszej aplikacji. Wpis obejmie konfigurację mechanizmów uwierzytelniania oraz autoryzacji wykorzystujących Spring Security (w tym hasła użytkowników zakodowane algorytmem sha256 + z&#160;wykorzystaniem tzw. soli). [...]]]></description>
			<content:encoded><![CDATA[<p>W <a title="Spring Framework 3.0 Tutorial – cz 2 – baza danych, walidacja, wiadomości, encje, hibernate" href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-–-cz-2-–-baza-danych-walidacja-wiadomosci-encje-hibernate" target="_blank">drugiej części</a> tutorialu udało nam się stworzyć mechanizm dodawania administratorów do naszego panelu, byłoby nierozsądne by każdy użytkownik miał do niego dostęp, dlatego w&nbsp;tej części zajmiemy się mechanizmem kontroli dostępu do naszej aplikacji. Wpis obejmie konfigurację mechanizmów uwierzytelniania oraz autoryzacji wykorzystujących Spring Security (w tym hasła użytkowników zakodowane algorytmem sha256 + z&nbsp;wykorzystaniem tzw. soli). Miało być też coś o&nbsp;Sitemeshu, ale zrobię to w&nbsp;następnym odcinku który pojawi się na dniach.<span id="more-819"></span></p>
<h3>Zabezpieczanie aplikacji</h3>
<p>Konfiguracja zabezpieczeń obejmuje dwa pliki, <strong>web-security.xml</strong> oraz <strong>web.xml. </strong>Pierwszy z&nbsp;nich zawiera już konfigurację obiektu szyfrującego hasła oraz mechanizm soli (<a title="Spring Framework 3.0 Tutorial – cz 2 – baza danych, walidacja, wiadomości, encje, hibernate" href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%E2%80%93-cz-2-%E2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate">z wcześniejszego tutorialu</a>), tym razem musimy dodać obsługę poziomów dostępu oraz mechanizmu uwierzytelniania opartego o&nbsp;bazę danych. Konfiguracja taka prócz skonfigurowanych już wcześniej obiektów zawierać powinna manager uwierzytelniania, dostawcę danych uwierzytelnianych, filtr przechwytujący, oraz listę reguł które będą mówić mechanizmowi, kto gdzie ma dostęp i&nbsp;ew. gdzie ma się zalogować. Zmiany w&nbsp;tym pliku wyglądają następująco<em> (pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: xml;">

&lt;authentication-manager alias=&quot;authenticationManager&quot;&gt;
 &lt;authentication-provider ref=&quot;authProvider&quot; /&gt;
 &lt;/authentication-manager&gt;

 &lt;beans:bean id=&quot;authProvider&quot;
 class=&quot;org.springframework.security.authentication.dao.DaoAuthenticationProvider&quot;&gt;
 &lt;beans:property name=&quot;userDetailsService&quot; ref=&quot;userService&quot; /&gt;
 &lt;beans:property name=&quot;passwordEncoder&quot; ref=&quot;passwordEncoder&quot; /&gt;
 &lt;beans:property name=&quot;saltSource&quot; ref=&quot;saltSource&quot; /&gt;
 &lt;beans:property name=&quot;includeDetailsObject&quot; value=&quot;true&quot; /&gt;
 &lt;/beans:bean&gt;

 &lt;beans:bean id=&quot;authenticationProcessingFilterEntryPoint&quot;
 class=&quot;org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint&quot;&gt;
 &lt;beans:property name=&quot;forceHttps&quot; value=&quot;false&quot; /&gt;
 &lt;beans:property name=&quot;loginFormUrl&quot; value=&quot;/login.html&quot; /&gt;
 &lt;/beans:bean&gt;

 &lt;http entry-point-ref=&quot;authenticationProcessingFilterEntryPoint&quot; auto-config=&quot;true&quot;&gt;
 &lt;intercept-url pattern=&quot;/**&quot; access=&quot;ROLE_ADMIN&quot; /&gt;
 &lt;intercept-url pattern=&quot;/login.html&quot; filters=&quot;none&quot; /&gt;
 &lt;logout logout-url=&quot;/logout.html&quot; /&gt;
 &lt;anonymous granted-authority=&quot;ROLE_ANONYMOUS&quot; /&gt;
 &lt;form-login login-page=&quot;/login.html&quot; login-processing-url=&quot;/j_spring_security_check.html&quot;
 authentication-failure-url=&quot;/login.html?error=true&quot; /&gt;
 &lt;/http&gt;
</pre>
<p>Czyli:</p>
<p><strong>authentication-manager</strong>: mechanizm odpowiedzialny za uwierzytelnianie, przekazujemy mu referencje do obiektu odpowiedzialnego za dostarczenie informacji o&nbsp;użytkownikach</p>
<p><strong>authProvider</strong>: obiekt odpowiedzialny jest za dostarczenie użytkowników (tj, pobranie użytkownika na podstawie loginu), w&nbsp;naszym wypadku obiekt korzysta z&nbsp;bazy danych oraz dodatkowych obiektów szyfrujących. authProvider posiada również parametr <strong>userDetailsService </strong>który powinien wskazywać na obiekt odpowiedzialny za wyszukanie użytkownika, obiekt taki wskazujemy poprzez nadanie mu id <strong>userService</strong> (patrz web-data.xml).</p>
<p><strong>authenticationProcessingFilterEntryPoint</strong>: obiekt rozpoczynający proces autoryzacji, przechowuje ścieżkę (w formie URL-a) do strony z&nbsp;formularzem logowania</p>
<p><strong>&lt;http&gt;: </strong>najważniejsza część, tutaj ustawiamy poziomy dostępów do konkretnych zasobów, ustalamy również formularza logowania oraz adres powodujący wylogowanie. (<strong>UWAGA!</strong> jeśli ustalamy niestandardowy adres logowania należy wyłączyć mu poziom dostepu (<em>filter=&#8221;none&#8221;</em>) inaczej dostaniemy pętle przekierowań)</p>
<p>Według powyższej konfiguracji nasza aplikacja jest dostępna tylko dla użytkowników z&nbsp;poziomem dostępu <strong>ROLE_ADMIN</strong>, jeśli nie jesteś zalogowany zostajesz automatycznie przekierowany na stronę <strong>/login.html</strong> która wyświetla formularz i&nbsp;wysyła go pod adres <strong>/j_spring_security_check.html</strong>, jeśli logowanie się nie powiedzie, do adresu logowania zostanie dopisany parametr <strong>error=true, </strong>gdy natomiast podasz poprawne dane logujące zostaniesz przeniesiony na wcześniej żądaną stronę, lub na stronę główną serwisu. Aby się wylogować musisz wejść pod adres <strong>/logout.html</strong>.</p>
<p>W pliku <strong>web.xml</strong> ustawiamy filtr który każde żądanie kończące się rozszerzeniem <strong>.html</strong> będzie &#8220;testował&#8221; pod względem bezpieczeństwa (tzn. czy użytkownik wywołujący żądanie ma prawo je wykonać), zdefiniowany filtr wygląda tak <em>(pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: xml;">

&lt;filter&gt;
 &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
 &lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;/filter-class&gt;
 &lt;/filter&gt;
 &lt;filter-mapping&gt;
 &lt;filter-name&gt;springSecurityFilterChain&lt;/filter-name&gt;
 &lt;url-pattern&gt;*.html&lt;/url-pattern&gt;
 &lt;/filter-mapping&gt;
</pre>
<p>Jak wspomniałem wcześniej gdy użytkownik nie ma praw do wykonania danego żądania, bądź nie jest zalogowany zostaje automatycznie przekierowany do strony <strong>loguj.html</strong>. Ponieważ nie jest to standardowa strona musimy sami obsłużyć to żądanie, na szczęście nie jest to trudne, wymaga tylko 2 elementów, metody w&nbsp;kontrolerze która obsłuży żądanie oraz widoku formularza który wyświetli pola do podania loginu i&nbsp;hasła. Akcja w&nbsp;kontrolerze dodatkowo przyjmie parametr <strong>error </strong>(o czym mówiłem wcześniej) który posłuży do wykrycia czy akcja logowania się nie powiodła i&nbsp;jeśli jest to prawdą wyświetli odpowiedni komunikat.</p>
<p>Metodę obsługującą logowanie zawarłem w&nbsp;kontrolerze <strong>IndexController</strong> i&nbsp;wygląda ona następująco <em>(pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: java;">
@RequestMapping(value = &quot;/login&quot;, method = RequestMethod.GET)
 public ModelAndView login(@RequestParam(value = &quot;error&quot;, required = false, defaultValue = &quot;false&quot;) boolean error) {
 ModelAndView mav = new ModelAndView(&quot;index/login&quot;);
 mav.addObject(&quot;isError&quot;, error);
 return mav;
 }
</pre>
<p>@<strong>RequestParam</strong> pobiera parametr przekazywany w&nbsp;żądaniu i&nbsp;przekazuje go w&nbsp;zmiennej error, parametr ten nie jest wymagany, więc jeśli nie istnieje do zmiennej <strong>error</strong> zostanie przypisana wartość domyślna <strong>false.</strong> Parametr <strong>error</strong> przekazywany jest do widoku który prezentuje się następująco:</p>
<pre class="brush: xml;">

&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&gt;
&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jstl/core_rt&quot; %&gt;
&lt;%@ taglib prefix=&quot;tag&quot; uri=&quot;http://www.springframework.org/tags&quot; %&gt;
&lt;html&gt;
&lt;head&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;c:if test=&quot;${isError eq true}&quot;&gt;
 &lt;div&gt;&lt;tag:message code=&quot;login_error&quot; /&gt;&lt;/div&gt;
&lt;/c:if&gt;
&lt;div&gt;
 &lt;form action=&quot;&lt;c:url value=&quot;/j_spring_security_check.html&quot; /&gt;&quot; method=&quot;POST&quot;&gt;
 &lt;div&gt;
 &lt;label for=&quot;login&quot;&gt;&lt;tag:message code=&quot;administrator.username&quot;/&gt;&lt;/label&gt;
 &lt;input id=&quot;login&quot; name=&quot;j_username&quot;/&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;label for=&quot;password&quot;&gt;&lt;tag:message code=&quot;administrator.password&quot;/&gt;&lt;/label&gt;
 &lt;input type=&quot;password&quot; id=&quot;password&quot; name=&quot;j_password&quot;/&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;input type=&quot;submit&quot;/&gt;
 &lt;/div&gt;
 &lt;/form&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Jak widzimy powyżej, najpierw sprawdzamy czy zmienna <strong>isError</strong> jest równa <strong>true</strong> co by oznaczało, że podaliśmy błędne dane podczas logowania, jeśli warunek jest spełnony zostaje wyświetlony komunikat. Następnie tworzymy formularz który metodą POST przesyła dane pod adres <strong>/j_spring_security_check.html</strong> który jak pamiętacie ustawiliśmy wcześniej w&nbsp;pliku <strong>web-security.xml</strong>. Formularz musi zawierać przynajmniej dwa pola (login i&nbsp;hasło) które dodatkowo powinny przyjmować odpowiednie nazwy: <strong>j_username</strong> dla nazwy użytkownika oraz <strong>j_password</strong> dla jego hasła.</p>
<p>Byłoby wspaniale gdyby na tym zakończyła się konfiguracja, niestety musimy zmodyfikować klasę encji <strong>Account</strong> by mogła być poprawnie przetwarzana przez Spring Security. Aby nasza klasa była poprawnie obsługiwana musi rozszerzać klasę <strong>User</strong> (z pakietu org.springframework.security.core.userdetails) oraz implementować interfejs <strong>UserDetails</strong> (z tego samego pakietu).<br /> W&nbsp;naszym wypadku implementacja wygląda następująco <em>(pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: java;">

public class Account extends User implements UserDetails {

@Override
 public Collection&lt;GrantedAuthority&gt; getAuthorities() {
 Set&lt;GrantedAuthority&gt; ga = new HashSet&lt;GrantedAuthority&gt;();
 for (AccountRole ar : this.accountRole) {
 ga.add(new GrantedAuthorityImpl(ar.getRole()));
 }
 return ga;
 }
&lt;pre&gt; @Override
 public boolean isEnabled() {
 if (this.accountRole.size() &gt; 0) {
 return true;
 }
 return false;
 }&lt;/pre&gt;
@Override
 public boolean isAccountNonExpired() {
 return this.isEnabled();
 }

 @Override
 public boolean isAccountNonLocked() {
 return this.isEnabled();
 }

 @Override
 public boolean isCredentialsNonExpired() {
 return this.isEnabled();
 }

}
</pre>
<p>Zostały zaimplementowane metody:</p>
<p><strong>public Collection&lt;GrantedAuthority&gt; getAuthorities()</strong> &#8211; zwraca listę poziomów dostępu jakie posiada użytkownik, czyli nasze <strong>AccountRole,</strong><br />
<strong>public boolean isEnabled()</strong> &#8211; zwraca <strong>true</strong> jeśli konto jest aktywne, w&nbsp;naszym wypadku kierujemy się zasadą &#8220;Jeśli użytkownik ma przypisaną rolę to konto jest aktywne&#8221;,<br />
<strong>public boolean isAccountNonExpired() &#8211; </strong>zwraca <strong>true</strong> jeśli konto nie wygasło,<br />
<strong>public boolean isAccountNonLocked()</strong> &#8211; zwraca <strong>true</strong> jeśli konto nie jest zablokowane,<br />
<strong>public boolean isCredentialsNonExpired()</strong> &#8211; zwraca <strong>true</strong> jeśli poziomy dostępów nie wygasły</p>
<p>Musimy również dodać metodę <strong>loadUserByUsername</strong> która będzie wykorzystywana przez dostawcę autoryzacji do znalezienia użytkownika. Funkcja ta wykorzystuje metodę <strong>findUsername</strong> z&nbsp;klasy <strong>AccountDao</strong> którą wykorzystujemy podczas rejestracji, i&nbsp;prezentuje się ona następująco <em>(pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: java;">

@Override
 public UserDetails loadUserByUsername(String username)
 throws UsernameNotFoundException, DataAccessException {
 try {
 return (UserDetails) accountDao.findUsername(username);
 } catch (UserNotFoundException e) {
 throw new UsernameNotFoundException(username);
 }
 }
</pre>
<p>Metodę tą dodajemy do obiektu który jest wskazany w&nbsp;obiekcie <strong>authProvider</strong> jako parametr <strong>userDetailsService</strong>, w&nbsp;naszym wypadku było to dodanie identyfikatora <strong>userService</strong> do obiektu <strong>AccountServiceImpl</strong> w&nbsp;pliku <strong>web-data.xml</strong> <em>(pełna zawartość pliku w repozytorium – zobacz koniec wpisu)</em>:</p>
<pre class="brush: xml;">

&lt;bean id=&quot;userService&quot;
class=&quot;com.darekzon.bookstore.service.AccountServiceImpl&quot; /&gt;
</pre>
<p>I to wszystko, tak skonfigurowany mechanizm powinien działać poprawnie, pamiętajcie tylko, żeby włączyć zabezpieczenia po dodaniu użytkownika.</p>
<h3>Jak pobrać projekt</h3>
<blockquote><p>Projekt został umieszczony na serwerach <a href="http://kenai.com/" target="_blank">Kenai.com</a>. Adres bezpośredni do projektu: <a href="http://kenai.com/projects/summer-bookstore" target="_blank">http://kenai.com/projects/summer-bookstore</a>.<br />
Dodatkowo zostało uruchomione repozytorium <strong>GIT</strong> dla wszystkich chętnych i&nbsp;dostępny jest pod adresem: <a href="git://kenai.com/summer-bookstore~books0re-source " target="_blank">git://kenai.com/summer-bookstore~books0re-source</a></p>
<p>Projekt umieszczony jest również w&nbsp;repozytorium Github pod adresem: <a href="http://github.com/darek/bookstore" target="_blank">http://github.com/darek/bookstore</a></p></blockquote>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+3+%E2%80%93+spring+security" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;t=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+3+%E2%80%93+spring+security" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-–-cz-3-–-spring-security/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;n=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+3+%E2%80%93+spring+security&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+3+%E2%80%93+spring+security" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+3+%E2%80%93+spring+security&amp;description=W%20drugiej%20cz%C4%99%C5%9Bci%20tutorialu%20uda%C5%82o%20nam%20si%C4%99%20stworzy%C4%87%20mechanizm%20dodawania%20administrator%C3%B3w%20do%20naszego%20panelu%2C%20by%C5%82oby%20nierozs%C4%85dne%20by%20ka%C5%BCdy%20u%C5%BCytkownik%20mia%C5%82%20do%20niego%20dost%C4%99p%2C%20dlatego%20w%20tej%20cz%C4%99%C5%9Bci%20zajmiemy%20si%C4%99%20mechanizmem%20kontroli%20dost%C4%99pu%20do%20naszej%20aplikacji.%20Wpis%20obejmie%20konfiguracj%C4%99%20mechani" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/aDkxtSFrRbD6KH7doeb8atIKAwY/0/da"><img src="http://feedads.g.doubleclick.net/~a/aDkxtSFrRbD6KH7doeb8atIKAwY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/aDkxtSFrRbD6KH7doeb8atIKAwY/1/da"><img src="http://feedads.g.doubleclick.net/~a/aDkxtSFrRbD6KH7doeb8atIKAwY/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/XRfn7n6_ax8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-3-%e2%80%93-spring-security</feedburner:origLink></item>
		<item>
		<title>Spring Framework 3.0 Tutorial – cz 2 – baza danych, walidacja, wiadomości, encje, hibernate</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/4aMeKcaTXqM/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate</link>
		<comments>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate#comments</comments>
		<pubDate>Thu, 06 May 2010 08:48:27 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[javaee]]></category>
		<category><![CDATA[jsr 303]]></category>
		<category><![CDATA[persistence]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=736</guid>
		<description><![CDATA[W tej części tutorialu skupimy się na skonfigurowaniu połączenia z&#160;bazą danych, podłączeniu frameworka hibernate do naszej aplikacji oraz zobaczymy jak tworzyć encje i&#160;jak sprawdzać poprawność danych przed ich zapisem (walidacja). Przygotowanie do pracy W poprzedniej części przygotowaliśmy w&#160;ramach części klienckiej małą aplikację &#8220;witaj świecie&#8221;, ponieważ projekt nie zawierał elementów stricte przyporządkowanych części dla klienta możemy [...]]]></description>
			<content:encoded><![CDATA[<p>W tej części tutorialu skupimy się na skonfigurowaniu połączenia z&nbsp;bazą danych, podłączeniu frameworka hibernate do naszej aplikacji oraz zobaczymy jak tworzyć encje i&nbsp;jak sprawdzać poprawność danych przed ich zapisem (walidacja).<span id="more-736"></span></p>
<h2>Przygotowanie do pracy</h2>
<p>W poprzedniej części przygotowaliśmy w&nbsp;ramach części klienckiej małą aplikację &#8220;witaj świecie&#8221;, ponieważ projekt nie zawierał elementów stricte przyporządkowanych części dla klienta możemy skopiować go (głównie pliki konfiguracyjne) i&nbsp;użyć w&nbsp;panelu administracyjnym (prawie jak <a href="http://pl.wikipedia.org/wiki/Antywzorzec_projektowy#Antywzorce_metodologiczne" target="_blank">copypasteryzm</a>).</p>
<p>Aby przejść przez tą część tutoriala będziemy musieli zainstalować bazę danych <a href="http://www.postgresql.org/" target="_blank">PostgreSQL</a> oraz pobrać kilka dodatkowy bibliotek (zrobimy to wykorzystując mavena).<br />
Jak wspomniałem w&nbsp;pierwszym odcinku tutoriala, wspólne klasy będą trzymane w&nbsp;osobnym projekcie &#8220;<strong>bookstore-lib&#8221;</strong>, tam przechowywane będą klasy Encji, Dao oraz Serwisy, a&nbsp;także wspólne klasy które będą wykonywać specyficzne zadania (powstaną wkrótce), eclipse zadba, by dołączyć je automatycznie podczas kompilacji. Projekt &#8220;bookstore-lib&#8221; również korzysta z&nbsp;mavena do obsługi bibliotek wykorzystanych w&nbsp;projekcie, nie posiada on natomiast zintegrowanego Spring frameworka (co jest logiczne). Nad jego konfiguracją rozpisywać się nie będę, stworzyłem czysty projekt, dodałem obsługę mavena i&nbsp;zacząłem pisać klasy (w tym przypadku na pierwszy ogień poszły Encje), gdy eclipse wykrył, że nie mam jakiejś klasy zależnej dodałem ją do projektu ustawiając odpowiedni zakres (<a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope" target="_blank">scope</a> &#8211; jeśli klasa wykorzystywana jest w&nbsp;panelu, zakres ustawiałem na runtime, jeśli była używana stricte w&nbsp;<strong>bookstore-lib</strong>, zakres ustawiany był na compile).</p>
<p>Projekt &#8220;<strong>bookstore-admin</strong>&#8221; prócz bibliotek potrzebnych do uruchomienia Springframework-a potrzebuje również bibliotek odpowiedzialnych za obsługę bazy danych oraz walidację formularzy, do pliku <strong>pom.xml</strong> dodałem następujące biblioteki (tu również skorzystałem z&nbsp;zakresów &#8211; scope, dzięki czemu aplikacje nie posiadały zdublowanych bibliotek).</p>
<pre class="brush: xml;">
&lt;dependency&gt;
 &lt;groupId&gt;postgresql&lt;/groupId&gt;
 &lt;artifactId&gt;postgresql&lt;/artifactId&gt;
 &lt;version&gt;8.4-701.jdbc4&lt;/version&gt;
 &lt;type&gt;jar&lt;/type&gt;
 &lt;scope&gt;compile&lt;/scope&gt;
 &lt;/dependency&gt;
 &lt;dependency&gt;
 &lt;groupId&gt;org.springframework&lt;/groupId&gt;
 &lt;artifactId&gt;spring-orm&lt;/artifactId&gt;
 &lt;version&gt;3.0.2.RELEASE&lt;/version&gt;
 &lt;type&gt;jar&lt;/type&gt;
 &lt;scope&gt;compile&lt;/scope&gt;
 &lt;/dependency&gt;
 &lt;dependency&gt;
 &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
 &lt;artifactId&gt;hibernate-core&lt;/artifactId&gt;
 &lt;version&gt;3.3.2.GA&lt;/version&gt;
 &lt;type&gt;jar&lt;/type&gt;
 &lt;scope&gt;compile&lt;/scope&gt;
 &lt;/dependency&gt;
 &lt;dependency&gt;
 &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
 &lt;artifactId&gt;hibernate-entitymanager&lt;/artifactId&gt;
 &lt;version&gt;3.4.0.GA&lt;/version&gt;
 &lt;type&gt;jar&lt;/type&gt;
 &lt;scope&gt;compile&lt;/scope&gt;
 &lt;/dependency&gt;
 &lt;dependency&gt;
 &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
 &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
 &lt;version&gt;1.5.8&lt;/version&gt;
 &lt;type&gt;jar&lt;/type&gt;
 &lt;scope&gt;compile&lt;/scope&gt;
 &lt;/dependency&gt;
&lt;dependency&gt;
 &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
 &lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
 &lt;version&gt;4.0.2.GA&lt;/version&gt;
 &lt;/dependency&gt;
</pre>
<h2>Konfiguracja bazy danych</h2>
<p>Konfiguracja bazy danych jak i&nbsp;wszystkich elementów związanych z&nbsp;obsługą zapisu do bazy danych oraz odczytu z&nbsp;niej znajduje się w&nbsp;pliku <strong>web-data.xml</strong> (trzeba być porządnym programistą i&nbsp;nie tworzyć śmietnika konfiguracyjnego).<br />
Zanim skonfigurujemy połączenie z&nbsp;bazą danych musimy stworzyć użytkownika bazy danych oraz dodać bazę z&nbsp;którą będzie się łączyć, jeśli ktoś nie wie polecam <a href="http://google.com" target="_blank">google.com</a> lub program <a href="http://www.pgadmin.org/" target="_blank">pgAdmin</a>. Połączenie z&nbsp;bazą danych możemy skonfigurować na 2 sposoby (tyle znam), pierwszy (standardowy), czyli dostęp do bazy poprzez adres serwera+port oraz dane uwierzytelniające, drugi to dostęp do bazy poprzez nazwę JNDI (czytaj więcej o <a href="http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Resources2.html" target="_blank">Java Naming and Directory Interface API</a>), ważną zaletą (moim zdaniem) połączenia JNDI jest niezależność ustawień autoryzacyjnych, ponieważ łączymy się z&nbsp;bazą nie poprzez login i&nbsp;hasło, a&nbsp;ustaloną wcześniej przez serwer nazwę, możliwe jest bezproblemowe (bez potrzeby ponownego grzebania w&nbsp;konfiguracji) zmienianie danych autoryzacyjnych, czy też adresu bazy danych dlatego też oprę naszą aplikację o&nbsp;ten typ połączenia.<br />
Ponieważ połączenia JNDI opierają się na skonfigurowanej nazwie musimy taką konfigurację wprowadzić. W&nbsp;naszym przypadku (tomcat 6.0) robimy to w&nbsp;pliku <strong>TOMCAT_HOME/conf/context.xml</strong><sup>1</sup> poprzez wpisanie między tagi &lt;context&gt; zawartości:</p>
<pre class="brush: xml;">&lt;Resource auth=&quot;Container&quot; driverClassName=&quot;org.postgresql.Driver&quot; name=&quot;bookstore&quot; password=&quot;bookstore&quot; type=&quot;javax.sql.DataSource&quot; url=&quot;jdbc:postgresql://localhost:5432/bookstore&quot; username=&quot;bookstore&quot;/&gt;</pre>
<p>Co w&nbsp;skrócie oznacza &#8220;<em>przypisz nazwie <strong>bookstore</strong> połączenie do bazy o&nbsp;nazwie <strong>bookstore</strong> znajdującej się pod adresem <strong>localhost</strong>, na porcie <strong>5432</strong> wykorzystując nazwę użytkownika <strong>bookstore</strong> oraz hasło <strong>bookstore</strong>&#8220;.</em></p>
<p>Nasza aplikacja korzystać będzie z&nbsp;frameworka hibernate, dlatego potrzebujemy skonfigurować jego działanie. Konfiguracja taka polega na utworzeniu pliku  <strong>hibernate.cfg.xml</strong> w  <strong>classpath</strong> (np. src/META-INF; może ktoś zna polski odpowiednik classpath) i&nbsp;wpisujemy zawartość:</p>
<pre class="brush: xml;">
&lt;!DOCTYPE hibernate-configuration PUBLIC
 &quot;-//Hibernate/Hibernate Configuration DTD 3.0//EN&quot;
 &quot;http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd&quot;&gt;
&lt;hibernate-configuration&gt;
 &lt;session-factory&gt;
 &lt;property name=&quot;hibernate.dialect&quot;&gt;org.hibernate.dialect.PostgreSQLDialect&lt;/property&gt;
 &lt;property name=&quot;hibernate.hbm2ddl.auto&quot;&gt;update&lt;/property&gt;
 &lt;property name=&quot;hibernate.show_sql&quot;&gt;true&lt;/property&gt;
 &lt;property name=&quot;hibernate.format_sql&quot;&gt;true&lt;/property&gt;
 &lt;property name=&quot;hibernate.use_sql_comments&quot;&gt;true&lt;/property&gt;
 &lt;mapping
 class=&quot;com.darekzon.bookstore.domain.Account&quot; /&gt;
 &lt;mapping
 class=&quot;com.darekzon.bookstore.domain.AccountRole&quot; /&gt;
 &lt;mapping
 class=&quot;com.darekzon.bookstore.domain.Administrator&quot; /&gt;
 &lt;/session-factory&gt;
&lt;/hibernate-configuration&gt;
</pre>
<p>Pliik ustawia kolejno:</p>
<ol>
<li>hibernate.dialect -  jaki język zapytań będzie wykorzystywany (w tym wypadku rozszerzenia dodane przez postgresql)</li>
<li>hibernate.hbm2ddl.auto &#8211; automatycznie aktualizuj schemat bazy danych na podstawie class encji (super sprawa)</li>
<li>hibernate.show_sql &#8211; pokazuje zapytania sql jakie wykonuje hibernate (dobre przy debugowaniu, czasem wprowadza chaos do konsoli)</li>
<li>hibernate.format_sql &#8211; formatuje w/w zapytania, przydaje się</li>
<li>hibernate.user_sql_comments &#8211; dodatkowe komentarze, pomagają zorientować się jakie zapytanie aktualnie jest wykonywane</li>
<li>mapping class  &#8211; wskazanie jakie klasy traktowane są jako klasy encji (muszą być oznaczone adnotacją <strong>@Entity</strong>), wykorzystywane przy aktualizacji schematów</li>
</ol>
<p>Drugim ważnym plikiem jest <strong>persistence.xml</strong> który konfiguruje nam PersistenceUnit czyli jednostę utrwalającą. Plik ten ma zawartość:</p>
<pre class="brush: xml;">
&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;
 version=&quot;2.0&quot;&gt;
 &lt;persistence-unit name=&quot;bookstorePU&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
 &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
 &lt;jta-data-source&gt;bookstore&lt;/jta-data-source&gt;
 &lt;class&gt;com.darekzon.bookstore.domain.Administrator&lt;/class&gt;
 &lt;class&gt;com.darekzon.bookstore.domain.Account&lt;/class&gt;
 &lt;class&gt;com.darekzon.bookstore.domain.AccountRole&lt;/class&gt;
 &lt;/persistence-unit&gt;
&lt;/persistence&gt;
</pre>
<p>Określamy w&nbsp;nim nazwę jednostki utrwalającej, <a href="http://openejb.apache.org/3.0/jpa-concepts.html" target="_blank">typ transakcji</a>, dostawę jednostki oraz adres naszego źródła danych, musimy również wprowadzić informacje, które klasy będą używane podczas utrwalania (więc pewne dane się zdublują z&nbsp;plikiem hibernate.cfg.xml). Powyższy plik możemy umieścić w&nbsp;tym samym miejscu co plik <strong>hibernate.cfg.xml</strong>, tak by był dostępny dla JVM podczas ładowania aplikacji.</p>
<p>Gdy mamy już skonfigurowanego hibernate-a oraz jednostę utrwalającą, pora zintegrować je z&nbsp;naszą aplikacja, polegać to będzie na utworzeniu szeregu <strong>beanów</strong> odpowiedzialnych za obsługę żądań do bazy danych. Konfiguracja ta została zapisana w&nbsp;pliku <strong>web-data.xml</strong> i&nbsp;ma zawartość:</p>
<pre class="brush: xml;">
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
 xmlns:tx=&quot;http://www.springframework.org/schema/tx&quot; xmlns:mvc=&quot;http://www.springframework.org/schema/mvc&quot;
 xmlns:jee=&quot;http://www.springframework.org/schema/jee&quot;
 xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-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&quot;&gt;

 &lt;jee:jndi-lookup id=&quot;dataSource&quot; jndi-name=&quot;java:comp/env/bookstore&quot;
 cache=&quot;true&quot; resource-ref=&quot;true&quot; lookup-on-startup=&quot;false&quot;
 proxy-interface=&quot;javax.sql.DataSource&quot; /&gt;

&lt;bean id=&quot;entityManagerFactory&quot;
 class=&quot;org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean&quot;&gt;
 &lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&gt;
 &lt;/bean&gt;

 &lt;bean id=&quot;sessionFactory&quot;
 class=&quot;org.springframework.orm.hibernate3.LocalSessionFactoryBean&quot;&gt;
 &lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&gt;
 &lt;property name=&quot;configurationClass&quot; value=&quot;org.hibernate.cfg.AnnotationConfiguration&quot;/&gt;
 &lt;property name=&quot;configLocation&quot; value=&quot;classpath:META-INF/hibernate.cfg.xml&quot; /&gt;
 &lt;/bean&gt;

 &lt;bean id=&quot;transactionManager&quot;
 class=&quot;org.springframework.orm.jpa.JpaTransactionManager&quot;&gt;
 &lt;property name=&quot;sessionFactory&quot; ref=&quot;sessionFactory&quot; /&gt;
 &lt;/bean&gt;

 &lt;bean id=&quot;templateManager&quot;
class=&quot;org.springframework.orm.hibernate3.HibernateTemplate&quot;&gt;
 &lt;property name=&quot;sessionFactory&quot; ref=&quot;sessionFactory&quot; /&gt;
 &lt;/bean&gt;

&lt;tx:annotation-driven transaction-manager=&quot;transactionManager&quot; /&gt;

&lt;/beans&gt;
</pre>
<p>Konfiguracja zawiera:</p>
<p><strong>dataSource:<br />
</strong>Wyszukuje nasze połączenie (skonfigurowane w&nbsp;serwerze) i&nbsp;binduje je do nazwy dataSource</p>
<p><strong>entityManager: </strong> manager encji</p>
<p><strong>sessionFactory: </strong>można powiedzieć, że sesja jest tożsama (oznacza to  samo) co połączenie z&nbsp;bazą danych. Dzięki podaniu klasy<strong> AnnotationConfiguration</strong> do parametru <em>configurationClass</em> mogę używać adnotacji do konfigurowania encji zamiast pisać pliki <strong>*.hba.xml.</strong> Parametr <strong>configLocation</strong> wskazuje miejsce gdzie znajduje się plik konfiguracyjny hibernate-a.</p>
<p><strong>transactionManager: </strong> manager transakcji (raczej jasne)</p>
<p><strong>templateManager: </strong>posiada szereg metod upraszczających obsługę ORM (wyszukiwanie, zapisywanie, aktualizacja, kasowanie etc.), do działania wymaga sesji podawanej w&nbsp;parametrze <strong>sessionFactory.</strong></p>
<p><strong>tx:annotation-driven: </strong>dzięki temu zapisowi możemy używać dodatkowych adnotacji (np. @Transactional)</p>
<p>Należy pamiętać by dopisać ścieżkę do konfiguracji  (/WEB-INF/web-data.xml) w&nbsp;pliku <strong>web.xml</strong> (w miejscu konfiguracji kontekstu).</p>
<p>Tak skonfigurowany spring, będzie lączył się przy starcie ze zdefiniowanym serwerem bazy danych, udostępnia również szereg obiektów pomagających w&nbsp;dostępie do bazy. Jeśli połączenie działa poprawnie (czyt. przy starcie nie wyskakuje żadne wyjątek) bierzemy się do dalszej pracy.</p>
<h2>Obsługa wiadomości / tłumaczenia</h2>
<p>Jestem zwolennikiem odcinania treści od formy, nie lubię gdy w&nbsp;kodzie strony widzę treści takie jak, nazwy pól, komunikaty błędów, czy też nagłówki. Takie podejście sprawia problem, gdy będziemy musieli zmienić tekst znajdujący się w&nbsp;wielu elementach aplikacji czy też co ważniejsze udostępnić aplikację w&nbsp;wielu językach.  Na szczęście istnieje proste rozwiązanie jakim jest mechanizm wiadomości. Mechanizm ten składa się z&nbsp;3 elementów: konfiguracji wskazującej gdzie znajdują się teksty, pliku z&nbsp;tekstami oraz odpowiednich wstawek w&nbsp;kodzie aplikacji które wskazują jaka treść ma zostać umieszczona w&nbsp;danym miejscu.</p>
<p>Konfiguracja mechanizmu jest niezwykle prosta, polega na zdefiniowaniu nowego obiektu i&nbsp;przekazaniu mu listy plików w&nbsp;której znajdują się nasze wiadomości (poniżej):</p>
<pre class="brush: xml;">

&lt;bean id=&quot;messageSource&quot;
class=&quot;org.springframework.context.support.ResourceBundleMessageSource&quot;&gt;
 &lt;property name=&quot;basenames&quot;&gt;
 &lt;list&gt;
 &lt;value&gt;/WEB-INF/messages/main&lt;/value&gt;
 &lt;/list&gt;
 &lt;/property&gt;
 &lt;/bean&gt;
</pre>
<p>Pewną nieścisłością jest fakt, że obiekt ten będzie przeszukiwał katalog <strong>/WEB-INF/messages/ </strong>w poszukiwaniu pliku <strong>main.properties</strong>, a&nbsp;nie jak można by sadzić pliku <strong>main</strong>, o&nbsp;czym trzeba pamiętać.</p>
<p>Nasz plik z&nbsp;wiadomościami ma prostą budowę, składa się z&nbsp;zestawu   <strong>klucz = treść,</strong> gdzie klucz jest unikalnym identyfikatorem nadawanym naszej treści, będzie on również używany w&nbsp;kodzie strony, gdzie należy wstawiać tagi w&nbsp;postaci <strong>&lt;tag:message code=&#8221;IDENTYFIKATOR&#8221; /&gt;</strong> który zostanie zastąpiony odpowiednią treścią. Proste w&nbsp;wygodne.</p>
<h2><strong>Dodawanie administratorów</strong></h2>
<p>Pierwszym zadaniem z&nbsp;jakim się zmierzymy jest dodawanie administratorów (w następnej części tutoriala zabezpieczymy nasz system, więc potrzebujemy konta by móc się zalogować), gdzie konta powinny spełniać wymagania:</p>
<ol>
<li>hasło musi mieć przynajmniej 8 znaków, ale nie więcej jak 20 znaków</li>
<li>hasła zaszyfrowane zostaną algorytmem SHA-2 (odmiana sha256)</li>
<li>wykorzystana zostanie sól w&nbsp;postaci identyfikatora użytkownika (identyfikator nie będzie wystawiany na widok publiczny)</li>
<li>w bazie danych przechowywani będą użytkownicy o&nbsp;różnych poziomach dostępu, do panelu administracyjnego dostęp będą mieli tylko i&nbsp;wyłącznie Ci użytkownicy, którzy posiadają poziom <strong>ROLE_ADMIN</strong></li>
</ol>
<p>Z powyższych krótkich wymagań można łatwo wywnioskować, że potrzebujemy obiektu który będzie szyfrować ciągi znaków, oraz jednego do tworzenia soli. Obiekty te skonfigurowane zostaną w&nbsp;kolejnym pliku xml zapisanym pod nazwą <strong>security.xml</strong>, z&nbsp;racji, że są to obiekty wykorzystywane przy funkcjach bezpieczeństwa.<br />
Plik ten aktualnie prezentuje się jak poniżej:</p>
<pre class="brush: xml;">

&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
 xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
 xmlns:tx=&quot;http://www.springframework.org/schema/tx&quot; xmlns:mvc=&quot;http://www.springframework.org/schema/mvc&quot;
 xmlns:jee=&quot;http://www.springframework.org/schema/jee&quot;
 xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/jee

http://www.springframework.org/schema/jee/spring-jee-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&quot;&gt;

 &lt;bean id=&quot;passwordEncoder&quot; class=&quot;org.springframework.security.authentication.encoding.ShaPasswordEncoder&quot;&gt;
     &lt;constructor-arg value=&quot;256&quot;/&gt;
 &lt;/bean&gt;

 &lt;bean id=&quot;saltSource&quot; class=&quot;org.springframework.security.authentication.dao.ReflectionSaltSource&quot;&gt;
     &lt;property name=&quot;userPropertyToUse&quot; value=&quot;id&quot;/&gt;
 &lt;/bean&gt;

&lt;/beans&gt;
</pre>
<p>Diagram klas struktury przechowującej dane nt. administratorów wygląda następująco:</p>
<div id="attachment_801" class="wp-caption aligncenter" style="width: 310px"><a href="http://darekzon.com/wp-content/uploads/2010/05/adm_acc_acr_dia.png" rel="lightbox[736]"><img class="size-medium wp-image-801" title="Diagram klas - konta użytkowników" src="http://darekzon.com/wp-content/uploads/2010/05/adm_acc_acr_dia-300x113.png" alt="Diagram klas - konta użytkowników" width="300" height="113" /></a><p class="wp-caption-text">Diagram klas - konta użytkowników</p></div>
<p><a href="http://darekzon.com/wp-content/uploads/2010/04/adm_acc_acr_dia.png" rel="lightbox[736]"><br />
</a>Klasa administratora (na razie pusta) rozszerza klasę użytkownika która posiada login oraz hasło jako dane uwierzytelniające,<strong> </strong>dodatkowo użytkownik agreguje poziom dostępu użytkownika (z racji, że w&nbsp;tej samej tabeli przechowywani będą administratorzy, operatorzy oraz zwykli użytkownicy) który wydelegowany jest do oddzielnej klasy.</p>
<h3>Tworzymy Encje</h3>
<p>Powyższy diagram musimy przepisać na klasy encji, najprościej mówiąc encja to obiekt reprezentujący jeden rekord jednej tabeli, tak więc Encja <strong>Account</strong> będzie odzwierciedleniem strukturę tabeli <strong>account.</strong></p>
<p>Encje jakie utworzyliśmy podczas projektu powinny wyglądać tak:</p>
<p><strong>Administrator</strong><em> (pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec wpisu)</em>:</p>
<pre class="brush: java;">

@Table(name = &quot;administrator&quot;)
@Entity
public class Administrator extends Account { }
</pre>
<p><strong>Account</strong><em> (pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec </em><em>wpisu</em><em>):</em></p>
<pre class="brush: java;">

@Entity
@Table(name = &quot;account&quot;)
@Inheritance(strategy = InheritanceType.JOINED)
public class Account {

 @Id
 @GeneratedValue(generator = &quot;account_id&quot;, strategy = GenerationType.SEQUENCE)
 @SequenceGenerator(name = &quot;account_id&quot;, sequenceName = &quot;account_id_seq&quot;)
 Integer id;

 public Integer getId() {
 return id;
 }

 public void setId(Integer id) {
 this.id = id;
 }

 @Basic
 @NotNull
 @Size(min = 5, max = 20)
 String username;

 public String getUsername() {
 return username;
 }

 public void setUsername(String username) {
 this.username = username;
 }

 @Basic
 @Size(min = 8, max = 20)
 String password;

 public String getPassword() {
 return password;
 }

 public void setPassword(String password) {
 this.password = password;
 }

 @Transient
 public String repeatedPassword;

 public String getRepeatedPassword() {
 return repeatedPassword;
 }

 public void setRepeatedPassword(String repeatedPassword) {
 this.repeatedPassword = repeatedPassword;
 }

 @Basic
 @DateTimeFormat(iso = ISO.DATE_TIME)
 Date addDate = new Date();

 public Date getAddDate() {
 return addDate;
 }

 public void setAddDate(Date addDate) {
 this.addDate = addDate;
 }

 @OneToMany(cascade = CascadeType.ALL, mappedBy = &quot;account&quot;, fetch = FetchType.EAGER, targetEntity = AccountRole.class)
 List&lt;AccountRole&gt; accountRole = new ArrayList&lt;AccountRole&gt;();

 public List&lt;AccountRole&gt; getAccountRole() {
 return accountRole;
 }

 public void setAccountRole(List&lt;AccountRole&gt; accountRole) {
 for (AccountRole ar : accountRole) {
 this.addAccountRole(ar);
 }
 }

 public void addAccountRole(AccountRole accountRole) {
 if (!this.accountRole.contains(accountRole)) {
 accountRole.setAccount(this);
 this.accountRole.add(accountRole);
 }
 }
}
</pre>
<p><strong>AccountRole</strong><em> (pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec </em><em>wpisu</em><em>)</em><strong>:</strong></p>
<pre class="brush: java;">

@Entity
@Table(name = &quot;account_role&quot;)
public class AccountRole {

 public AccountRole() {
 this.setRole(&quot;ROLE_ANONYMOUS&quot;);
 }

 public AccountRole(String role) {
 this.setRole(role);
 }

 @Id
 @GeneratedValue(generator = &quot;role_id&quot;, strategy = GenerationType.SEQUENCE)
 @SequenceGenerator(name = &quot;role_id&quot;, sequenceName = &quot;account_role_id_seq&quot;, initialValue = 1)
 Integer roleId;

 public Integer getRoleId() {
 return roleId;
 }

 public void setRoleId(Integer roleId) {
 this.roleId = roleId;
 }

 @Basic
 String role;

 public String getRole() {
 return role;
 }

 public void setRole(String role) {
 this.role = role;
 }

 @ManyToOne(targetEntity = Account.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 @JoinColumn(name = &quot;accountId&quot;, nullable = true)
 Account account;

 public Account getAccount() {
 return account;
 }

 public void setAccount(Account account) {
 this.account = account;
 }

}
</pre>
<p><strong>Warto zwrócić uwagę na adnotacje:</strong></p>
<ol>
<li>@Entity &#8211; oznacza, że dana klasa jest klasą encyjną</li>
<li>@Table &#8211; mówi jaka tabela w&nbsp;bazie odpowiada naszej encji (jeśli ustawimy, hibernate automatycznie wyeksportuje naszą encje do danej tabeli)</li>
<li>@Inheritance &#8211; mówi hibernate-owi, że ewentualne zależności (poprzez dziedziczenie) powinny być zapisywane w&nbsp;osobnych tabelach (<strong>UWAGA!</strong> &#8211; domyślnie, hibernate łączy wszelkie zależności w&nbsp;jednej tabeli), mechanizm sam zadba o&nbsp;odpowiednie klucze obce.</li>
<li>@Id &#8211; oznacza wybrane pole jako identyfikator</li>
<li>@GeneratedValue &#8211; konfiguruje metodę generowania wartości dla pola, wykorzystywany w&nbsp;identyfikatorach (autoincrement)</li>
<li>@SequenceGenerator &#8211; konfiguruje generator sekwencji dla wybranego pola</li>
<li>@Basic &#8211; zwykłe pole</li>
<li>@Transistent &#8211; mówi aplikacji, że dane pole nie jest odzwierciedlone w&nbsp;bazie danych</li>
<li>@DateTimeFormat &#8211; ustala format daty, dla pola które datę będzie przechowywać</li>
<li>@ManyToOne &#8211; tworzy relacje wiele-do-jednego</li>
<li>@OneToMany &#8211; tworzy relacje jeden-do-wielu</li>
<li>@JoinColumn &#8211; ustawia kolumnę łączącą dwie tabele</li>
</ol>
<p>Ostatnie adnotacje posłużyły do skonfigurowania relacji <strong>Konto-&gt;Poziom dostępu</strong>, dzięki temu przy pobieraniu informacji o&nbsp;koncie, automatycznie dostaniemy listę poziomów dostępu jakie posiada użytkownik.</p>
<p>Drugą ważną rzeczą w&nbsp;powyższych klasach encji są adnotacje służące walidowaniu Dzięki nim nie musimy zaśmiecać kontrolerów dodatkowymi regułami sprawdzającymi, czy też konfigurować walidacji przez XML, reguły walidacji to kolejno:</p>
<ol>
<li>@NotNull &#8211; pole nie może być nullem</li>
<li>@Size &#8211; wielkość pola musi mieścić się w&nbsp;granicach <strong>min</strong> do <strong>max</strong> znaków</li>
</ol>
<p>Oczywiście, to nie jedyne walidatory jakie są dostępne, pełną listę podstawowych walidatorów znajdziecie w&nbsp;<a href="http://java.sun.com/javaee/6/docs/api/javax/validation/constraints/package-summary.html" target="_blank">dokumentacji</a>.</p>
<p>Dodawanie administratorów będzie zapisane w&nbsp;kontrolerze <strong>AdministratorController</strong>, na początek zaimplementujemy metodę która będzie wyświetlać formularz rejestracyjny.</p>
<p><strong>AdministratorController</strong><em> (pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec </em><em>wpisu</em><em>)</em><strong>:</strong></p>
<pre class="brush: java;">

@Controller
public class AdministratorController {

 @Autowired
 AccountService accountService;

 @RequestMapping(value = &quot;/administrator/add&quot;, method = RequestMethod.GET)
 public ModelAndView add() {
 ModelAndView mav = new ModelAndView(&quot;/administrator/add&quot;);
 mav.addObject(&quot;administrator&quot;, new Administrator());
 return mav;
 }

}
</pre>
<p>Co warto zauważyć?</p>
<ol>
<li><em>@Controler</em> &#8211; każdy kontroler oznaczony musi być adnotacją @Controler, dzięki czemu spring podczas skanowania pakietu dodaje go do listy</li>
<li><em>@Autowired </em><strong>- </strong>mówi Spring-owi aby poszukał obiektu o&nbsp;zadanym typie i&nbsp;automatycznie podpiął go do pola</li>
<li><em>@RequestMapping</em> &#8211; mówi springowi jakie żądanie ma być skierowane do danej metody, opcja <em>RequestType</em> wskazuje dodatkowo jaki typ żądania ma być tam skierowane,w tym przypadku zależy nam na żądaniu GET</li>
</ol>
<p>Powyższa metoda zwraca obiekt ModelAndView (standardowy obiekt zwracany przez większość metod) który przechowuje informacje na temat pliku widok oraz obiekt klasy Administrator, obiekt ten zbindujemy w&nbsp;widoku dzięki czemu wartości pól w&nbsp;formularzu zostaną przepisane do odpowiadających im wartości pól w&nbsp;obiekcie.<br />
Widok formularza prezentuje się następująco:</p>
<pre class="brush: xml;">

&lt;%@ taglib prefix=&quot;form&quot; uri=&quot;http://www.springframework.org/tags/form&quot; %&gt;
&lt;%@ taglib prefix=&quot;tag&quot; uri=&quot;http://www.springframework.org/tags&quot; %&gt;
&lt;div&gt;
 &lt;form:form commandName=&quot;administrator&quot;&gt;
 &lt;ol&gt;
 &lt;li&gt;
 &lt;form:label path=&quot;username&quot;&gt;&lt;tag:message code=&quot;administrator.username&quot; /&gt;&lt;/form:label&gt;
 &lt;form:input path=&quot;username&quot; /&gt;
 &lt;form:errors path=&quot;username&quot; /&gt;
 &lt;/li&gt;
 &lt;li&gt;
 &lt;form:label path=&quot;password&quot;&gt;&lt;tag:message code=&quot;administrator.password&quot; /&gt;&lt;/form:label&gt;
 &lt;form:password path=&quot;password&quot; /&gt;
 &lt;form:errors path=&quot;password&quot; /&gt;
 &lt;/li&gt;
 &lt;li&gt;
 &lt;form:label path=&quot;repeatedPassword&quot;&gt;&lt;tag:message code=&quot;administrator.repeatedPassword&quot; /&gt;&lt;/form:label&gt;
 &lt;form:password path=&quot;repeatedPassword&quot; /&gt;
 &lt;form:errors path=&quot;repeatedPassword&quot; /&gt;
 &lt;/li&gt;
 &lt;li&gt;
 &lt;input type=&quot;submit&quot; /&gt;
 &lt;/li&gt;
 &lt;/ol&gt;
 &lt;/form:form&gt;
&lt;/div&gt;
</pre>
<p>Gdzie:</p>
<ul>
<li>taglib &#8211; pozwala stosować rozszerzenia w&nbsp;JSP; <strong>form-</strong>generowanie formularzy, obsługa błedów, <strong>tag</strong>-wyświetlanie wiadomości o&nbsp;których wspomniałem wcześniej</li>
<li>commandName &#8211; to nazwa nadana naszemu obiektowi podczas przekazywania go z&nbsp;kontrolera do widoku,</li>
<li>input path &#8211; to pole w&nbsp;naszym obiekcie</li>
<li>errors &#8211; lista błędów dla danego pola (pojawia się po walidacji)</li>
</ul>
<p>Powyższy formularz prezentuje się następująco:</p>
<div id="attachment_802" class="wp-caption aligncenter" style="width: 310px"><a href="http://darekzon.com/wp-content/uploads/2010/05/BookStore.jpg" rel="lightbox[736]"><img class="size-medium wp-image-802" title="Formularz dodawania administratora" src="http://darekzon.com/wp-content/uploads/2010/05/BookStore-300x145.jpg" alt="Formularz dodawania administratora" width="300" height="145" /></a><p class="wp-caption-text">Formularz dodawania administratora</p></div>
<p>Po wciśnięciu wyślij, dane z&nbsp;formularza już pod postacią obiektu klasy <strong>Administrator</strong> przekazywane są do kolejnej metody która sprawdza poprawność danych, i&nbsp;jeśli wszystko jest jak trzeba zapisuje je. Metoda ta wygląda następująco <em>(pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec posta)</em>:</p>
<pre class="brush: java;">

@RequestMapping(value = &quot;/administrator/add&quot;, method = RequestMethod.POST)
 public ModelAndView add(@Valid Administrator admin, BindingResult result) {
 ModelAndView mav = new ModelAndView(&quot;administrator/add&quot;);
 if (!admin.getPassword().equals(admin.getRepeatedPassword())) {
 result.addError(new FieldError(&quot;administrator&quot;, &quot;repeatedPassword&quot;,
 &quot;notEqual&quot;));
 }
 if (result.hasErrors()) {
 mav.addObject(&quot;administrator&quot;, admin);
 return mav;
 }
 List&lt;AccountRole&gt; ar = new ArrayList&lt;AccountRole&gt;();
 ar.add(new AccountRole(&quot;ROLE_ADMIN&quot;));
 try {
 accountService.registerAccount(admin, ar);
 } catch (UserExistsException e) {
 result.reject(&quot;user.exists&quot;);
 mav.addObject(&quot;administrator&quot;, admin);
 return mav;
 }
 mav.setViewName(&quot;redirect:/administrator.html&quot;);
 return mav;
 }
</pre>
<p>Powyższa metoda przyjmuje dwa argumenty, pierwszym jest nasz obiekt <strong>Administrator</strong> który zawiera dane z&nbsp;formularza, oraz obiekt <strong>BindingResult</strong> który przechowuje informacje na temat ewentualnych błędów które wystąpiły podczas sprawdzania poprawności (zgodnie z&nbsp;adnotacjami w&nbsp;klasach encyjnych). Aby Spring wiedział, że dany obiekt wymaga sprawdzenia poprawności danych należy oznaczyć go adnotacją <strong>@Valid, </strong>dzięki temu, spring automatycznie sprawdzi obiekt, a&nbsp;błędy zapisze w&nbsp;obiekcie BindingResult.</p>
<p>Ponieważ nie istnieje adnotacja walidacyjna (przynajmniej w&nbsp;podstawowym zestawie) która sprawdza czy dwa pola są identyczne musiałem zaprogramować dodatkowe sprawdzanie już w&nbsp;kontrolerze. Gdy akcja wykryje, że hasło oraz jego powtórzona wartość nie są identyczne, doda do obiektu <strong>BindingResult</strong> błąd dla pola <strong>repeatedPassword</strong> przez co formularz nie zostanie zapisany w&nbsp;bazie, a&nbsp;zamiast tego zostanie ponownie wyświetlony z&nbsp;zaznaczonym błędem, jak przykład poniżej:</p>
<div id="attachment_803" class="wp-caption aligncenter" style="width: 310px"><a href="http://darekzon.com/wp-content/uploads/2010/05/BookStore-1.jpg" rel="lightbox[736]"><img class="size-medium wp-image-803" title="Formularz z&nbsp;błędnymi polami" src="http://darekzon.com/wp-content/uploads/2010/05/BookStore-1-300x121.jpg" alt="Formularz z&nbsp;błędnymi polami" width="300" height="121" /></a><p class="wp-caption-text">Formularz z&nbsp;błędnymi polami</p></div>
<p>Jeśli natomiast wszystkie nasze pola zostaną wypełnione poprawnie nastąpi próba zapisania formularza <strong>accountService.registerAccount</strong>, a&nbsp;po poprawnym zapisaniu zostaniemy przekierowani (dyrektywa <strong>&#8220;redirect:/administrator&#8221;</strong>) do strony <strong>/administrator.html.</strong> Akcja rejestracji nowego administratora składa się z&nbsp;2 plików (nie wliczając interfejsów które te pliki implementują.</p>
<p>Pierwszy plik to <strong>AccountServiceImpl</strong> który jest w&nbsp;tym wypadku głównym plikiem<em> (pełna zawartość pliku w&nbsp;repozytorium &#8211; zobacz koniec posta)</em>:</p>
<pre class="brush: java;">

@Transactional
@Repository
public class AccountServiceImpl implements AccountService {
 @Autowired
 AccountDao accountDao;

 @Autowired
 PasswordEncoder passwordEncoder;

 @Autowired
 SaltSource saltSource;

 @PersistenceContext
 EntityManager entityManager;

 @Override
 public void registerAccount(Account account,List&lt;AccountRole&gt; ar) throws UserExistsException {
 try{
 accountDao.findUsername(account.getUsername());
 throw new UserExistsException();
 }catch(UserNotFoundException une){
 entityManager.persist(account);
 account.setPassword(passwordEncoder.encodePassword(account.getPassword(), saltSource));
 for(AccountRole arole : ar){
 account.addAccountRole(arole);
 }
 entityManager.flush();
 }

 }

}
</pre>
<p>Nasza klasa oznaczona została dwoma adnotacjami, @Transactional, która mówi że, wszystkie metody w&nbsp;niej zaimplementowane objęte są transakcją, oraz @Repository które pozwala nam na pobranie managera encji poprzez adnotację @PersistenceContext.</p>
<p>Aby nasza metoda działała poprawnie musimy dostarczyć jej obiekt <strong>accountDao</strong> który posłuży do sprawdzenia czy dany użytkownik już istnieje, <strong>manager encji</strong> który zapisze nasz obiekt w&nbsp;bacie, a&nbsp;także obiekty <strong>passwordEncoder</strong> oraz <strong>saltSource</strong> służące szyfrowaniu hasła.</p>
<p>Po wywołaniu metody obiekt <strong>accountDao</strong> znajduje użytkownika o&nbsp;podanej nazwie użytkownika i&nbsp;jeśli go nie znajdzie wyrzuca wyjątek <strong>UserNotFoundException</strong> i&nbsp;gdy ten wyjątek wystąpi możemy zapisywać użytkownika do bazy. Nasz administrator zapisywany jest metodą <strong>persist</strong> z&nbsp;obiektu <strong>entityManager</strong>. Dzięki tej metodzie nasza encja zostanie tymczasowo związana z&nbsp;rekordem w&nbsp;bazie danych co oznacza, że wszelkie modyfikacje administratora będą automatyczne odzwierciedlane w&nbsp;bazie danych (więcej o&nbsp;cyklu życia encji w&nbsp;<a href="http://openjpa.apache.org/builds/1.0.2/apache-openjpa-1.0.2/docs/manual/jpa_overview_em_lifecycle.html" target="_blank">dokumentacji</a>). Gdy nasz użytkownik zostanie zapisany musimy zaktualizować mu hasło, dzieje się tak, gdyż hasło szyfrowane algorytmem sha256 z&nbsp;dodatkową solą w&nbsp;postaci identyfikatora użytkownika, który nadawany jest dopiero po zapisaniu go do bazy danych.</p>
<p>Po aktualizacji hasła przypisujemy naszemu użytkownikowi odpowiednie poziomy dostępu (może mieć ich więcej jak jeden) poprzez dodanie obiektów <strong>AccountRole</strong> do obiektu <strong>Administrator </strong>(dane zostają zapisane dzięki wcześniejszemu skonfigurowaniu powiązań @ManyToOne i&nbsp;@OneToMany).</p>
<p>Ciekawie wygląda również plik <strong>AccountDaoImpl</strong> który wyszukuje użytkowników po zadanym loginie<em> (pełna zawartość  pliku w&nbsp;repozytorium &#8211; zobacz koniec posta)</em>:</p>
<pre class="brush: java;">

 public class AccountDaoImpl implements AccountDao {

 @Autowired
 HibernateTemplate template;

 @Autowired
 SessionFactory session;

 public Account findUsername(String username) throws  UserNotFoundException {
 DetachedCriteria dc = DetachedCriteria.forClass(Account.class);
 dc.add(Property.forName(&quot;username&quot;).eq(username));
 List users = template.findByCriteria(dc, 0, 1);

 if (users.size() &gt; 0) {
 return (Account) users.get(0);
 }

 throw new UserNotFoundException();
 }

 }
</pre>
<p>W ciele metody <strong>findUsername</strong> zastosowane zostało wyszukiwanie po kryteriach, <strong>CriteriaApi</strong> daje ogromne możliwości w&nbsp;dynamicznym budowaniu zapytań do bazy, w&nbsp;naszym przypadku wskazaliśmy, że dane zapytanie dotyczyć będzie klasy <strong>Account</strong> (a tym samym tabeli odzwierciedlającej tą klasę), oraz dodaliśmy właściwość pola <strong>username</strong> ustalając że pole to powinno być równe wartości podanej w&nbsp;argumencie<em>.</em></p>
<h4>Wyświetlamy użytkowników</h4>
<p>Jeśli nasi administratorzy zostali zapisani do bazy, warto by ich wyświetlić w&nbsp;liście, w&nbsp;tym celu stworzymy metodę obsługującą żądanie <strong>/administrator.html</strong>. Metoda ta znajduje się w&nbsp;pliku <strong>AdministratorController</strong> i&nbsp;wygląda następująco:</p>
<pre class="brush: java;">

@RequestMapping(value = &quot;/administrator&quot;)
 public ModelAndView index() {
 ModelAndView mav = new ModelAndView(&quot;/administrator/index&quot;);
 List&lt;String&gt; roles = new ArrayList&lt;String&gt;();
 roles.add(&quot;ROLE_ADMIN&quot;);
 List&lt;Account&gt; acc = accountService.listAccounts(roles);
 mav.addObject(&quot;accounts&quot;, acc);
 return mav;
 }
</pre>
<p>Metoda listująca pobiera z&nbsp;bazy wszystkich użytkowników o&nbsp;zadanym poziomie dostępu (<strong>AccountRole</strong>) po czym przekazujemy listę do widoku. Metoda wyszukująca użytkowników zaimplementowana jest w&nbsp;dwóch plikach, pierwszy <strong>AccountServiceImpl</strong> poniżej:</p>
<pre class="brush: java;">

@Override
 @Transactional(readOnly=true)
 public List&lt;Account&gt; listAccounts(List&lt;String&gt; roles) {
 return accountDao.listAccounts(roles);
 }
</pre>
<p>Ma jedynie za zadanie wywołać metodę wyszukującą z&nbsp;obiektu <strong>AccountDaoImpl</strong>, warto wyjaśnić adnotację @Transactional, ponieważ wszystkie metody w&nbsp;klasie <strong>AccountServiceImpl</strong> objęte są transakcją warto przy metodach które nie zapisują danych zaznaczyć, że transakcja ma być traktowana jako tylko do odczytu, dzięki temu zyskujemy na wydajności.</p>
<p>Metoda wywołana przez powyższą metodę ma postać:</p>
<p><span style="text-decoration: line-through;">@Override<br />
public List listAccounts(List roles) {<br />
Criteria criteria = session.openSession().createCriteria(Account.class);<br />
criteria.addOrder(Order.asc(&#8220;username&#8221;));<br />
criteria.createCriteria(&#8220;accountRole&#8221;).add(Restrictions.in(&#8220;role&#8221;,roles));<br />
return criteria.list();<br />
}</span></p>
<p><span style="text-decoration: line-through;">Również tutaj zastosowanie znalazły kryteria, choć w&nbsp;troszkę inny sposób. W&nbsp;tym przypadku wyszukujemy danych dla klasy <strong>Account</strong> sortując je (criteria.addOrder) według nazwy użytkownika, przy czym wszystkie zwracane rekordy powinny posiadać powiązany rekord z&nbsp;tabeli reprezentowanej przez obiekt accountRole który pole <strong>role</strong> ma zadaną wartość (tu <em>ROLE_ADMIN)<strong>. </strong></em>Ponieważ do wyszukania poziomów dostępu musimy złączyć dwie tabele robimy to poprzez stworzenie nowych cryteriów &#8220;na obiekcie&#8221; już aktywnych kryteriów.</span></p>
<p>UPDATE 1</p>
<p>W komentarzach zauważyliście, że w&nbsp;aplikacji mieszam JPA z&nbsp;hibernatem, aby to poprawić stworzyłem nową metodę z&nbsp;wykorzystaniem JPA QL:</p>
<pre class="brush: java;">

@Override
 public Collection&lt;Account&gt; listAccounts(Collection&lt;AccountRole&gt; roles){
 List&lt;String&gt; c = new ArrayList&lt;String&gt;(roles.size());
 for(AccountRole in : roles){
 c.add(in.getRole());
 }
 List&lt;Account&gt; accounts = entityManager.createQuery(&quot;SELECT a&nbsp;FROM Account a&nbsp;JOIN a.accountRole r WHERE r.role IN(?1)&quot;,Account.class).setParameter(1,c).getResultList();
 return accounts;
 }
</pre>
<p>Powyższa metoda przyjmuje jako argument kolekcję ról do jakich muszą należeć konta które pobieramy. Kolekcję obiektów musimy przekrztałcić na kolekcję prymitywów (w naszym wypadku ciągów znaków &#8211; STRING).<br />
Następnie przy pomocy managera encji (entityManager) tworzymy zapytanie (createQuery) które przyjmuje tylko jeden parametr przekazywany poprzez setParameter.</p>
<p>Gdy znajdziemy wszystkich użytkowników przekazujemy ich listę do widoku i&nbsp;generujemy:</p>
<pre class="brush: xml;">

&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jstl/core_rt&quot; %&gt;

&lt;c:choose&gt;
 &lt;c:when test=&quot;${not empty accounts}&quot;&gt;
 &lt;c:forEach items=&quot;${accounts}&quot; var=&quot;account&quot; varStatus=&quot;status&quot;&gt;
 ${status.index} ${account.username}
 &lt;/c:forEach&gt;
 &lt;/c:when&gt;
 &lt;c:otherwise&gt;
 &lt;tag:message code=&quot;list.no-entry&quot; /&gt;
 &lt;/c:otherwise&gt;
&lt;/c:choose&gt;
</pre>
<h2>Co dalej</h2>
<p>W kolejnej części tutoriala postaramy się zabezpieczyć nasz panel administracyjny poprzez zastosowanie SpringSecurity, ponieważ w&nbsp;tej chwili panel administracyjny wygląda <strong>biednie</strong>, wykorzystamy sitemesh, jsp oraz html by poprawić jego wygląd. A&nbsp;jeśli zostanie trochę miejsca i&nbsp;czasu zajmiemy się&#8230;. (<em>może niespodzianka)</em></p>
<p><em>PS. Zauważyłem, że ta część tutoriala zajęła mi dużo czasu, postanowiłem rozbić go na mniejsze ale częściej występujące wpisy.<br />
</em></p>
<h2>Jak pobrać projekt</h2>
<blockquote><p>Projekt został umieszczony na serwerach <a href="http://kenai.com/" target="_blank">Kenai.com</a>. Adres bezpośredni do projektu: <a href="http://kenai.com/projects/summer-bookstore" target="_blank">http://kenai.com/projects/summer-bookstore</a>.<br />
Dodatkowo zostało uruchomione repozytorium <strong>GIT</strong> dla wszystkich chętnych i&nbsp;dostępny jest pod adresem: <a href="git://kenai.com/summer-bookstore~books0re-source " target="_blank">git://kenai.com/summer-bookstore~books0re-source</a></p></blockquote>
<hr />
<ol>
<li> Gdzie TOMCAT_HOME jest katalogiem głównym tomcata</li>
</ol>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+2+%E2%80%93+baza+danych%2C+walidacja%2C+wiadomo%C5%9Bci%2C+encje%2C+hibernate" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;t=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+2+%E2%80%93+baza+danych%2C+walidacja%2C+wiadomo%C5%9Bci%2C+encje%2C+hibernate" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/05/spring-framework-3-0-tutorial-–-cz-2-–-baza-danych-walidacja-wiadomosci-encje-hibernate/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;n=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+2+%E2%80%93+baza+danych%2C+walidacja%2C+wiadomo%C5%9Bci%2C+encje%2C+hibernate&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+2+%E2%80%93+baza+danych%2C+walidacja%2C+wiadomo%C5%9Bci%2C+encje%2C+hibernate" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate&amp;title=Spring+Framework+3.0+Tutorial+%E2%80%93+cz+2+%E2%80%93+baza+danych%2C+walidacja%2C+wiadomo%C5%9Bci%2C+encje%2C+hibernate&amp;description=W%20tej%20cz%C4%99%C5%9Bci%20tutorialu%20skupimy%20si%C4%99%20na%20skonfigurowaniu%20po%C5%82%C4%85czenia%20z%20baz%C4%85%20danych%2C%20pod%C5%82%C4%85czeniu%20frameworka%20hibernate%20do%20naszej%20aplikacji%20oraz%20zobaczymy%20jak%20tworzy%C4%87%20encje%20i%20jak%20sprawdza%C4%87%20poprawno%C5%9B%C4%87%20danych%20przed%20ich%20zapisem%20%28walidacja%29.%0D%0APrzygotowanie%20do%20pracy%0D%0AW%20poprzedniej%20cz%C4%99%C5%9Bci%20przygotow" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/T7g-dRHzIMMYBxl1jqQZQf4Fh4o/0/da"><img src="http://feedads.g.doubleclick.net/~a/T7g-dRHzIMMYBxl1jqQZQf4Fh4o/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/T7g-dRHzIMMYBxl1jqQZQf4Fh4o/1/da"><img src="http://feedads.g.doubleclick.net/~a/T7g-dRHzIMMYBxl1jqQZQf4Fh4o/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/4aMeKcaTXqM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/05/spring-framework-3-0-tutorial-%e2%80%93-cz-2-%e2%80%93-baza-danych-walidacja-wiadomosci-encje-hibernate</feedburner:origLink></item>
		<item>
		<title>Spring Framework 3.0 Tutorial – cz 1 – przygotowanie projektu, witaj świecie</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/jvHG8BC1dZA/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie</link>
		<comments>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie#comments</comments>
		<pubDate>Tue, 13 Apr 2010 20:16:17 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[sitemesh]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=691</guid>
		<description><![CDATA[Zanim przystąpimy do tworzenia projektu warto odpowiednio przygotować sobie zaplecze techniczne. Z&#160;racji, że w&#160;eclipse pisze znaczna część firm (przynajmniej polskich), a&#160;ja jeszcze z&#160;niego nie korzystałem w&#160;tego typu projektach postanowiłem, że to będzie dobry moment by się z&#160;nim zmierzyć. Eclipse wyposażony zostanie dodatkowo we wtyczkę m2Eclipse która pomoże mi w&#160;zarządzaniu maven-em. Aplikacja uruchomiona zostanie na kontenerze [...]]]></description>
			<content:encoded><![CDATA[<p>Zanim przystąpimy do tworzenia projektu warto odpowiednio przygotować sobie zaplecze techniczne. Z&nbsp;racji, że w&nbsp;eclipse pisze znaczna część firm (przynajmniej polskich), a&nbsp;ja jeszcze z&nbsp;niego nie korzystałem w&nbsp;tego typu projektach postanowiłem, że to będzie dobry moment by się z&nbsp;nim zmierzyć.<br />
Eclipse wyposażony zostanie dodatkowo we wtyczkę m2Eclipse która pomoże mi w&nbsp;zarządzaniu maven-em. Aplikacja uruchomiona zostanie na kontenerze aplikacji Tomcat, a&nbsp;dane przechowam w&nbsp;bazie PostreSQL. Z&nbsp;racji, że źródła umieszczane będą w&nbsp;zewnętrznym repozytorium opartym o&nbsp;GIT potrzebny jest też ten właśnie program, ja preferuję korzystać z&nbsp;gita poprzez konsolę, oczywiście jeśli ktoś woli można doinstalować odpowiednią wtyczkę bądź nakładkę graficzną.</p>
<p>Co przyda się przy tworzeniu:</p>
<ul>
<li><a href="http://www.eclipse.org/" target="_blank">Eclipse</a></li>
<li><a href="http://maven.apache.org/" target="_blank">maven2</a> i&nbsp;plugin <a href="http://m2eclipse.sonatype.org/" target="_blank">m2Eclipse</a></li>
<li><span style="color: #888888;"><span style="color: #000000;"><a href="http://tomcat.apache.org/tomcat-6.0-doc/index.html" target="_blank">Tomcat 6</a></span></span></li>
<li><a href="http://www.postgresql.org/" target="_blank">PostgreSQL</a></li>
<li><a href="http://git-scm.com/" target="_blank">GIT</a></li>
<li><a href="http://hudson-ci.org/" target="_blank">Hudson</a> <span style="color: #888888;">- bo czemu nie<span id="more-691"></span></span></li>
</ul>
<h2>Podstawowe założenia</h2>
<p>Aplikacja składać się będzie z&nbsp;dwóch modułów, panelu administracyjnego dostępnego tylko i&nbsp;wyłącznie dla użytkowników z&nbsp;poziomem dostępu <strong>ADMIN</strong> 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&nbsp;poziomem dostępu <strong>CLIENT</strong>). Podział taki można wykonać na dwa sposoby, pierwszym jest stworzenie jednego projektu w&nbsp;którym dokonamy logicznego podziału widoków jak i&nbsp;kontrolerów na panel administracyjny oraz strefę otwartą, spring security dodatkowo zabezpieczy wejście. Wyniki składane będą przez <strong>sitemesh</strong> 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&nbsp;projekcie(o ile nie jest duży), wszystko mamy w&nbsp;jednym miejscu dzięki czemu nie trzeba przechodzić między projektami i&nbsp;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&nbsp;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&nbsp;jednym projekcie co z&nbsp;początku może wydawać się plusem w&nbsp;większych projektach staje się zmorą, gdyż większa ilość plików powoduje utrudnienia w&nbsp;odszukaniu tego który chcemy zmodyfikować (wiem, przeżyłem to na własnej skórze).</p>
<p>Drugim rozwiązaniem jest stworzenie osobnych projektów dla panelu administracyjnego oraz części klienckiej. Dzięki takiemu rozwiązaniu zachowujemy pewien ład i&nbsp;porządek w&nbsp;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&nbsp;obiektami bazy danych) trzymane są w&nbsp;projekcie który dołączany jest jako biblioteka. Mój wybór padł właśnie na tą metodę.</p>
<p>Podsumowując, utworzone zostaną 3 projekty: bookstore, bookstore-admin oraz bookstore-lib.</p>
<h2>Zaczynamy</h2>
<p>Projekt zaczniemy od stworzenia prostej strony a&#8217;la Witaj Świecie!. Aby zacząć całą zabawę otwieramy Eclipse i&nbsp;tworzymy nowy projekt typu &#8220;<strong>Dynamic Web Project</strong>&#8221; (File -&gt; New -&gt; Project&#8230; -&gt; Web -&gt; Dynamic Web Project). Następnie wpisujemy nazwę projektu i&nbsp;klikamy <strong>finish</strong>.<br />
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&nbsp;wybrać odpowiednio <strong>Maven</strong> -&gt;  <strong>Enable Dependency Managment</strong>. Plugin doda do naszego projektu plik <strong>pom.xml</strong>, który zawiera wszelkie informacje potrzebne dla maven-a. W&nbsp;strukturze projektu możemy zauważyć folder <strong>WebContent</strong> 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 <strong>war </strong>(co będziecie mogli zobaczyć po pobraniu projektu).</p>
<div id="attachment_695" class="wp-caption aligncenter" style="width: 227px"><a href="http://darekzon.com/wp-content/uploads/2010/04/Java-EE-bookstore_pom.xml-Eclipse-_Users_darek_Projects-3.jpg" rel="lightbox[691]"><img class="size-full wp-image-695" title="Struktura projektu z&nbsp;uruchomioną opcją Dependency Managment" src="http://darekzon.com/wp-content/uploads/2010/04/Java-EE-bookstore_pom.xml-Eclipse-_Users_darek_Projects-3.jpg" alt="" width="217" height="150" /></a><p class="wp-caption-text">Struktura projektu z&nbsp;uruchomioną opcją Dependency Managment</p></div>
<p style="text-align: center;">
<h2>Dodawanie zależności</h2>
<p>Pierwszą rzeczą jaką robię w&nbsp;nowo utworzonym projekcie jest dodanie podstawowych zależności. Z&nbsp;mojej strony są to takie biblioteki jak sitemesh 3 (UWAGA! &#8211; wydanie alpha, mam nadzieję, że działa), spring-web, spring-context, czy też spring-webmvc; czyli wszystko co potrzebne na dobry początek.<br />
Na koniec dodaję biblioteki JUnit oraz Mockito które posłużą do testowania aplikacji. Ponieważ biblioteki te nie będą nam potrzebne w&nbsp;działającej aplikacji, warto zaznaczyć w&nbsp;ich zakresie (ang. scope) opcje &#8220;<strong>test</strong>&#8221; dzięki czemu będą dołączane tylko podczas testów.</p>
<div id="attachment_696" class="wp-caption aligncenter" style="width: 310px"><a href="http://darekzon.com/wp-content/uploads/2010/04/Java-EE-bookstore_pom.xml-Eclipse-_Users_darek_Projects.jpg" rel="lightbox[691]"><img class="size-medium wp-image-696" title="&lt;Java EE&gt; - bookstore_pom.xml - Eclipse - _Users_darek_Projects" src="http://darekzon.com/wp-content/uploads/2010/04/Java-EE-bookstore_pom.xml-Eclipse-_Users_darek_Projects-300x213.jpg" alt="Zarządzanie zależnościami w&nbsp;Eclipse" width="300" height="213" /></a><p class="wp-caption-text">Zarządzanie zależnościami w&nbsp;Eclipse</p></div>
<h2>Konfiguracja</h2>
<p>Podstawowa konfiguracja obejmuje dwa pliki, najważniejszy <strong>web.xml</strong> oraz podstawowa konfiguracja spring-a i&nbsp;głównych servletów w&nbsp;pliku <strong>web-servlet.xml<br />
</strong>Plik <strong>web.xml</strong> jest jak najbardziej zwyczajny, podana jest lokalizacja pliku <strong>web-servlet.xml</strong>, skonfigurowane zostały listenery, a&nbsp;także servlety wraz z&nbsp;mapowaniem.</p>
<p><strong>web.xml:</strong></p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;web-app xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;

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

xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;

id=&quot;b0ok&quot; version=&quot;2.5&quot;&gt;

&lt;display-name&gt;bookstore&lt;/display-name&gt;

&lt;!--

wskazujemy lokalizacje plikow konfiguracyjnych

--&gt;

&lt;context-param&gt;

&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;

&lt;param-value&gt;

/WEB-INF/web-servlet.xml

&lt;/param-value&gt;

&lt;/context-param&gt;

&lt;listener&gt;

&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;

&lt;/listener&gt;

&lt;!--

tworzymy servlet ktory obslugiwac bedzie nasze zapytania

--&gt;

&lt;servlet&gt;

&lt;servlet-name&gt;web&lt;/servlet-name&gt;

&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;

&lt;/servlet&gt;

&lt;!--

ustalamy ze nasz servlet obslugiwac bedzie tylko zapytania konczace

sie rozszerzeniem *.html

--&gt;

&lt;servlet-mapping&gt;

&lt;servlet-name&gt;web&lt;/servlet-name&gt;

&lt;url-pattern&gt;*.html&lt;/url-pattern&gt;

&lt;/servlet-mapping&gt;

&lt;!--

ustalamy, jakie pliki beda ladowane gdy aplikacja dostanie zapyanie

&quot;/&quot; (np. http://example.com/)

--&gt;

&lt;welcome-file-list&gt;

&lt;welcome-file&gt;redirect.jsp&lt;/welcome-file&gt;

&lt;/welcome-file-list&gt;

&lt;/web-app&gt;
</pre>
<p>Dodatkowo wskazaliśmy plik który jest ładowany, gdy serwer otrzyma żądanie <strong>&#8220;</strong>/<strong>&#8221; </strong>(czyli strona startowa), w&nbsp;tym przypadku jest to załadowanie pliku redirect.jsp który przekieruje nas na stronę główną:</p>
<p><strong>redirect.jsp:</strong></p>
<pre class="brush: xml;">
&lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot;%&gt;

&lt;jsp:forward page=&quot;/index.html&quot; /&gt;
</pre>
<p><strong><span style="color: #808080;">Update 1:</span></strong><span style="color: #808080;"><br />
Jak trafnie zauważył </span><a href="http://chlebik.wordpress.com/" target="_blank"><span style="color: #808080;">Chlebik</span></a><span style="color: #808080;"> (zob. </span><a href="http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie#comment-319"><span style="color: #808080;">komentarz</span></a><span style="color: #808080;">), zamiast redirect.jsp możemy śmiało napisać &#8220;index.html&#8221; wtedy spring  wykona akcję przeznaczoną dla żądania &#8220;/&#8221;, 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ę. </span></p>
<p>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&nbsp;oparciu o&nbsp;<a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html" target="_blank">adnotacje</a>.<br />
<strong>web-servlet.xml</strong></p>
<pre class="brush: xml;">&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
xmlns:tx=&quot;http://www.springframework.org/schema/tx&quot; xmlns:mvc=&quot;http://www.springframework.org/schema/mvc&quot;
xsi:schemaLocation=&quot;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&quot;&gt;
&lt;context:component-scan base-package=&quot;com.darekzon.bookstore.controller&quot; /&gt;
&lt;context:annotation-config /&gt;
&lt;context:spring-configured /&gt;
&lt;bean
class=&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;&gt;
&lt;property name=&quot;prefix&quot; value=&quot;/views/&quot; /&gt;
&lt;property name=&quot;suffix&quot; value=&quot;.jsp&quot; /&gt;
&lt;/bean&gt;
&lt;/beans&gt;</pre>
<p>W sekcji &lt;<strong>context:component-scan</strong>&gt; wskazujemy, który pakiet ma być skanowany w&nbsp;poszukiwaniu kontrolerów (klas z&nbsp;adnotacją <em>@Controller</em>), 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 <strong>IndexController</strong> w&nbsp;naszym pakiecie to w&nbsp;pakiecie <em>com.darekzon.bookstore.controller</em> musimy umieścić <strong>Index2Controller</strong>.</p>
<p>Ach, no i&nbsp;ostatni blok wskazuje gdzie spring ma szukać plików jsp za pomocą których generować będzie wyniki.</p>
<h2>Pierwszy kontroler</h2>
<p>Aplikacja skonfigurowana, pierwszy kontroler będzie wyświetlał legendarny napis &#8220;Witaj świecie!&#8221;. Sam kontroler jest wyjątkowo prosty, posiada tylko jedną metodę, która zwraca obiekt typu &#8220;<strong>ModelAndView</strong>&#8221; przechowujący nazwę widoku do wyrenderowania. Kontroler zapisany jest w&nbsp;pliku IndexController.java (konwencja nazewnicza nie jest obowiązkowa) a&nbsp;jego zawartość przedstawia się jak poniżej:</p>
<pre class="brush: java;">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 = &quot;/index&quot;)
public ModelAndView index(){
ModelAndView mav = new ModelAndView(&quot;index/index&quot;);

return mav;
}

}</pre>
<p>Warto tutaj zwrócić uwagę na 3 rzeczy:</p>
<ol>
<li>Każdy kontroler powinien mieć adnotację <strong>@Controller</strong>, dzięki temu spring podczas skanowania pakietów (zob. konfigurację web-servlet.xml ↑)</li>
<li>Spring szuka metody którą ma wykonać na podstawie adnotacji <strong>@RequestMapping</strong>, w&nbsp;naszym przypadku czeka aż wywołamy żądanie &#8220;<strong>/index</strong>&#8220;,  warto dodać, że nie można dodać dwóch metod z&nbsp;tą samą wartością tej adnotacji (podczas uruchamiania wyskoczy wyjątek)</li>
<li>W tym przypadku zwracamy obiekt <strong>ModelAndView</strong> który zawiera nazwę pliku widoków który posłuży do renderowania wyników, plik widoku powinien znajdować się w&nbsp;folderze <strong>/views/index/index.jsp</strong>, czyli według ustawień w&nbsp;pliku <strong>web-servlet.xml</strong> oraz wartości zwracanej przez metodę.</li>
</ol>
<p>Kontroler gotowy, pora na widok który będzie renderowany, ponieważ będzie to wyświetlenie tekstu &#8220;<strong>Witaj świecie!</strong>&#8221; plik ten nie jest skomplikowany (kolejne na pewno wniosą coś nowego w&nbsp;tej kwestii), a&nbsp;jego zawartość przedstawia się następująco:</p>
<pre class="brush: xml;">&lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot;
pageEncoding=&quot;UTF-8&quot;%&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Index&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Witaj świecie!
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Tu tłumaczyć raczej nic nie trzeba, no może poza faktem pisania kodu całej strony w&nbsp;wyniku, ale o&nbsp;tym za chwilę.</p>
<h2>Sitemesh i&nbsp;konfiguracja szablonów</h2>
<p><a href="http://www.sitemesh.org/" target="_blank">Sitemesh</a> to ciekawy projekt dzięki któremu znacznie ułatwimy sobie zabawę z&nbsp;wyglądem strony, jego głównym zadaniem jest sklejanie widoków wygenerowanych przez &#8220;aplikację&#8221; z&nbsp;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).</p>
<p><div id="attachment_701" class="wp-caption aligncenter" style="width: 222px">&#8220;]<a href="http://darekzon.com/wp-content/uploads/2010/04/overview.gif" rel="lightbox[691]"><img class="size-medium wp-image-701" title="Sitemesh - sposób działania" src="http://darekzon.com/wp-content/uploads/2010/04/overview-212x300.gif" alt="Sitemesh - sposób działania" width="212" height="300" /></a><p class="wp-caption-text">Sposób działania Sitemesh-a[1</p></div>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ą <a href="http://www.opensymphony.com/sitemesh/" target="_blank">stroną projektu</a>.</p>
<p>Konfiguracja sitemesh-a może odbywać się na dwa sposoby:  klasa Java rozszerzająca klasę<strong> ConfigurableSiteMeshFilter</strong> lub plik XML, ponieważ z&nbsp;niewiadomych przyczyn konfiguracja przez XML mi nie działa skupię się na konfigurowaniu z&nbsp;wykorzystaniem JAVY.</p>
<p>W pliku web.xml musimy dodać filtry które będą go uruchamiać dla każdego żądania (przynajmniej w&nbsp;moim przypadku), wskazując przy tym naszą klasę konfigurującą, kod wygląda następująco:</p>
<pre class="brush: xml;">&lt;filter&gt;
&lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
&lt;filter-class&gt;com.darekzon.bookstore.filter.Sitemesh&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</pre>
<p>Zaś klasa <strong>Sitemesh </strong>konfigurująca ma postać:</p>
<pre class="brush: java;">public class Sitemeshextends ConfigurableSiteMeshFilter {
@Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath(&quot;/*&quot;, &quot;/views/layout/default.jsp&quot;);
}
}</pre>
<p>Działanie proste, przechwytujemy wyniki żądań wysłanych do aplikacji, i&nbsp;&#8220;kompilujemy&#8221; je z&nbsp;dekoratorem z&nbsp;pliku &#8220;<strong>/views/layout/default.jsp</strong>&#8221; (UWAGA! powinno podawać się pliki z&nbsp;rozszerzeniami innymi od tych zdefiniowanych w&nbsp;filtrach w&nbsp;pliku web.xml &#8211; w&nbsp;moim wypadku .html).</p>
<p>W tej chwili dekorator wygląda następująco:</p>
<pre class="brush: xml;">&lt;!doctype html&gt;
&lt;html lang=&quot;pl&quot; dir=&quot;ltr&quot;&gt;
&lt;head&gt;
&lt;title&gt;&lt;sitemesh:write property='title' /&gt; - BookStore&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;/resource/style/default.css&quot; /&gt;
&lt;sitemesh:write property='head' /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;sitemesh:write property='body' /&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Podczas renderowania sitemesh otwiera dekorator oraz plik wynikowy kontrolera oraz je scala (nie chodzi o&nbsp;język programowania), w&nbsp;miejscu tagu <strong>&lt;sitemesh:write property=&#8217;title&#8217; /&gt;</strong> wstawia wartość tagu &lt;title&gt; wyrenderowanego wyniku, w&nbsp;miejsce tagu<strong> &lt;sitemesh:write property=&#8217;head&#8217; /&gt;</strong> wartość tagu head (za wyjątkiem title), a&nbsp;tam gdzie pyta o&nbsp;<strong>&lt;sitemesh:write property=&#8217;body&#8217; /&gt;</strong>, wszystko co znajduje się w&nbsp;body. Proste, a&nbsp;co ważne wygodne.</p>
<h2>CDN&#8230;</h2>
<p>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&nbsp;Sitemesh.Tymczasem zapraszam do pozostawiania komentarzy, wszelkie postaram się wziąć pod uwagę.</p>
<p>Do zobaczenia wkrótce.</p>
<h2>Jak pobrać projekt</h2>
<blockquote><p>Projekt został umieszczony na serwerach <a href="http://kenai.com/" target="_blank">Kenai.com</a>. Adres bezpośredni do projektu: <a href="http://kenai.com/projects/summer-bookstore" target="_blank">http://kenai.com/projects/summer-bookstore</a>.<br />
Dodatkowo zostało uruchomione repozytorium <strong>GIT</strong> dla wszystkich chętnych i&nbsp;dostępny jest pod adresem: <a href="git://kenai.com/summer-bookstore~books0re-source " target="_blank">git://kenai.com/summer-bookstore~books0re-source</a></p></blockquote>
<hr /><sup>1.</sup> Diagram pobrany ze strony <a href="http://www.sitemesh.org/overview.html">http://www.sitemesh.org/overview.html</a></p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;title=Spring+Framework+3.0+Tutorial+-+cz+1+-+przygotowanie+projektu%2C+witaj+%C5%9Bwiecie" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;t=Spring+Framework+3.0+Tutorial+-+cz+1+-+przygotowanie+projektu%2C+witaj+%C5%9Bwiecie" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;n=Spring+Framework+3.0+Tutorial+-+cz+1+-+przygotowanie+projektu%2C+witaj+%C5%9Bwiecie&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;title=Spring+Framework+3.0+Tutorial+-+cz+1+-+przygotowanie+projektu%2C+witaj+%C5%9Bwiecie" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie&amp;title=Spring+Framework+3.0+Tutorial+-+cz+1+-+przygotowanie+projektu%2C+witaj+%C5%9Bwiecie&amp;description=Zanim%20przyst%C4%85pimy%20do%20tworzenia%20projektu%20warto%20odpowiednio%20przygotowa%C4%87%20sobie%20zaplecze%20techniczne.%20Z%20racji%2C%20%C5%BCe%20w%20eclipse%20pisze%20znaczna%20cz%C4%99%C5%9B%C4%87%20firm%20%28przynajmniej%20polskich%29%2C%20a%20ja%20jeszcze%20z%20niego%20nie%20korzysta%C5%82em%20w%20tego%20typu%20projektach%20postanowi%C5%82em%2C%20%C5%BCe%20to%20b%C4%99dzie%20dobry%20moment%20by%20si%C4%99%20z%20nim%20zmierzy" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/3hb5xThAjPv5ltgaPoMD6BwnIbY/0/da"><img src="http://feedads.g.doubleclick.net/~a/3hb5xThAjPv5ltgaPoMD6BwnIbY/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/3hb5xThAjPv5ltgaPoMD6BwnIbY/1/da"><img src="http://feedads.g.doubleclick.net/~a/3hb5xThAjPv5ltgaPoMD6BwnIbY/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/jvHG8BC1dZA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-cz-1-przygotowanie-projektu-witaj-swiecie</feedburner:origLink></item>
		<item>
		<title>Spring Framework 3.0 Tutorial – wstęp</title>
		<link>http://feedproxy.google.com/~r/darekzon/~3/SCm2apHQT3o/spring-framework-3-0-tutorial-wstep</link>
		<comments>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep#comments</comments>
		<pubDate>Fri, 09 Apr 2010 20:17:44 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[jasypt]]></category>
		<category><![CDATA[lucene]]></category>
		<category><![CDATA[sitemesh]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=674</guid>
		<description><![CDATA[Największym minusem podczas nauki Spring Framework był brak kompleksowych przykładów pokazujących jak zbudować pełną aplikację wykorzystując nie tylko Spring-a, ale również integrując z&#160;nim inne rozwiązania. Ten tutorial ma za zadanie uzupełnić tą lukę, choć jego zadanie jest troszkę większe. Pisząc tutorial mam zamiar nie tylko pokazać jak wygląda taka aplikacja, ale również skonsolidować swoją wiedzę [...]]]></description>
			<content:encoded><![CDATA[<p>Największym minusem podczas nauki Spring Framework był brak kompleksowych przykładów pokazujących jak zbudować pełną aplikację wykorzystując nie tylko Spring-a, ale również integrując z&nbsp;nim inne rozwiązania.</p>
<p>Ten tutorial ma za zadanie uzupełnić tą lukę, choć jego zadanie jest troszkę większe. Pisząc tutorial mam zamiar nie tylko pokazać jak wygląda taka aplikacja, ale również skonsolidować swoją wiedzę oraz nauczyć się czegoś więcej od was (choćby poprzez komentarze). Myślę, że będzie to dobre miejsce na wszelkie dyskusje na temat technologii użytych w&nbsp;projekcie oraz sposobu ich użycia. Z&nbsp;chęcią przyjmę również wszelką KONSTRUKTYWNĄ krytykę.</p>
<p>Projekt jaki tutaj zrealizuje to księgarnia internetowa (helion może zacząć się bać <img src='http://darekzon.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ) która na początku oferować będzie standardowe funkcjonalności (kategorie, książki, wyszukiwarkę, mechanizm zamawiania). Szerzej opiszę wszystko w&nbsp;następnych częściach tutorialu.</p>
<p>W projekcie mam zamiar wykorzystać:</p>
<ul>
<li>Spring Framework 3.0</li>
<li>Hibernate + Hibernate Search (implementacja wyszukiwarki Lucene)</li>
<li>Jasypt</li>
<li>Sitemesh</li>
<li>inne o&nbsp;których jeszcze nie wiem</li>
<li>Lucene (indeksowanie/wyszukiwanie zawartości)</li>
<li>inne</li>
</ul>
<p>Wkrótce podam również adres do repozytorium projektu który umieszczony będzie na serwerach kenai.com (wkrótce w&nbsp;strukturach java.net)</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-knowledge">
<ul class="socials">
		<li class="shr-wykop">
			<a href="http://www.wykop.pl/dodaj?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;title=Spring+Framework+3.0+Tutorial+-+wst%C4%99p" rel="nofollow" class="external" title="Add this to Wykop!">Add this to Wykop!</a>
		</li>
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;t=Spring+Framework+3.0+Tutorial+-+wst%C4%99p" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
		<li class="shr-comfeed">
			<a href="http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep/feed" rel="nofollow" class="external" title="Subscribe to the comments for this post?">Subscribe to the comments for this post?</a>
		</li>
		<li class="shr-blogger">
			<a href="http://www.blogger.com/blog_this.pyra?t&amp;u=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;n=Spring+Framework+3.0+Tutorial+-+wst%C4%99p&amp;pli=1" rel="nofollow" class="external" title="Blog this on Blogger">Blog this on Blogger</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;title=Spring+Framework+3.0+Tutorial+-+wst%C4%99p" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-dzone">
			<a href="http://www.dzone.com/links/add.html?url=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep&amp;title=Spring+Framework+3.0+Tutorial+-+wst%C4%99p&amp;description=Najwi%C4%99kszym%20minusem%20podczas%20nauki%20Spring%20Framework%20by%C5%82%20brak%20kompleksowych%20przyk%C5%82ad%C3%B3w%20pokazuj%C4%85cych%20jak%20zbudowa%C4%87%20pe%C5%82n%C4%85%20aplikacj%C4%99%20wykorzystuj%C4%85c%20nie%20tylko%20Spring-a%2C%20ale%20r%C3%B3wnie%C5%BC%20integruj%C4%85c%20z%20nim%20inne%20rozwi%C4%85zania.%0D%0A%0D%0ATen%20tutorial%20ma%20za%20zadanie%20uzupe%C5%82ni%C4%87%20t%C4%85%20luk%C4%99%2C%20cho%C4%87%20jego%20zadanie%20jest%20t" rel="nofollow" class="external" title="Add this to DZone">Add this to DZone</a>
		</li>
		<li class="shr-technorati">
			<a href="http://technorati.com/faves?add=http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep" rel="nofollow" class="external" title="Share this on Technorati">Share this on Technorati</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>


<p><a href="http://feedads.g.doubleclick.net/~a/y9c84HoJMr6OKHz7-Xdf5e8jnbA/0/da"><img src="http://feedads.g.doubleclick.net/~a/y9c84HoJMr6OKHz7-Xdf5e8jnbA/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/y9c84HoJMr6OKHz7-Xdf5e8jnbA/1/da"><img src="http://feedads.g.doubleclick.net/~a/y9c84HoJMr6OKHz7-Xdf5e8jnbA/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/darekzon/~4/SCm2apHQT3o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://darekzon.com/2010/04/spring-framework-3-0-tutorial-wstep</feedburner:origLink></item>
	</channel>
</rss>
