<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>dev garden &#187; Java</title>
	<atom:link href="http://darekzon.com/category/java/feed" rel="self" type="application/rss+xml" />
	<link>http://darekzon.com</link>
	<description>when technology meets nature</description>
	<lastBuildDate>Mon, 19 Mar 2012 23:02:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Globalne łapanie wyjątków w Spring 3.1</title>
		<link>http://darekzon.com/2012/03/globalne-lapanie-wyjatkow-w-spring-3-1</link>
		<comments>http://darekzon.com/2012/03/globalne-lapanie-wyjatkow-w-spring-3-1#comments</comments>
		<pubDate>Mon, 19 Mar 2012 23:01:40 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Projektowanie aplikacji]]></category>
		<category><![CDATA[Spring framework]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring3.1]]></category>
		<category><![CDATA[wyjątki]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1416</guid>
		<description><![CDATA[Wielokrotnie wchodząc na przeróżne strony zamiast oczekiwanej przeze mnie treści pojawiała się strona z błędami aplikacji, i nie był to tylko komunikat w stylu &#8222;Błąd strony&#8221; a pełne kody błędów, łącznie ze stacktracem czy też kodem strony (jeśli była pisana &#8230; <a href="http://darekzon.com/2012/03/globalne-lapanie-wyjatkow-w-spring-3-1">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Wielokrotnie wchodząc na przeróżne strony zamiast oczekiwanej przeze mnie treści pojawiała się strona z błędami aplikacji, i nie był to tylko komunikat w stylu &#8222;Błąd strony&#8221; a pełne kody błędów, łącznie ze stacktracem czy też kodem strony (jeśli była pisana w języku skryptowym). Nie trzeba chyba nikomu tłumaczyć, że tego typu treść nigdy nie powinna być widoczna dla użytkownika końcowego. I nie tylko dlatego, że strona taka brzydko wygląda i może odstraszyć użytkowników. Treści wyjątków jakie powoduje aplikacja, czy też część kodu jakie pojawią się mogą być bez problemu wykorzystane przez osoby interesujące się zabezpieczeniami.<span id="more-1416"></span></p>
<p>W bibliotece SpringFramework, istnieje coś takiego jak ExceptionHandler, który działa lokalnie i jest implementowany per kontroler co przy większej aplikacji może być mało wygodne. Niestety globalny mechanizm przechwytywania powstanie najwcześniej w wersji 3.2(kiedyś przeczytałem pewien komentarz programisty Springa w ich systemie Jira) więc puki co musimy radzić sobie sami. Prosty system przechwytujący wyjątki można napisać samemu i nawet specjalnie się przy tym nie napracujemy.<br />
Do stworzenia takiego systemu będziemy potrzebować najnowszych bibliotek Springa oraz bibliotek wspomagających programowanie aspektowe (aspectjweaver)</p>
<p>Na początek skonfigurujemy klasę która będzie obsługiwać wyjątki, konfigurację umieszczamy w applicationContext.xml</p>
<pre class="brush: xml; title: ; notranslate">&lt;/pre&gt;
&lt;aop:aspectj-autoproxy /&gt;
 &lt;aop:config&gt;
 &lt;aop:aspect id=&quot;exceptionHandler&quot; ref=&quot;globalExceptionHandler&quot;&gt;
 &lt;!-- find all methods that returns ModelAndView objects --&gt;
 &lt;aop:pointcut expression=&quot;execution(org.springframework.web.servlet.ModelAndView+ *(..))&quot; id=&quot;returningMav&quot; /&gt;
 &lt;!-- and execute them inside exceptionHandler --&gt;
 &lt;aop:around method=&quot;exceptionHandler&quot; pointcut-ref=&quot;returningMav&quot; /&gt;
 &lt;/aop:aspect&gt;
 &lt;/aop:config&gt;
 &lt;bean id=&quot;globalExceptionHandler&quot; class=&quot;com.darekzon.spring.exhandler.aop.ExceptionHandler&quot; /&gt;
&lt;pre&gt;</pre>
<p>Powyższy zapis konfiguruje system tak aby wyłapał wszystkie metody zwracające obiekt &#8222;ModelAndView&#8221; (czyli zazwyczaj metody mapujące URL-e) i przekazywał je do naszego obiektu, a dokładniej do metody &#8222;exceptionHandler&#8221; w klasie &#8222;ExceptionHandler&#8221;.<br />
Metody te będą przekazywane w formie obiektu ProceedingJoinPoint posiadającego metodę &#8222;proceed&#8221; która służy do wywołania domyślnej akcji.</p>
<p>Nasza metoda obsługująca wyjątki wygląda jak poniżej</p>
<pre class="brush: java; title: ; notranslate">
public ModelAndViewexceptionHandler(ProceedingJoinPoint pjp)throws Throwable{
        ModelAndView mav=newModelAndView();
        try{
            mav=(ModelAndView) pjp.proceed();
        }catch(Exceptionae){
            mav.addObject(&quot;exceptionMessage&quot;,ae.getMessage());
            mav.setViewName(&quot;exception&quot;);
        }
        return mav;
    }
</pre>
<p>Działanie jest proste, wywołaj metodę która może rzucić wyjątek (tj. metodę obsługującą url) i jeśli taki wyjątek zostanie rzucony, złap go, dodaj jego wiadomość do widoku jako &#8216;exceptionMessage&#8217; oraz wygeneruj widok o nazwie &#8216;exception&#8217;. A co za tym idzie, jeśli nasza metoda kontrolera wyrzuci wyjątek, zostanie on złapany a zamiast niego zostanie zwrócony poprawny obiekt ModelAndView.</p>
<p>Oczywiście zamiast prostej podmiany widoków możemy przekierować użytkownika do innej strony, zapisać logi, czy też wysłać maila.</p>
<h3>Działający projekt</h3>
<blockquote><p>Działający projekt można pobrać przeglądać pod adresem <a title="Spring 3.1 globalne łapanie wyjątków" href="https://github.com/darek/spring.3.examples/tree/master/aop-global-exception-handler" target="_blank">https://github.com/darek/spring.3.examples/tree/master/aop-global-exception-handler</a></p></blockquote>
<div class="shr-publisher-1416"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2012/03/globalne-lapanie-wyjatkow-w-spring-3-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Źródła IntelliJ Community dostępne za darmo, inne wersje tańsze</title>
		<link>http://darekzon.com/2011/10/zrodla-intellij-community-dostepne-za-darmo-inne-wersje-tansze</link>
		<comments>http://darekzon.com/2011/10/zrodla-intellij-community-dostepne-za-darmo-inne-wersje-tansze#comments</comments>
		<pubDate>Fri, 07 Oct 2011 20:47:18 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[IDE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Swing/SWT]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[intellij]]></category>
		<category><![CDATA[jetbrains]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[testng]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1397</guid>
		<description><![CDATA[Firma Jetbrains znana z wysokiej jakości środowisk programistycznych (IDE) postanowiła kilka dni temu wypuścić kod źródłowy swojego flagowego produktu. Kod źródłowy został umieszczony na serwerach GitHuba w ramach konsolidacji projektów open-source-owych prowadzonych w firmie. Na serwerach GitHuba dostępna jest wersja &#8230; <a href="http://darekzon.com/2011/10/zrodla-intellij-community-dostepne-za-darmo-inne-wersje-tansze">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Firma Jetbrains znana z wysokiej jakości środowisk programistycznych (IDE) postanowiła kilka dni temu wypuścić <a title="IntelliJ - Community Edition" href="https://github.com/JetBrains/intellij-community" target="_blank">kod źródłowy</a> swojego flagowego produktu. Kod źródłowy został umieszczony na serwerach GitHuba w ramach konsolidacji projektów open-source-owych prowadzonych w firmie.</p>
<p><span id="more-1397"></span>Na serwerach GitHuba dostępna jest wersja Community Edition która posiada pełne wsparcie dla języków Java, Groovy, Xml, Sala, Clojure (dwa ostatnie po zainstalowaniu darmowych wtyczek), a także posiada GUI builder, integrację frameworków testujących (JUnit oraz TestNG) oraz wsparcie dla Maven-a i Ant-a. Dla tych którzy wolą programować aplikacje mobilne zaimplementowane jest wsparcie platformy Android, a dla pracujących w grupie przewidziane jest wsparcie systemów kontroli wersji CVS, Subversion, Git (wraz z integracją GitHub-a) oraz Mercurial. Jeśli nie macie gdzie publikować swoich źródeł polecam BitBucket który ostatnimi czasy przeszedł <a title="Atlassian Bitbucket – wreszcie wsparcie dla GIT-a" href="http://darekzon.com/2011/10/atlassian-bitbucket-wreszcie-wsparcie-dla-git-a">małą modernizację</a>.</p>
<p>Niestety w tych wszystkich wspaniałościach zabrakło dla mnie najważniejszej rzeczy, czyli pełnego wsparcia dla frameworków webowych (JSP, Spring, Hibernate, etc.) które to są dostępne dopiero w płatnych edycjach.</p>
<p>Gdyby ktoś tak jak ja potrzebował funkcjonalności nie zawartych w wersji Community może wybrać wersję Ultimate i skorzystać z nowych cen jakie zaproponował Jetbrains, za najtańszą wersję (Personal License) zapłacimy 175€ czyli o 44€ mniej (poprzednia cena 219€), natomiast licencja dla firm i organizacji (Commercial License) to wydatek rzędu 439€ o 88€ mniej (poprzednia cena 527€). Oczywiście możliwe jest też otrzymanie licencji na wersję Ultimate za darmo o ile prowadzimy w miarę popularny projekt Open Source.</p>
<div class="shr-publisher-1397"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/10/zrodla-intellij-community-dostepne-za-darmo-inne-wersje-tansze/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Prosta aplikacja RESTful w Struts2 (Convention i REST plugin), Guice i MongoDB</title>
		<link>http://darekzon.com/2011/09/prosta-aplikacja-restful-w-struts2-convention-i-rest-plugin-guice-i-mongodb</link>
		<comments>http://darekzon.com/2011/09/prosta-aplikacja-restful-w-struts2-convention-i-rest-plugin-guice-i-mongodb#comments</comments>
		<pubDate>Fri, 30 Sep 2011 20:40:08 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[convention-plugin]]></category>
		<category><![CDATA[guice]]></category>
		<category><![CDATA[jee]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[morphia]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[rest-plugin]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1366</guid>
		<description><![CDATA[Ponieważ od jakiegoś czasu zdobywam wiedzę na temat nowych frameworków i technologii postanowiłem stworzyć właśnie projekt który integruje je wszystki. Wykorzystam w nim frameworki Guice oraz Struts2, a za przechowywanie danych odpowiadać będzie MongoDB wspierana przez bibliotekę Morphia. Dodatkowo z &#8230; <a href="http://darekzon.com/2011/09/prosta-aplikacja-restful-w-struts2-convention-i-rest-plugin-guice-i-mongodb">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Ponieważ od jakiegoś czasu zdobywam wiedzę na temat nowych frameworków i technologii postanowiłem stworzyć właśnie projekt który integruje je wszystki. Wykorzystam w nim frameworki <a title="Guice - lightweight dependency injection framework" href="http://code.google.com/p/google-guice/" target="_blank">Guice</a> oraz <a title="Struts2 - extensible framework for creating enterprise-ready Java web applications" href="http://struts.apache.org/2.x/" target="_blank">Struts2</a>, a za przechowywanie danych odpowiadać będzie <a title="MongoDB" href="http://www.mongodb.org/" target="_blank">MongoDB</a> wspierana przez bibliotekę <a title="Morphia: A type-safe java library for MongoDB" href="http://code.google.com/p/morphia/" target="_blank">Morphia</a>. Dodatkowo z racji, że ostatnio co chwile mówi się o aplikacjach REST-owych postanowiłem wykorzystać ten wzorzec w mojej aplikacji &#8211; &#8222;<a title="Struts2 REST shopping list (with struts2-convention plugin, struts2-rest plugin, guice, mongodb and morphia)" href="https://github.com/darek/struts2-rest-shopping-list" target="_blank">liście zakupowej</a>&#8222;.</p>
<p><span id="more-1366"></span></p>
<h2>Skąd pobrać projekt</h2>
<blockquote><p>Projekt dostępny jest w formie repozytorium GIT pod adresem <a title="Struts2 REST shopping list (with struts2-convention plugin, struts2-rest plugin, guice, mongodb and morphia)" href="https://github.com/darek/struts2-rest-shopping-list" target="_blank">https://github.com/darek/struts2-rest-shopping-list</a></p></blockquote>
<h2>Struts2 oraz Guice</h2>
<p>Jeśli ktoś nie zna frameworka Struts2 to wspomnę tylko, że jest to jeden z bardziej popularnych bibliotek do tworzenia aplikacji JEE. Cechuje się elastycznością oraz rozszerzalnością (poprzez pluginy).<br />
Guice jest dość świeży na polu frameworków, służy do wstrzykiwania zależności, a jego twórcami są inżynierowie Google.</p>
<h2>MongoDB</h2>
<p>Jak wspomniałem na wstępie MongoDB to baza danych oparta o dokumenty, oznacza to tyle, że dane w niej zawarte nie reprezentowane są w formie tabel posiadającej sztywny schemat a raczej w formie łatwo rozszerzalnego dokumentu (wykorzystywany jest tu format <a title="BSON" href="http://bsonspec.org/" target="_blank">BSON</a>). Największą zaletą (prócz łatwej skalowalności i wydajności) jest brak schematu, możemy wrzucić do niej co tylko chcemy bez potrzeby aktualizacji struktur tabel, każdy dokument nawet jeśli jest w tej samej kolekcji może się różnić od innych. Dokumenty te jednak nie posiadają powiązań więc trudniej jest zaimplementować schemat typu jeden do wielu, wiele do wielu. Pomimo tego baza ta idealnie nadaje się do mojej aplikacji. W końcu każda lista zakupowa posiada swój własny zestaw produktów do kupienia, nie potrzebujemy tu oddzielnej tabeli do składowania produktów.</p>
<h2>REST</h2>
<p>Od dłuższego czasu coraz większą popularność zyskuje wzorzec architektury zwany <a title="REST" href="http://pl.wikipedia.org/wiki/Representational_State_Transfer" target="_blank">REST</a> (Representational State Transfer) zaproponowany przez <a title="Strona domowa Roy-a Thomasa Fieldinga" href="http://www.ics.uci.edu/~fielding/" target="_blank">Roya T. Fieldinga</a> w publikacji <a title="Principled Design of Modern Web Architecture, Roy T. Fielding (REST)" href="http://www.ics.uci.edu/~taylor/documents/2002-REST-TOIT.pdf" target="_blank">Principled Design of the Modern Web Architecture</a>. W wielkim skrócie chodzi o takie przygotowanie aplikacji by zasoby którymi operuje były dostępne pod unikalnymi linkami (URI), czyli żeby wyświetlić szczegóły użytkownika naszej aplikacji wykorzystamy adres http://example.com/user/23 (gdzie 23 to jego unikalny identyfikator). Dzięki takiemu rozwiązaniu zapewniony jest warunek bezstanowości aplikacji (nie ma ukrytego wysyłania danych aby zobaczyć dany zasób, np. http://example.com/user + cookie.id=23 do wyświetlenia zasobu użytkownika). Drugą chyba najbardziej widoczną cechą jest użycie większej ilości operacji protokołu HTTP. Zwykła aplikacja zazwyczaj używa tylko dwóch metod: POST i GET podczas gdy aplikacje napisane z wykorzystaniem REST-u mogą dodatkowo wykorzystać metody CREATE, PUT, DELETE  dzięki czemu jeden adres URI może służyć do wielu celów, gdy wywołamy adres http://example.com/user/23 metodą DELETE aplikacja powinna usunąć użytkownika o identyfikatorze 23, wywołując ten sam adres metodą PUT zaktualizujemy dane użytkownika itd. Więcej o architekturze REST możecie poczytać w sieci.</p>
<h2>Aplikacja</h2>
<h3>Założenia aplikacji</h3>
<ul>
<li>Aplikacja ma być bardzo uproszczona, powinna posiadać 2 główne widoki, pierwszy do tworzenia list zakupowych i wybierania ich poprzez wpisanie specjalnego identyfikatora, drugi widok powinien wyświetlać szczegóły listy wraz z produktami, oraz powinien pozwalać na dodawanie i usuwanie produktów.</li>
<li>Tworzenie listy ma następować po wpisaniu w formularzu nazwy listy i wysłaniu go metodą POST do odpowiedniego kontrolera</li>
<li>Otwieranie listy następować będzie poprzez wpisanie jej identyfikatora w odpowiednim formularzu i wysłanie go metodą GET do kontrolera list</li>
<li>Dodawanie produktów odbywać się będzie poprzez wysłanie danych z formularza (nazwa i ilość) metodą POST do kontrolera produktów</li>
<li>Kasowanie produktów odbywać się będzie poprzez wysłanie identyfikatora produktu metodą DELETE do kontrolera produktów</li>
</ul>
<h3>Konfigurowanie projektu</h3>
<p>Na początek skonfigurujemy wszystkie zależności wymagane w projekcie przy użyciu maven-owskiego pliku pom.xml.</p>
<pre class="brush: xml; title: ; notranslate">

&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
&lt;groupId&gt;shopping-list&lt;/groupId&gt;
&lt;artifactId&gt;shopping-list&lt;/artifactId&gt;
&lt;version&gt;0.1.0&lt;/version&gt;
&lt;packaging&gt;war&lt;/packaging&gt;
&lt;build&gt;
&lt;plugins&gt;
&lt;plugin&gt;
&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
&lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;
&lt;version&gt;2.1.1&lt;/version&gt;
&lt;configuration&gt;
&lt;!-- &lt;packagingExcludes&gt;**/web.xml&lt;/packagingExcludes&gt; --&gt;
&lt;webXml&gt;web/WEB-INF/web.xml&lt;/webXml&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/plugins&gt;
&lt;/build&gt;
&lt;repositories&gt;
&lt;repository&gt;
&lt;id&gt;morphia&lt;/id&gt;
&lt;url&gt;http://morphia.googlecode.com/svn/mavenrepo/&lt;/url&gt;
&lt;/repository&gt;
&lt;/repositories&gt;
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;aopalliance&lt;/groupId&gt;
&lt;artifactId&gt;aopalliance&lt;/artifactId&gt;
&lt;version&gt;1.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.inject&lt;/groupId&gt;
&lt;artifactId&gt;guice&lt;/artifactId&gt;
&lt;version&gt;3.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.inject.extensions&lt;/groupId&gt;
&lt;artifactId&gt;guice-servlet&lt;/artifactId&gt;
&lt;version&gt;3.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.mongodb&lt;/groupId&gt;
&lt;artifactId&gt;mongo-java-driver&lt;/artifactId&gt;
&lt;version&gt;2.5.2&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.code.morphia&lt;/groupId&gt;
&lt;artifactId&gt;morphia&lt;/artifactId&gt;
&lt;version&gt;0.99&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.apache.struts&lt;/groupId&gt;
&lt;artifactId&gt;struts2-rest-plugin&lt;/artifactId&gt;
&lt;version&gt;2.2.3.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
&lt;artifactId&gt;struts2-core&lt;/artifactId&gt;
&lt;version&gt;2.2.3.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;log4j&lt;/groupId&gt;
&lt;artifactId&gt;log4j&lt;/artifactId&gt;
&lt;version&gt;1.2.16&lt;/version&gt;
&lt;scope&gt;compile&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;javax.servlet&lt;/groupId&gt;
&lt;artifactId&gt;servlet-api&lt;/artifactId&gt;
&lt;version&gt;2.5&lt;/version&gt;
&lt;type&gt;jar&lt;/type&gt;
&lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
&lt;artifactId&gt;struts2-convention-plugin&lt;/artifactId&gt;
&lt;version&gt;2.2.3.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.inject.extensions&lt;/groupId&gt;
&lt;artifactId&gt;guice-struts2&lt;/artifactId&gt;
&lt;version&gt;3.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
&lt;modules&gt;
&lt;/modules&gt;
&lt;/project&gt;
</pre>
<p>Poza podstawowymi frameworkami (Guice i Struts) użyjemy również dwóch pluginów Strutsa2 które ułatwią pisanie aplikacji, oraz pozwolą zaimplementować architekturę REST, zostaną one opisane później. Aby dodać biblioteki Morphia potrzebne było skonfigurowanie dodatkowego repozytorium (jako repozytorium służy strona google code).</p>
<p>Naszym głównym frameworkiem będzie Struts2 który będzie odpowiadać za przekierowywanie naszych żądań do odpowiednich klas i generowanie odpowiedzi, Guice będzie pełnił rolę narzędzia do wstrzykiwania zależności (zob. <a title="Wstrzykiwanie zależności" href="http://pl.wikipedia.org/wiki/Wstrzykiwanie_zale%C5%BCno%C5%9Bci" target="_blank">Dependency Injection</a>) dlatego też potrzebujemy plugin Guice-Struts2 który to pozwoli ładnie połączyć oba frameworki.</p>
<p>Jak w każdej aplikacji webowej tak i w tej potrzebujemy skonfigurowany plik web.xml. Ponieważ nasza aplikacja nie jest szczególnie skomplikowana tak i tutaj nie będzie niczego nadzwyczajnego. No może poza jedną rzeczą.</p>
<pre class="brush: xml; title: ; notranslate">

&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;WebApp_ID&quot; version=&quot;2.5&quot;&gt;
&lt;display-name&gt;shopping-list&lt;/display-name&gt;
&lt;listener&gt;
&lt;listener-class&gt;com.darekzon.shoppinglist.listener.GuiceStruts2PluginListener&lt;/listener-class&gt;
&lt;/listener&gt;

&lt;filter&gt;
&lt;filter-name&gt;struts&lt;/filter-name&gt;
&lt;filter-class&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
&lt;filter-name&gt;struts&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;

&lt;/web-app&gt;
</pre>
<p>Poza skonfigurowaniem Struts-owego flitra i przekierowaniem do niego wszystkich zapytań musieliśmy utworzyć Listener który odpowiadać będzie za wstrzykiwanie zależności. Listener stworzył <a title="Crazy Bob" href="http://blog.crazybob.org/" target="_blank">Bob Lee</a> jednak nie pamiętam skąd go pobrałem (zapewne jakaś strona w Google Code lub z forum), poza skopiowaniem Listenera zainstalowałem w nim mój moduł który będzie wstrzykiwał zależności (entity manager oraz repozytorium).</p>
<pre class="brush: java; title: ; notranslate">
public class GuiceStruts2PluginListener extends GuiceServletContextListener {

public Injector getInjector() {
return Guice.createInjector(
new Struts2GuicePluginModule(),
new ServletModule() {
@Override
protected void configureServlets() {
// Struts 2 setup
bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class);
filter(&quot;/*&quot;).through(StrutsPrepareAndExecuteFilter.class);

install(new ShoppingListModule());
}
});
}

}
</pre>
<p>Pora na konfigurację głównego frameworka, ponieważ ostatnio zniechęciłem się do XML-a użyję plików *.properties które umieszczam w głównym folderze z źródłami.<br />
Plik struts.properties odpowiedzialny jest za konfigurację Strutsa i wygląda następująco:</p>
<pre class="brush: plain; title: ; notranslate">

struts.objectFactory = guice

# Fix exception &quot;Cannot cast HttpHeaders to String&quot;
struts.rest.namespace =

struts.mapper.class = rest
struts.convention.action.suffix = Controller
struts.convention.action.mapAllMatches = true
struts.convention.action.alwaysMapExecute = true

struts.convention.relative.result.types    = dispatcher
struts.convention.default.parent.package = rest-default
struts.convention.package.locators  = actions

struts.devMode = true
</pre>
<p>Na samym początku konfigurujemy fabrykę obiektów (czyli wskazujemy Strutsowi aby używał pluginu Struts2Guice o którym wspomniałem wcześniej).<br />
Opcja <em>struts.rest.namespace</em> to przestrzeń nazw dla serwisów REST-owych (tak jakby kontekst pod którym będą dostępne). Ustawienie tej wartości na &#8222;<strong>nic</strong>&#8221; pozwoli uniknąć bardzo uciążliwego problemu przez którego nie można było używać HttpHeaders jako rezultatu metod (zob. <a title="Issue: org.apache.struts2.rest.DefaultHttpHeaders cannot be cast to java.lang.String" href="https://issues.apache.org/jira/browse/WW-3616" target="_blank">błąd 3616</a> ), warto dodać, że wartość tą należy zostawić pustą, wstawienie &#8222;&#8221; spowoduje wyrzucanie wcześniej wspomnianych błędów.</p>
<p><em>struts.mapper.class</em> pozwala ustalić jak żądania URL będą mapowane (co będzie wywoływane po wpisaniu adresu url), rozwinięcie tej nazwy znajdziecie w plikach konfiguracyjnych konkretnego pluginu (w tym przypadku wystarczy wejść do biblioteki struts2-rest-plugin i otworzyć plik struts-plugin.xml).Kolejne wartości ustalają jak ma działać plugin Convention, aby dowiedzieć się co oznaczają możecie przejść do odpowiedniej sekcji na <a title="Struts2 Convention Plugin" href="https://cwiki.apache.org/confluence/display/WW/Convention%20Plugin#ConventionPlugin-Configurationreference" target="_blank">stronie pluginu</a>.</p>
<p>Konfiguracja bazy danych jest bardzo prosta, wystarczy podać dane dostępowe takie jak host, port, login oraz haslo, a także tzw. datastore (czyli nazwę bazy). To wszystko odbywa się w pliku database.properties którego nie trzeba przytaczać.</p>
<h3>Jak działają pluginy Strutsa</h3>
<p>W aplikacji mamy doczynienia z dwoma pluginami Struts2, pierwszy z nich Convention będzie mapować nasze adresy URL na pakiety i klasy co to znaczy?<br />
Załóżmy, że mamy dwie klasy<em> com.darekzon.application.UserController</em> oraz <em>com.darekzon.application.user.DetailsController.</em> Niech nasza aplikacja będzie dostępna pod adresem <em>http://example.com/</em>. W takim przypadku adres <em>http://example.com/user</em> wywoła nam klasę UserController, natomiast adres <em>http://example.com/user/details </em>wywoła klasę DetailsController znajdującą się w pakiecie <strong>user</strong>.<br />
Rest-plugin działa trochę inaczej, on do mapowania używa metod HTTP. Mając nasz kontroler UserController możemy go wywołać na 4 sposoby za każdym razem zostanie wywołana inna metoda.</p>
<pre class="brush: plain; title: ; notranslate">
 GET         - http://example.com/user  - zostanie wywołana metoda INDEX
POST       - http://example.com/user  - zostanie wywołana metoda CREATE
 GET         -  http://example.com/user/ID  - zostanie wywołana metoda SHOW
 PUT         - http://example.com/user/ID - zostanie wywołana metoda UPDATE
 DELETE - http://example.com/user/ID - zostanie wywołana metoda DELETE
</pre>
<p>Metoda PUT oraz Delete muszę mieć dodatkowy parametr ID (identyfikator obiektu) ponieważ są wykonywane na obiekcie (więc logiczne, że trzeba wskazać obiekt). Gdy do metody GET dodamy identyfikator zostanie wywołana metoda SHOW ponieważ aplikacja wie że w tym wypadku, nie chcemy listy a konkretny obiekt.</p>
<h3>Drugi kontroler</h3>
<p>Nie będę pokazywał jak powstał pierwszy kontroler, bo jest on na tyle prosty, że nie wymaga opisu, zabawę zaczniemy z drugim, najważniejszym kontrolerem który  odpowiadać będzie za obsługę całej listy, a zwie się <em>ShoppingListController</em>.<br />
Ponieważ ShoppingListController będzie operować na danych, musimy wskazać mu klasę która będzie do tego przeznaczona, w tym przypadku jest to ShoppingListRepository a dodajemy ją do kontrolera poprzez wstrzyknięcie</p>
<pre class="brush: java; title: ; notranslate">
ShoppingListRepository shoppingListRepository;

@Inject
publicvoid setShoppingListRepository(ShoppingListRepository pr){
this.shoppingListRepository = pr;
}
</pre>
<p>Szczegółowa implementacja tej klasy dostępna jest w źródłach.<br />
Ważny jest również fakt, że klasa ta implementuje interfejs <strong>ModelDriven&lt;T&gt;</strong>, dzięki temu gdy poprosimy o dane w formacie XML nasza aplikacja będzie wiedziała jaki obiekt przetworzyć do żądanej postaci. Gdyby nie było tego interfejsu, przy prośbie o format XML dostalibyśmy przetkonwerterowaną całą klasę ShoppingListController czego chcemy uniknąć. Interfejs ten wymaga od nas zaimplementowania jednej metody &#8222;<strong>public T getModel()</strong>&#8221; zwracającej obiekt który będziemy konwertować (w razie konieczności).</p>
<h4>Strona początkowa:</h4>
<p>Strona początkowa aplikacji posiada dwa formularze, pierwszy otwiera listę o zadanym przez nas identyfikatorze, druga po podaniu nazwy tworzy taką listę. Widok prezentuje się następująco:</p>
<div id="attachment_1374" class="wp-caption aligncenter" style="width: 310px"><a href="http://www3.darekzon.com/wp-content/uploads/2011/09/shopping-list-forms.jpg" rel="lightbox[1366]"><img class="size-medium wp-image-1374" title="Shopping-list formularze" src="http://www3.darekzon.com/wp-content/uploads/2011/09/shopping-list-forms-300x175.jpg" alt="" width="300" height="175" /></a><p class="wp-caption-text">Strona początkowa</p></div>
<p>Pierwsza metoda jaką wywołujemy (czyli index wchodząc pod adres <em>http://example.com/shopping-list/index.xhtml</em>) wygląda następująco:</p>
<pre class="brush: java; title: ; notranslate">
public HttpHeaders index(){
if(this.id != null &amp;&amp; this.list==null){
returnnew DefaultHttpHeaders(&quot;notfound&quot;).withStatus(404);
}
if(this.id !=null &amp;&amp; this.list!=null){
// BUG - even with directly setted 302 status application is returning 201 (created) status.
return new DefaultHttpHeaders(&quot;show&quot;).setLocationId(this.id).withStatus(302);
}
return new DefaultHttpHeaders(&quot;index&quot;);
}
</pre>
<p>Tak naprawdę mogłaby być ona pusta z racji, że jej jedynym zadaniem jest wyświetlenie dwóch formularzy, ale wysyłanie formularza otwierającego listę powoduje wywołanie w/w metody (a nie metody show jak mogłoby się zdawać) dzieje się tak ponieważ wysłanie formularza przenosi nas pod adres <em>http://example.com/shopping-list/index.xhtml?id=IDENTYFIKATOR</em>  &#8211; a tego plugin rest nie potrafi zmapować do metody SHOW. W metodziej tej sprawdzamy oczywiście, czy lista istnieje, jeśli nie, wyświetlamy komunikat (cały widok) z informacją o braku listy oraz co ważne wysyłamy status HTTP 404 (<strong>NOT FOUND</strong>).<br />
Jeśli lista została znaleziona wysyłamy jej identyfikator oraz status 302 (<strong>FOUND</strong>) który powinien wymusić na przeglądarce automatyczne przekierowanie pod prawidłowy adres (tj. http://example.com/shopping-list/ID.xhtml)</p>
<h4>Tworzenie listy:</h4>
<p>Lista tworzona jest po wysłaniu formularza metodą post pod adres http://example.com/shopping-list/index.xhtml, wtedy wywoływana jest metoda create która wygląda następująco:</p>
<p>@Validations(requiredStrings = {@RequiredStringValidator(type = ValidatorType.FIELD, fieldName = &#8222;list.name&#8221;, message = &#8222;You must set shopping list name a value for string.&#8221;)})<br />
public HttpHeaders create(){<br />
String id = this.shoppingListRepository.create(this.list);<br />
returnnew DefaultHttpHeaders(&#8222;create&#8221;).withStatus(201).setLocationId(id.toString());<br />
}</p>
<p>Nad wyraz prosta (jak cała aplikacja) metoda składa się z 3 części:</p>
<ol>
<li>ustawienie walidatora tak by wymagał podania nazwy listy</li>
<li>przesłanie listy (z wypełnionym polem nazwy) do repozytorium w celu zapisania w bazie</li>
<li>zwrócenie nagłówków ze statusem 201 (CREATED) oraz identyfikatorem listy w celu przejścia do strony z listą</li>
</ol>
<p>Metodę tą możemy wywołać na 3 sposoby, poprzez wypełnienie formularza na stronie oraz wciśnięcie przycisku, poprzez wysłanie zapytania w formie XML-a (metodą <strong>CREATE</strong>) pod adres http://example.com/shopping-list.xml lub wysłanie zapytania w formie JSON (również <strong>CREATE</strong>) pod ten sam adres lecz z rozszerzeniem json.</p>
<p>Po wywołaniu tej metody zostajemy automatycznie przekierowani pod adres <em>http://example.com/shopping-list/ID.xhtml</em> który wywołuje metodę show.<br />
Strona z listą zakupów prezentuje się jak poniżej:</p>
<div id="attachment_1376" class="wp-caption aligncenter" style="width: 310px"><a href="http://www1.darekzon.com/wp-content/uploads/2011/09/Shopping-list-Testowa-1.jpg" rel="lightbox[1366]"><img class="size-medium wp-image-1376" title="Shopping list - Testowa-1" src="http://www1.darekzon.com/wp-content/uploads/2011/09/Shopping-list-Testowa-1-300x230.jpg" alt="" width="300" height="230" /></a><p class="wp-caption-text">Lista zakupowa</p></div>
<pre class="brush: java; title: ; notranslate">

public HttpHeaders show(){
 if(this.list == null){
 returnnew DefaultHttpHeaders(&quot;notfound&quot;).withStatus(404);
 }
 returnnew DefaultHttpHeaders(&quot;show&quot;).withStatus(200);
 }
</pre>
<p>W metodzie tej sprawdzamy jedynie czy lista istnieje, jeśli nie, generujemy informację o braku listy (jak w metodzie index) oraz zwracamy status 404 (<strong>NOT FOUND</strong>), w innym przypadku wyświetlamy listę oraz zwracamy status 200 (OK).</p>
<h4>Dodawanie produktów</h4>
<p>Dodawanie produktów następuje poprzez wysłanie formularza z nazwą produktu oraz ilością jaką chcemy kupić metodą POST do klasy ProductController co ma insynuować tworzenie nowego Produktu gdy tak naprawdę będziemy jedynie aktualizować naszą listę. Poniżej znajduje się wynik wysłania formularza.</p>
<div id="attachment_1378" class="wp-caption aligncenter" style="width: 310px"><a href="http://www3.darekzon.com/wp-content/uploads/2011/09/Dodawanie-produktu-do-listy-1.jpg" rel="lightbox[1366]"><img class="size-medium wp-image-1378" title="Dodawanie produktu do listy" src="http://www3.darekzon.com/wp-content/uploads/2011/09/Dodawanie-produktu-do-listy-1-300x150.jpg" alt="" width="300" height="150" /></a><p class="wp-caption-text">Dodawanie produktu do listy</p></div>
<p>Po dodaniu produktu wysyłamy status 204 (<strong>NO CONTENT</strong>) ponieważ nie chcemy wysyłać niczego, zamiast tego odświeżamy naszą stronę dzięki czemu dostajemy świeże dane. Gdybyśmy zamiast tego chcieli wysłać naszą listę i odświeżyć ją poprzez javascript musimy wysłać status 200 (<strong>OK</strong>)</p>
<h4>Kasowanie produktów</h4>
<p>Aby wykasować produkt z listy należy kliknąć w ikonę koszyka która pojawia się po najechaniu na nasz produkt. Po kliknięciu javascript automatycznie wyśle żądanie typu <strong>DELETE</strong> w odpowiedzi dostając status taki sam jak przy dodawaniu.</p>
<h4>Inne formaty</h4>
<p>Aby zobaczyć naszą listę zakupową w innym formacie wystarczy otworzyć stronę z rozszerzeniem XML:</p>
<div id="attachment_1379" class="wp-caption aligncenter" style="width: 310px"><a href="http://www1.darekzon.com/wp-content/uploads/2011/09/localhost_8080_shopping-list__shopping-list_4e84c6a230049d8994e8a74f.xml_.jpg" rel="lightbox[1366]"><img class="size-medium wp-image-1379" title="Lista zakupowa w formacie XML" src="http://www1.darekzon.com/wp-content/uploads/2011/09/localhost_8080_shopping-list__shopping-list_4e84c6a230049d8994e8a74f.xml_-300x189.jpg" alt="" width="300" height="189" /></a><p class="wp-caption-text">Lista zakupowa w formacie XML</p></div>
<p>bądź JSON:</p>
<div id="attachment_1380" class="wp-caption aligncenter" style="width: 310px"><a href="http://www1.darekzon.com/wp-content/uploads/2011/09/localhost_8080_shopping-list__shopping-list_4e84c6a230049d8994e8a74f.json_.jpg" rel="lightbox[1366]"><img class="size-medium wp-image-1380" title="Lista zakupowa w formacie JSON" src="http://www1.darekzon.com/wp-content/uploads/2011/09/localhost_8080_shopping-list__shopping-list_4e84c6a230049d8994e8a74f.json_-300x189.jpg" alt="" width="300" height="189" /></a><p class="wp-caption-text">Lista zakupowa w formacie JSON</p></div>
<p>Dzięki temu możemy zintegrować naszą aplikację z aplikacjami zewnętrznymi bez zbędnego nakładu pracy.</p>
<h4>Podobne tematy</h4>
<ol>
<li>Podobny tutorial: <a title="Struts2 rest web app" href="http://www.zulutown.com/blog/2009/01/28/rest-web-application-with-struts21-rest-and-convention-plugins/" target="_blank">http://www.zulutown.com/blog/2009/01/28/rest-web-application-with-struts21-rest-and-convention-plugins/</a></li>
<li>Hypertext Transfer Protocol: <a title="Hypertext Transfer Protocol" href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" target="_blank">http://www.w3.org/Protocols/rfc2616/rfc2616.html</a></li>
<li>Nieco krytycznie o REST: <a title="Rest to zuo" href="http://michalorman.pl/blog/2011/02/bullshit-bingo-rest-i-restful/" target="_blank">http://michalorman.pl/blog/2011/02/bullshit-bingo-rest-i-restful/</a></li>
<li>Prezentacja na temat REST: <a title="Usługi sieciowe REST" href="https://www.soa.edu.pl/c/document_library/get_file?uuid=46b0faf6-6743-4184-ab16-dbddfd413685&amp;groupId=10122" target="_blank">https://www.soa.edu.pl/c/document_library/get_file?uuid=46b0faf6-6743-4184-ab16-dbddfd413685&amp;groupId=10122</a></li>
</ol>
<div class="shr-publisher-1366"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/09/prosta-aplikacja-restful-w-struts2-convention-i-rest-plugin-guice-i-mongodb/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nauka wielozadaniowości z IBM</title>
		<link>http://darekzon.com/2011/09/nauka-wielozadaniowosci-z-ibm</link>
		<comments>http://darekzon.com/2011/09/nauka-wielozadaniowosci-z-ibm#comments</comments>
		<pubDate>Sun, 18 Sep 2011 18:09:27 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[kurs]]></category>
		<category><![CDATA[wątki]]></category>
		<category><![CDATA[wielowątkowość]]></category>
		<category><![CDATA[współbierzność]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1359</guid>
		<description><![CDATA[Jakiś czas temu IBM wypuścił mały poradnik jak tworzyć aplikacje wielozadaniowe, co zrobić by uchronić się przed deadlock-ami, co zrobić by nie stracić wydajności naszej aplikacji. Wszystko to napisane przystępnym językiem wraz z masą przykładowego kodu. Kurs dostępny jest pod adrese,: http://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.html?ca=drs-]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Jakiś czas temu IBM wypuścił mały poradnik jak tworzyć aplikacje wielozadaniowe, co zrobić by uchronić się przed deadlock-ami, co zrobić by nie stracić wydajności naszej aplikacji.<br />
Wszystko to napisane przystępnym językiem wraz z masą przykładowego kodu.</p>
<p>Kurs dostępny jest pod adrese,: <a title="Java concurrency - IBM" href="http://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.html?ca=drs-" target="_blank">http://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.html?ca=drs-</a></p>
<div class="shr-publisher-1359"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/09/nauka-wielozadaniowosci-z-ibm/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wysyłanie wiadomości w Javie: JavaMail i Gmail</title>
		<link>http://darekzon.com/2011/09/wysylanie-wiadomosci-w-javie-javamail-i-gmail</link>
		<comments>http://darekzon.com/2011/09/wysylanie-wiadomosci-w-javie-javamail-i-gmail#comments</comments>
		<pubDate>Sun, 11 Sep 2011 10:53:18 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javax.mail]]></category>
		<category><![CDATA[mail]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1353</guid>
		<description><![CDATA[Bardzo często chcemy aby nasza aplikacja miała możliwość wysyłania maili, czy to aby wysłać mail aktywacyjny dla nowo zarejestrowanych użytkowników czy też w postaci formularza kontaktowego. Na szczęście biblioteki Java zawierają w sobie klasy dzięki którym bardzo łatwo osiągniemy nasz &#8230; <a href="http://darekzon.com/2011/09/wysylanie-wiadomosci-w-javie-javamail-i-gmail">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Bardzo często chcemy aby nasza aplikacja miała możliwość wysyłania maili, czy to aby wysłać mail aktywacyjny dla nowo zarejestrowanych użytkowników czy też w postaci formularza kontaktowego. Na szczęście biblioteki Java zawierają w sobie klasy dzięki którym bardzo łatwo osiągniemy nasz cel. Jeśli nie mamy własnego serwera który odpowiedzialnyby był za wysyłanie poczty możemy użyć do tego celu serwerów Google i usługi Gmail.</p>
<p><span id="more-1353"></span></p>
<p>Aby wysyłać maile w aplikacjach javowych potrzebujemy biblioteki Javax Mail, możemy ją dodać poprzez zależności w maven-ie:</p>
<pre class="brush: xml; title: ; notranslate">

&lt;dependency&gt;

&lt;groupId&gt;javax.mail&lt;/groupId&gt;

&lt;artifactId&gt;mail&lt;/artifactId&gt;

&lt;version&gt;1.4.1&lt;/version&gt;

&lt;type&gt;jar&lt;/type&gt;

&lt;scope&gt;compile&lt;/scope&gt;

&lt;/dependency&gt;
</pre>
<p>lub pobierając ze <a title="Oracle JavaxMail" href="http://www.oracle.com/technetwork/java/javamail/index.html">strony projektu</a>.</p>
<p>Po pobraniu i dołączeniu bibliotek do naszego projektu musimy skonfigurować połączenie z serwerem smtp (odpowiedzialnym za wysyłanie maili), aby to zrobić tworzymy plik konfiguracyjny.</p>
<p>Plik &#8222;<em>mail.properties</em>&#8221; zawierający ustawienia umieszczamy w folderze głównym zawierającym źródła tak aby był łatwy do znalezienia, jego zawartość powinna wyglądać następująco:</p>
<pre class="brush: plain; title: ; notranslate">
mail.smtp.host= smtp.gmail.com
mail.smtp.port= 587
mail.smtp.auth= true
mail.smtp.starttls.enable = true
mail.smtp.quitwait= false
mail.user= username
mail.password = password
mail.encoding= &quot;utf8&quot;
mail.debug= false
</pre>
<p>W powyższym pliku ustawiamy host, port oraz dane autoryzacyjne. Opcja <em>mail.smtp.starttls.enable=true</em> wymusza na aplikacji aby używała operacji <strong><em>StartTLS</em></strong> która to ustanawia szyfrowanie <strong>TLS</strong> w połączeniu sieciowym.<br />
Opcja <em>mail.smtp.quitwait</em> odpowiada za rozłączanie się z serwerem, w normalnych warunkach, nasza aplikacja wysyła polecenie <strong>QUIT</strong> i czeka na potwierdzenie rozłączenia, my nie musimy czekać, więc zaraz po wysłaniu polecenia rozłączamy się od serwera.<br />
Mając plik konfiguracyjny potrzebujemy kodu który go wczyta i utworzy sesje mailową która odpowiada za wysłanie wiadomości., robimy to wykorzystując mechanizmy Javy a dokładniej klasę Properties</p>
<pre class="brush: java; title: ; notranslate">

Properties properties = new Properties();

try {

properties.load(this.getClass().getResourceAsStream(&quot;/mail.properties&quot;));
} catch (IOException e) {
e.printStackTrace();
 throw new RuntimeException(&quot;Fatal error&quot;);
}
</pre>
<p>Jeśli mamy wczytane ustawienia możemy przejść do wysyłania maila. Aby to zrobić tworzymy nową sesję (połączenie z serwerem smtp) oraz wiadomość.</p>
<p><span class="Apple-style-span" style="font-family: Consolas, Monaco, monospace; font-size: 12px; line-height: 18px; white-space: pre;">
<pre class="brush: java; title: ; notranslate">&lt;/span&gt;
&lt;pre&gt;
Session session = Session.getInstance(properties);

MimeMessage mm = new MimeMessage(session);

try {
    mm.setFrom(new InternetAddress(properties.getProperty(&quot;ADRES_NADAWCY@example.com&quot;),properties.get Property(&quot;NAZWA_NADAWCY&quot;)));
    mm.setRecipient(Message.RecipientType.TO, new InternetAddress(&quot;ADRES_ODBIORCY@example.com&quot;,&quot;NAZWA_ODBIORCY&quot;));
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

mm.setText(&quot;WIADOMOSC&quot;);
mm.setSubject(&quot;TEMAT_MAILA&quot;);
Transport t = session.getTransport(&quot;smtp&quot;);
t.connect(this.getProperty(&quot;mail.user&quot;),this.getProperty(&quot;mail.password&quot;));
t.sendMessage(mm, mm.getAllRecipients());
</pre>
<p>Wszystko powinno działać od ręki, z tego co pamiętam, Gmail ma ograniczenie do 500 maili dziennie (w darmowej usłudze) o czym trzeba pamiętać, choć możliwe, że już się to zmieniło.</p>
<div class="shr-publisher-1353"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/09/wysylanie-wiadomosci-w-javie-javamail-i-gmail/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gosling odchodzi z Google</title>
		<link>http://darekzon.com/2011/08/gosling-odchodzi-z-google</link>
		<comments>http://darekzon.com/2011/08/gosling-odchodzi-z-google#comments</comments>
		<pubDate>Wed, 31 Aug 2011 19:58:17 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Inne javove]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[gosling]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[sun]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1341</guid>
		<description><![CDATA[Jak podają chyba wszystkie zagraniczne blogi twórca Javy James Gosling opuścił firmę Google (do której przeszedł po przejęciu Sun-a przez Oracle). Jak głosza plotki pan Gosling zajął stanowisko głównego architekta oprogramowania w firmie Liquid Robotics która zajmuje się tworzeniem robotów oceanicznych. &#8230; <a href="http://darekzon.com/2011/08/gosling-odchodzi-z-google">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Jak podają chyba wszystkie zagraniczne blogi twórca Javy James Gosling opuścił firmę Google (do której przeszedł po przejęciu Sun-a przez Oracle). Jak głosza plotki pan Gosling zajął stanowisko głównego architekta oprogramowania w firmie <a title="Strona firmy Liquid Robotics" href="http://liquidr.com/" target="_blank">Liquid Robotics</a> która zajmuje się tworzeniem robotów oceanicznych.</p>
<p>Więcej możecie przeczytać w źródłach:</p>
<ol>
<li><a title="Java founder Gosling leaves google" href="http://www.infoworld.com/d/the-industry-standard/java-founder-gosling-leaves-google-startup-171199" target="_blank">Infoworld - Java founder Gosling leaves Google for startup<br />
</a></li>
<li><a title="Java founder Gosling leaves google" href="http://liquidr.com/files/2011/08/JamesGosling_8_30_11.pdf&quot;" target="_blank">Liquid Robotics &#8211; James Gosling joins Liquid Robotics</a></li>
</ol>
<div class="shr-publisher-1341"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/08/gosling-odchodzi-z-google/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jak Twitter przenosi się do JVM</title>
		<link>http://darekzon.com/2011/08/jak-twitter-przenosi-sie-do-jvm</link>
		<comments>http://darekzon.com/2011/08/jak-twitter-przenosi-sie-do-jvm#comments</comments>
		<pubDate>Tue, 02 Aug 2011 08:43:06 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Chmury]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1335</guid>
		<description><![CDATA[Jakiś czas temu pisałem o przenosinach Twittera do JVM. Tym razem prezentuję film z udziałem Raffiego Krikoriana który pracuje w Twitterze. Opowiada o tym jak przenosili się z Ruby do JVM.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Jakiś czas temu pisałem o przenosinach <a title="Twitter przenosi się do JVM" href="http://darekzon.com/2011/07/twitter-przenosi-sie-do-jvm" target="_blank">Twittera do JVM</a>. Tym razem prezentuję film z udziałem Raffiego Krikoriana który pracuje w Twitterze. Opowiada o tym jak przenosili się z Ruby do JVM.<span id="more-1335"></span></p>
<p><iframe src="http://www.youtube.com/embed/ohHdZXnsNi8?hd=1" frameborder="0" width="640" height="390"></iframe></p>
<div class="shr-publisher-1335"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/08/jak-twitter-przenosi-sie-do-jvm/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Błędy w JVM 7, zaleca się wstrzymanie przed migracją</title>
		<link>http://darekzon.com/2011/07/bledy-w-jvm-7-zaleca-sie-wstrzymanie-przed-migracja</link>
		<comments>http://darekzon.com/2011/07/bledy-w-jvm-7-zaleca-sie-wstrzymanie-przed-migracja#comments</comments>
		<pubDate>Sun, 31 Jul 2011 14:27:21 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[apache lucene]]></category>
		<category><![CDATA[apache solr]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[hotspot]]></category>
		<category><![CDATA[hotspot server]]></category>
		<category><![CDATA[java 7]]></category>
		<category><![CDATA[jvm]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1330</guid>
		<description><![CDATA[Nad maszyną wirtualną javy zebrały się czarne chmury (a może raczej obłoczki). Jak się okazuje 7 wersja maszyny wirtualnej Javy (chodzi o wersję HotSpot Server wydanej zaledwie kilka dni temu) zawiera trzy niepokojące błędy, które zostały odkryte przez programistów związanych &#8230; <a href="http://darekzon.com/2011/07/bledy-w-jvm-7-zaleca-sie-wstrzymanie-przed-migracja">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Nad maszyną wirtualną javy zebrały się czarne chmury (a może raczej obłoczki). Jak się okazuje 7 wersja maszyny wirtualnej Javy (chodzi o wersję HotSpot Server wydanej zaledwie kilka dni temu) zawiera trzy niepokojące błędy, które zostały odkryte przez programistów związanych z fundacją <a title="Fundacja Apache" href="http://apache.org/" target="_blank">Apache</a> (pracującymi nad projektami <a title="Projekt Apache Solr" href="http://lucene.apache.org/solr/" target="_blank">Apache Solr</a> oraz <a title="Projekt Apache Lucene" href="http://lucene.apache.org/" target="_blank">Apache Lucene)</a>.<span id="more-1330"></span></p>
<p>Błędy (<a title="Awaria maszyny wirtualnej z błędem sigsegv" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7070134" target="_blank">7070134</a>, <a title="Błędna optymalizacja rozwijania pętli" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7044738" target="_blank">7044738 </a>i <a title="Błąd optymalizacj pętli" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7068051" target="_blank">7068051</a>) mogą doprowadzić do awarii maszyny wirtualnej lub złych obliczeń.</p>
<p><a title="Błędna optymalizacja pętli w JVM 7" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7070134" target="_blank">Pierwszy błąd</a> dotyczy błędnej optymalizacji pętli wykonywanej przez kompilator. Optymalizacja (włączona domyślnie) może być wyłączona przez podanie argumentu:</p>
<pre class="brush: bash; title: ; notranslate">
-XX:-UseLoopPredicate
</pre>
<p><a title="Błędna optymalizacja rozwijania pętli" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7044738" target="_blank">Błąd nr. dwa</a> dotyczy optymalizacji rozwijania pętli która spowodować może zwrócenie błędnych wyników.<br />
W pewnych rzadkich sytuacjach, gdy kompilator wykona <a title="On-Stack Replacement - przykład" href="http://java.sun.com/developer/technicalArticles/Networking/HotSpot/onstack.html" target="_blank">OSR</a> (podmiany na stosie) dla zagnieżdżonej pętli może dojść do duplikacji która zamieni wyniki obliczeń. Aby uporać się z tym błędem trzeba dodać argument:</p>
<pre class="brush: bash; title: ; notranslate">

-XX:LoopUnrollLimit=1
</pre>
<p><a title="Błąd optymalizacji pętli" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7068051" target="_blank">Ostatni błąd</a> również dotyczy optymalizacji pętli i dostał się do JVM wraz z nową <a title="Klonowanie predykatów pętli" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7004535" target="_blank">funkcją</a> optymalizatora.</p>
<p>Ludzie z Organizacji Apache radzą by do czasu naprawienia w/w błędów nie migrować do nowej wersji JVM. Oracle zapowiedziało usunięcie błędów w najbliższej łacie serwisowej.</p>
<p>&nbsp;</p>
<p>Źródła:</p>
<ol>
<li><a title="Ostrzeżenie Apache ws. błędów JVM v7" href="http://lucene.apache.org/#28+July+2011+-+WARNING%3A+Index+corruption+and+crashes+in+Apache+Lucene+Core+%2F+Apache+Solr+with+Java+7 " target="_blank">http://lucene.apache.org/#28+July+2011+-+WARNING%3A+Index+corruption+and+crashes+in+Apache+Lucene+Core+%2F+Apache+Solr+with+Java+7<br />
</a></li>
<li><a title="Nie używaj Javy 7" href="http://blog.eisele.net/2011/07/dont-use-java-7-are-you-kidding-me.html" target="_blank">http://blog.eisele.net/2011/07/dont-use-java-7-are-you-kidding-me.html</a></li>
<li><a title="Apache i Oracle ostrzegają o błędach w JVM7" href="http://www.infoworld.com/t/java-programming/apache-and-oracle-warn-serious-java-7-compiler-bugs-168516" target="_blank">http://www.infoworld.com/t/java-programming/apache-and-oracle-warn-serious-java-7-compiler-bugs-168516</a></li>
</ol>
<div class="shr-publisher-1330"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/07/bledy-w-jvm-7-zaleca-sie-wstrzymanie-przed-migracja/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google+ zaproszenia</title>
		<link>http://darekzon.com/2011/07/google-zaproszenia</link>
		<comments>http://darekzon.com/2011/07/google-zaproszenia#comments</comments>
		<pubDate>Wed, 20 Jul 2011 11:29:25 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[google+ google]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1297</guid>
		<description><![CDATA[Z racji, że ostatnio nie mam zbyt dużo czasu na nowe wpisy w ramach przeprosin postanowiłem zrobić akcję Google+, jeśli ktoś jeszcze nie ma jeszcze konta może zostawić swój mail (podpięty do Google Account) w komentarzu (w formie rozczytywalnej dla &#8230; <a href="http://darekzon.com/2011/07/google-zaproszenia">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Z racji, że ostatnio nie mam zbyt dużo czasu na nowe wpisy w ramach przeprosin postanowiłem zrobić akcję Google+, jeśli ktoś jeszcze nie ma jeszcze konta może zostawić swój mail (podpięty do Google Account) w komentarzu (w formie rozczytywalnej dla mnie).</p>
<p>Komentarze po wysłaniu zaproszenia będą kasowane.</p>
<p>Uwaga!</p>
<p>Google raz na jakiś czas zawiesza napływ nowych ludzi, więc może się to przeciągnąć w czasie.</p>
<p>PS. Jak już będziecie mieć konto, możecie splusować wpis ;)</p>
<p>&nbsp;</p>
<p>PS 2. Zapraszanie zakończone, mam nadzieję, że wszyscy którzy się zgłosili dostali już konta.</p>
<div class="shr-publisher-1297"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/07/google-zaproszenia/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Twitter przenosi się do JVM</title>
		<link>http://darekzon.com/2011/07/twitter-przenosi-sie-do-jvm</link>
		<comments>http://darekzon.com/2011/07/twitter-przenosi-sie-do-jvm#comments</comments>
		<pubDate>Mon, 04 Jul 2011 21:41:43 +0000</pubDate>
		<dc:creator>darek</dc:creator>
				<category><![CDATA[Inne javove]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[hadoop]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://darekzon.com/?p=1292</guid>
		<description><![CDATA[Twitter to chyba największa strona napisana w języku Ruby (framework Ruby On Rails), a na pewno największa jeśli chodzi o moc obliczeniową jaką potrzebuje do codziennej pracy. Można powiedzieć, że była oczkiem w głowie programistów Ruby, jako argument, iż język &#8230; <a href="http://darekzon.com/2011/07/twitter-przenosi-sie-do-jvm">kontynuuj czytanie <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a title="Twitter" href="http://Twitter" target="_blank">Twitter</a> to chyba największa strona napisana w języku Ruby (framework Ruby On Rails), a na pewno największa jeśli chodzi o moc obliczeniową jaką potrzebuje do codziennej pracy. Można powiedzieć, że była oczkiem w głowie programistów Ruby, jako argument, iż język jest dojrzały i bardzo dobry jeśli chodzi o poważne zastosowania. Jednak od jakiegoś czasu ktoś wyjątkowo wytrwale dłubie w tym oku, tym kimś jest nie kto inny jak sam Twitter który powoli przenosi swój kod do języków uruchamianych w JVM.<span id="more-1292"></span></p>
<p>Wszystko zaczeło się jeszcze w 2010 roku kiedy to Twitter ogłosił, że programiści przepisali w języku <a title="Język Scala" href="http://www.scala-lang.org/" target="_blank">Scala</a> silnik kolejkowania oraz magazynowania wiadomości.<br />
W kwietniu tego roku zmieniony został mechanizm składowania indeksów wyszukiwarki, od teraz za indeksowanie odpowiada <a title="Wyszukiwarka Lucene" href="http://lucene.apache.org/" target="_blank">Lucene</a> dzięki czemu opóźnienie podczas wyszukiwania skróciło się trzykrotnie a przepustowość wzrosła dziesięciokrotnie, <a title="Aktualizacja wyszukwiarki Twittera" href="http://engineering.twitter.com/2011/05/engineering-behind-twitters-new-search.html" target="_blank">front-end wyszukiwarki również został zaktualizowany</a>, od teraz zamiast Ruby On Rails wykorzystywany jest  mechanizm <a title="Twitter search is now 3 times faster" href="http://engineering.twitter.com/2011/04/twitter-search-is-now-3x-faster_1656.html" target="_blank">Blender</a> (oparty o framework <a title="Netty" href="http://www.jboss.org/netty">JBoss Netty</a>).<br />
Od kuchni Twitter do składowania danych używa bazy MySQL oraz rozproszonej bazy danych <a title="Cassandra - rozproszona baza danych" href="http://cassandra.apache.org/" target="_blank">Cassandry</a>. Do przetwarzania offline, używany jest <a title="Przetwarzanie - Hadoop" href="http://hadoop.apache.org/" target="_blank">Hadoop</a> który ciągle zyskuje coraz większą popularność.</p>
<p>Powyższe zmiany w architekturze Twittera mogą świadczyć iż choć Ruby jest już językiem dojrzałym to nie nadaje się do projektów wymagających wysokiej wydajności o skalowalności (szczególnie jeśli chcemy zmniejszyć koszty działania).<br />
Sam Twitter jest również niezłym laboratorium z którego wyników można czerpać garściami, z pewnością polecam obserwowanie dalszego rozwoju akcji.</p>
<p>Źródło:</p>
<ol>
<li><a title="InfoQ - JVM w twitterze" href="http://www.infoq.com/articles/twitter-java-use" target="_blank">http://www.infoq.com/articles/twitter-java-use</a></li>
<li> <a title="Twitter blog" href="http://engineering.twitter.com" target="_blank">http://engineering.twitter.com</a></li>
</ol>
<div class="shr-publisher-1292"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://darekzon.com/2011/07/twitter-przenosi-sie-do-jvm/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

