<?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:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-6443533180962722149</atom:id><lastBuildDate>Sun, 08 Nov 2009 20:52:47 +0000</lastBuildDate><title>Na Jawie - czyli co w trjawie piszczy...</title><description /><link>http://na-jawie.blogspot.com/</link><managingEditor>noreply@blogger.com (MZ)</managingEditor><generator>Blogger</generator><openSearch:totalResults>44</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/NaJawie" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-5146264231178395528</guid><pubDate>Sat, 31 Oct 2009 21:29:00 +0000</pubDate><atom:updated>2009-10-31T15:54:22.260-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">testy wydajnościowe</category><title>O testach wydajnościowych słów kilka</title><description>Testy wydajnościowe, jak to testy... robić trzeba. Jak to pisze &lt;a href="http://misko.hevery.com/"&gt;Misko&lt;/a&gt;: &lt;a href="http://misko.hevery.com/2009/09/16/checked-exceptions-i-love-you-but-you-have-to-go/"&gt;You do test, right?&lt;/a&gt; Zazwyczaj aby je przeprowadzić korzystałem z &lt;a href="http://jakarta.apache.org/jmeter/"&gt;Apache JMeter&lt;/a&gt;. Polecam ten program i może nawet kiedyś zamieszczę prosty przewodnik, jak zacząć z nim przygodę. Dzisiaj jednak skupię się na  innym problemie i innym narzędziu.&lt;br /&gt;Przeprowadzając testy wydajnościowe, najważniejszym w moim odczucie problemem, z jakim się spotyka osoba pisząca test jest odwzorowanie charakterystyki żądań obsługiwanych przez aplikację. Tak przy okazji, wiedzieliście, że aplikacja to "&lt;a href="http://www.sjp.pl/co/aplikacja"&gt;ozdobny wzór naszywany na tło z innego materiału&lt;/a&gt;"? A spieszyć to "&lt;a href="http://www.sjp.pl/co/spieszy%C4%87"&gt;uczynić kogoś pieszym&lt;/a&gt;" Coraz bardziej lubię słowniki.&lt;br /&gt;&lt;br /&gt;A priori trudno określić, jak użytkownicy będą korzystać z naszego programu i w co będą klikać. Kiedy będą żądane obrazki, kiedy pliki css i różne inne. Obserwując jednak to, co się dzieje na serwerze, możemy utworzyć całkiem sprawne scenariusze.&lt;br /&gt;&lt;br /&gt;A co się dzieje, możemy odczytać z logów. Zakładam tutaj, że ruch sieciowy obsługiwany jest przez serwer &lt;a href="http://httpd.apache.org/"&gt;WWW Apache&lt;/a&gt;, za którym stoi serwer aplikacji, z naszą aplikacją internetową.&lt;br /&gt;Apache trzyma informacje o tym kto i do jakich zasobów wysyła żądania w pliku &lt;span class="pre"&gt;access.log&lt;/span&gt;.&lt;br /&gt;Podglądam jego zawartość poleceniem &lt;br /&gt;&lt;span class="pre"&gt;tail -f /var/logs/apache2/access.log&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: shell"&gt;&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /swiat/komentarze/_resource/fs/img/ajax_loading_small.gif HTTP/1.0" 301 284 "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/338&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /swiat/komentarze/_resource/fs/res/img-blogi.png HTTP/1.0" 301 276 "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/246&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /swiat/komentarze/_resource/res/20000457/cust/f120x80 HTTP/1.0" 200 4025 "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/1362&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /swiat/komentarze/_resource/fs/img/presseurop.png HTTP/1.0" 301 275 "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/337&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /swiat/komentarze/_resource/fs/img/polityka_logo_small.png HTTP/1.0" 301 280 "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/264&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /_resource/fs/img/close.png HTTP/1.0" 304 - "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/256&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /_resource/fs/res/img-blogi.png HTTP/1.0" 304 - "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/229&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /_resource/fs/img/presseurop.png HTTP/1.0" 304 - "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/251&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /_resource/fs/img/polityka_logo_small.png HTTP/1.0" 304 - "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/222&lt;br /&gt;83.2.107.220 - - [31/Oct/2009:23:03:08 +0100] "GET /_resource/fs/img/ajax_loading_small.gif HTTP/1.0" 304 - "http://beta.polityka.pl/swiat/komentarze/1500387,1,po-unijnym-szczycie.read" "Opera/9.80 (Windows NT 5.1; U; pl) Presto/2.2.15 Version/10.00" 0/220&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jest to bardzo cenne źródło żądań wysyłanych do aplikacji, z których stworzę scenariusz testowy. Wydobywam więc wszystkie żądania z godziny 9tej i zapisuję je w pliku &lt;span class="pre"&gt;/tmp/requests.txt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;&lt;br /&gt;cat /var/log/apache2/access.log | grep 31/Oct/2009:09 | awk '{print $7}' &gt; /tmp/requests.txt&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I już jestem w ogródku. Czas przywitać się z gąską...&lt;br /&gt;Pozostało jakoś z pliku o strukturze:&lt;br /&gt;&lt;pre class="brush: shell"&gt;&lt;br /&gt;/swiat/komentarze/_resource/fs/img/ajax_loading_small.gif&lt;br /&gt;/swiat/komentarze/_resource/fs/res/img-blogi.png&lt;br /&gt;/swiat/komentarze/_resource/res/20000457/cust/f120x80&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;wykonać żądania do poszczególnych zasobów. &lt;br /&gt;&lt;br /&gt;Tu z pomocą przychodzi program &lt;a href="http://httpd.apache.org/docs/2.0/programs/ab.html"&gt;Apache Benchmark&lt;/a&gt; i kilka poleceń linuksowych.&lt;br /&gt;&lt;br /&gt;Odpalam więc scenariusz poleceniem:&lt;br /&gt;&lt;span class="pre"&gt;for i in $(cat /tmp/requests.txt);do ab -n 2 -c 2 "http://nazwahosta$i"; done&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;-n 2&lt;/span&gt; odpali każde żądanie 2 razy&lt;br /&gt;&lt;span class="pre"&gt;-c 2&lt;/span&gt; zrobi to w 2 wątkach&lt;br /&gt;&lt;br /&gt;Dobre efekty daje odpalenie kilku scenariuszy testowych, np. z godziny 8, 9, 10, 11, zrównoleglonych &lt;a href="http://pl.wikipedia.org/wiki/GNU_Screen"&gt;screenem&lt;/a&gt;, czyli&lt;br /&gt;&lt;span class="pre"&gt;screen for i in $(cat /tmp/requests.txt);do ab -n 2 -c 2 "http://nazwahosta$i"; done&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A jakie są twoje patenty, na testy wydajnościowe?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-5146264231178395528?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/OTG_taDanpY/o-testach-wydajnosciowych-sow-kilka.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/10/o-testach-wydajnosciowych-sow-kilka.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-5995395410908515800</guid><pubDate>Sat, 15 Aug 2009 12:35:00 +0000</pubDate><atom:updated>2009-08-16T02:03:46.881-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">soft reference</category><category domain="http://www.blogger.com/atom/ns#">java</category><category domain="http://www.blogger.com/atom/ns#">weak reference</category><title>Słabe referencje... z czym to się je?</title><description>Dzisiaj święto Wojska Polskiego. Parady wojskowej nie będzie z powodu kryzysu, ale sklepy (z zupełnie zresztą innego powodu) pozamykane. A jeść trzeba...&lt;br /&gt;&lt;br /&gt;Może skuszę się na słabą referencję... ale z czym to się je?&lt;br /&gt;&lt;br /&gt;Referencja jak referencja, spotkał się z nią każdy:&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;String string = new String("123");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Słaba referencja wygląda trochę inaczej&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;Reference&amp;lt;String&amp;gt; refString = new WeakReference&amp;lt;String&amp;gt;(new String("123"));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;a dostęp do obiektu, na który referencja wskazuje uzyskujemy za pomocą wywołania metody &lt;span class="pre"&gt;get()&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;refString,get();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nie o wygląd jednak tutaj chodzi.&lt;br /&gt;&lt;br /&gt;Dopóki obiekt w naszym programie wskazywany jest przez zwykłą referencję, nie zostanie on usunięty z pamięci przez jakże uwielbiany przez wszystkich Garbage Collector.&lt;br /&gt;&lt;br /&gt;Natomiast obiekt wskazywany przez słabą referencję, może być usunięty przez GC jeżeli zacznie brakować pamięci, mimo, że referencja do niego cały czas jest obecna w programie. Metoda &lt;span class="pre"&gt;get()&lt;/span&gt; zwróci wtedy wartość null.&lt;br /&gt;&lt;br /&gt;Nie wierzysz?&lt;br /&gt;&lt;br /&gt;Oto krótki program obrazujący działanie słabych (i mocnych) referencji:&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;package pl.matt;&lt;br /&gt;&lt;br /&gt;import java.lang.ref.Reference;&lt;br /&gt;import java.lang.ref.WeakReference;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class WeakReferenceTest {&lt;br /&gt;&lt;br /&gt; int[] tab = new int[1024];&lt;br /&gt; &lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  // zwykła referencja&lt;br /&gt;  String string = new String("123");&lt;br /&gt;  &lt;br /&gt;  // słaba referencja&lt;br /&gt;  Reference&amp;lt;String&gt; refString = new WeakReference&amp;lt;String&gt;(new String("456"));&lt;br /&gt;  &lt;br /&gt;  System.out.println(string);&lt;br /&gt;  System.out.println(refString.get());&lt;br /&gt;  &lt;br /&gt;  java.util.List&amp;lt;WeakReferenceTest&gt; list = new ArrayList&amp;lt;WeakReferenceTest&gt;();&lt;br /&gt;  &lt;br /&gt;  for (int i = 0; i &amp;lt; 1000000; i++) {&lt;br /&gt;   WeakReferenceTest test = new WeakReferenceTest();&lt;br /&gt;   list.add(test);&lt;br /&gt;   if (refString.get() == null) {&lt;br /&gt;    System.out.println(string);&lt;br /&gt;    System.out.println(i + " " + refString.get());&lt;br /&gt;    break;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Program w pętli przydziela pamięć tworząc nowe obiekty klasy &lt;span calss="pre"&gt;WeakReferenceTest()&lt;/span&gt;. W pewnym momencie zaczyna się uruchamiać Garbage Collector i usuwa z pamięci obiekt który wskazywała słaba referencja.&lt;br /&gt;&lt;br /&gt;Oprócz słabych referencji, w javie mamy jeszcze "średnio mocne" referencje &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/SoftReference.html"&gt;SoftReference&lt;/a&gt;. Zasada ich działania jest podobna, z tym, że obiekty przez nie wskazywane żyją dłużej.&lt;br /&gt;&lt;br /&gt;Obiekt wskazywany przez miękką referencję zostanie usunięty z pamięci tuż przed rzuceniem wyjątku &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/OutOfMemoryError.html"&gt;java.lang.OutOfMemoryError&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Doskonałe narzędzia, to implementacji mechanizmów pamięci podręcznej.&lt;br /&gt;&lt;br /&gt;Żeby dopełnić obrazu całości... są jeszcze referencje fantomowe &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/PhantomReference.html"&gt;PhantomReference&lt;/a&gt;. Obiekty wskazywane przez te referencje są usuwane przy każdym uruchomieniu GC, o ile nie wskazuje na nie żadna inna referencja. Można je stosować, aby mieć informację o tym, kiedy dany obiekt został usunięty z pamięci.&lt;br /&gt;&lt;br /&gt;Aż się głodny zrobiłem, czas chyba zjeść coś bardziej konkretnego.&lt;br /&gt;&lt;br /&gt;PS. Czego używacie do przeglądania RSSów? Ja jak dotąd Thunderbirda, ale ciągle szukam czegoś lepszego.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-5995395410908515800?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/o8iUOY9egDk/sabe-referencje-z-czym-to-sie-je.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">14</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/08/sabe-referencje-z-czym-to-sie-je.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-6281563841099565434</guid><pubDate>Sat, 01 Aug 2009 16:29:00 +0000</pubDate><atom:updated>2009-08-05T14:45:14.149-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">EhCache</category><category domain="http://www.blogger.com/atom/ns#">JBoss Seam</category><title>Seam z EhCache</title><description>W poprzednim wpisie wygenerowaliśmy sobie pierwszą aplikację Seamową przy pomocy wtyczki JBoss Tools.&lt;br /&gt;&lt;br /&gt;Sposób bardzo fajny do szybkiej prezentacji, ale nie oszukujmy się, jest to sposób dobry dla dziewczyn. Do poważniejszych rozwiązań się nie nadaje. &lt;br /&gt;Głównym minusem jest brak skryptu budującego aplikację, czy to antowego, czy to mavenowego.&lt;br /&gt;&lt;br /&gt;Dlatego w dzisiejszym wpisie wygenerujemy sobie prostą aplikację Seamową, przy pomocy narzędzia seam-gen. Kilka dni temu światłu dziennemu ukazał się Seam 2.2.0.GA, ale ja posłużę się wersją &lt;a href="http://sourceforge.net/project/downloading.php?group_id=22866&amp;filename=jboss-seam-2.1.1.GA.zip&amp;a=79953978"&gt;2.1.1.GA&lt;/a&gt;, głównie dlatego, że mam już ją zainstalowaną.&lt;br /&gt;&lt;br /&gt;Wchodzę zatem do katalogu, w którym zainstalowałem Seama i konfiguruję go wykonując polecenie &lt;br /&gt;&lt;span class="pre"&gt;./seam setup&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam setup&lt;br /&gt;SEAM_HOME: /opt/jboss-seam-2.1.1.GA&lt;br /&gt;Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen&lt;br /&gt;Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml&lt;br /&gt;&lt;br /&gt;init:&lt;br /&gt;&lt;br /&gt;setup:&lt;br /&gt;     [echo] Welcome to seam-gen :-)&lt;br /&gt;    [input] Enter your Java project workspace (the directory that contains your Seam projects) [/home/mateusz/priv/workspace/] [/home/mateusz/priv/workspace/]&lt;br /&gt;&lt;br /&gt;    [input] Enter your JBoss AS home directory [/opt/jboss-5.0.1.GA/] [/opt/jboss-5.0.1.GA/]&lt;br /&gt;&lt;br /&gt;    [input] Enter the project name [seam_test] [seam_test]&lt;br /&gt;&lt;br /&gt;     [echo] Accepted project name as: seam_test&lt;br /&gt;    [input] Do you want to use ICEfaces instead of RichFaces [n] (y, [n])&lt;br /&gt;&lt;br /&gt;    [input] skipping input as property icefaces.home.new has already been set.&lt;br /&gt;    [input] Select a RichFaces skin [ruby] (blueSky, classic, deepMarine, DEFAULT, emeraldTown, japanCherry, [ruby], wine)&lt;br /&gt;&lt;br /&gt;    [input] Is this project deployed as an EAR (with EJB components) or a WAR (with no EJB support) [ear] ([ear], war)&lt;br /&gt;&lt;br /&gt;    [input] Enter the Java package name for your session beans [pl.matt.session] [pl.matt.session]&lt;br /&gt;&lt;br /&gt;    [input] Enter the Java package name for your entity beans [pl.matt.model] [pl.matt.model]&lt;br /&gt;&lt;br /&gt;    [input] Enter the Java package name for your test cases [pl.matt.test] [pl.matt.test]&lt;br /&gt;&lt;br /&gt;    [input] What kind of database are you using? [mysql] (hsql, [mysql], oracle, postgres, mssql, db2, sybase, enterprisedb, h2)&lt;br /&gt;&lt;br /&gt;    [input] Enter the Hibernate dialect for your database [org.hibernate.dialect.MySQLInnoDBDialect] [org.hibernate.dialect.MySQLInnoDBDialect]&lt;br /&gt;&lt;br /&gt;    [input] Enter the filesystem path to the JDBC driver jar [/opt/jboss-seam-2.1.1.GA/lib/hsqldb.jar] [/opt/jboss-seam-2.1.1.GA/lib/hsqldb.jar]&lt;br /&gt;/home/mateusz/java/lib/mysql-connector-java-5.1.7-bin.jar&lt;br /&gt;    [input] Enter JDBC driver class for your database [com.mysql.jdbc.Driver] [com.mysql.jdbc.Driver]&lt;br /&gt;&lt;br /&gt;    [input] Enter the JDBC URL for your database [jdbc:mysql:///test] [jdbc:mysql:///test]&lt;br /&gt;&lt;br /&gt;    [input] Enter database username [xxx] [xxx]&lt;br /&gt;&lt;br /&gt;    [input] Enter database password [xxx] [xxx]&lt;br /&gt;&lt;br /&gt;    [input] skipping input as property hibernate.default_schema.entered has already been set.&lt;br /&gt;    [input] Enter the database catalog name (it is OK to leave this blank) [] []&lt;br /&gt;&lt;br /&gt;    [input] Are you working with tables that already exist in the database? [n] (y, [n])&lt;br /&gt;&lt;br /&gt;    [input] Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n])&lt;br /&gt;&lt;br /&gt;   [delete] Deleting: /opt/jboss-seam-2.1.1.GA/seam-gen/build.properties&lt;br /&gt;[propertyfile] Creating new property file: /opt/jboss-seam-2.1.1.GA/seam-gen/build.properties&lt;br /&gt;     [echo] Installing JDBC driver jar to JBoss AS&lt;br /&gt;     [echo] Type './seam create-project' to create the new project&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;podaję ścieżki do przestrzeni roboczej, do serwera JBoss, parametry bazy danych, nazwy pakietów i inne ustawienia aplikacji.&lt;br /&gt;&lt;br /&gt;następnie tworzę projekt poleceniem &lt;br /&gt;&lt;span class="pre"&gt;./seam create-project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam create-project&lt;br /&gt;SEAM_HOME: /opt/jboss-seam-2.1.1.GA&lt;br /&gt;Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen&lt;br /&gt;Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml&lt;br /&gt;&lt;br /&gt;init:&lt;br /&gt;&lt;br /&gt;init-properties:&lt;br /&gt;     [echo] /opt/jboss-5.0.1.GA/&lt;br /&gt;&lt;br /&gt;validate-workspace:&lt;br /&gt;&lt;br /&gt;validate-project:&lt;br /&gt;&lt;br /&gt;icefaces-staging-copy:&lt;br /&gt;&lt;br /&gt;initcopy:&lt;br /&gt;&lt;br /&gt;initpoms:&lt;br /&gt;     [echo] Setting up dependencies&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;[artifact:install] [INFO] Installing /opt/jboss-seam-2.1.1.GA/classes/poms/root.pom to /home/mateusz/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;[artifact:install] [INFO] Installing /opt/jboss-seam-2.1.1.GA/classes/poms/parent.pom to /home/mateusz/.m2/repository/org/jboss/seam/parent/2.1.1.GA/parent-2.1.1.GA.pom&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;     [copy] Copying 1 file to /opt/jboss-seam-2.1.1.GA/classes/poms&lt;br /&gt;&lt;br /&gt;copyseam:&lt;br /&gt;&lt;br /&gt;copyseamdependencies:&lt;br /&gt;&lt;br /&gt;copyjbossembedded:&lt;br /&gt;&lt;br /&gt;copy-icefaces-home:&lt;br /&gt;&lt;br /&gt;copy-icefaces-maven:&lt;br /&gt;&lt;br /&gt;copy-lib:&lt;br /&gt;     [echo] Copying Seam and dependencies to the /home/mateusz/priv/workspace//seam_test/lib directory...&lt;br /&gt;     [copy] Copying 121 files to /home/mateusz/priv/workspace/seam_test/lib&lt;br /&gt;     [copy] Copied 5 empty directories to 2 empty directories under /home/mateusz/priv/workspace/seam_test/lib&lt;br /&gt;     [echo] Copying JBoss Embedded configuration to the /home/mateusz/priv/workspace//seam_test/bootstrap directory...&lt;br /&gt;     [copy] Copying 30 files to /home/mateusz/priv/workspace/seam_test/bootstrap&lt;br /&gt;&lt;br /&gt;file-copy-war:&lt;br /&gt;&lt;br /&gt;file-copy-ear:&lt;br /&gt;     [echo] Copying resources needed for EAR deployment to the /home/mateusz/priv/workspace//seam_test/resources directory...&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources/WEB-INF&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 7 files to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;&lt;br /&gt;setup-filters:&lt;br /&gt;&lt;br /&gt;file-copy:&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 11 files to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 4 files to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/.settings&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;    [mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/nbproject&lt;br /&gt;     [copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test/nbproject&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/resources&lt;br /&gt;     [copy] Copying 12 files to /home/mateusz/priv/workspace/seam_test/view&lt;br /&gt;     [copy] Copying 9 files to /home/mateusz/priv/workspace/seam_test/view&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/src/hot/pl/matt/session&lt;br /&gt;     [copy] Copying 3 files to /home/mateusz/priv/workspace/seam_test&lt;br /&gt;    [mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/src/main/pl/matt/model&lt;br /&gt;    [mkdir] Created dir: /home/mateusz/priv/workspace/seam_test/src/test/pl/matt/test&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/src/test&lt;br /&gt;&lt;br /&gt;create-project:&lt;br /&gt;     [echo] A new Seam project named 'seam_test' was created in the /home/mateusz/priv/workspace/ directory&lt;br /&gt;     [echo] Type './seam explode' and go to http://localhost:8080/seam_test&lt;br /&gt;     [echo] Eclipse Users: Import the project using File &gt; Import... &gt; Existing Projects into Workspace, set the root directory to /home/mateusz/priv/workspace/, then select the project named seam_test&lt;br /&gt;     [echo] NetBeans Users: Open the project using File &gt; Open project... and select the project folder /home/mateusz/priv/workspace//seam_test &lt;br /&gt;     [echo] IDEA Users: Open the project using File &gt; Open project... and select the file /home/mateusz/priv/workspace//seam_test/seam_test.ipr&lt;br /&gt;&lt;br /&gt;BUILD SUCCESSFUL&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i zgodnie z instrukcją &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Eclipse Users: Import the project using File &gt; Import... &gt; Existing Projects into Workspace, set the root directory to /home/mateusz/priv/workspace/, then select the project named seam_test&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;importuję projekt do Eclipsa.&lt;br /&gt;&lt;br /&gt;W pakiecie &lt;span class="pre"&gt;pl.matt.model&lt;/span&gt; tworzę klasę &lt;span class="pre"&gt;Employee&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;package pl.matt.model;&lt;br /&gt;&lt;br /&gt;import javax.persistence.Column;&lt;br /&gt;import javax.persistence.Entity;&lt;br /&gt;import javax.persistence.GeneratedValue;&lt;br /&gt;import javax.persistence.GenerationType;&lt;br /&gt;import javax.persistence.Id;&lt;br /&gt;import javax.persistence.Table;&lt;br /&gt;&lt;br /&gt;import org.hibernate.validator.Email;&lt;br /&gt;import org.hibernate.validator.Length;&lt;br /&gt;import org.hibernate.validator.Max;&lt;br /&gt;import org.hibernate.validator.Min;&lt;br /&gt;import org.hibernate.validator.NotNull;&lt;br /&gt;&lt;br /&gt;@Entity&lt;br /&gt;@Table(name="employees")&lt;br /&gt;public class Employee {&lt;br /&gt;&lt;br /&gt; @Id&lt;br /&gt; @GeneratedValue(strategy=GenerationType.IDENTITY)&lt;br /&gt; private int id; &lt;br /&gt; &lt;br /&gt; @Length(max=128)&lt;br /&gt; @NotNull&lt;br /&gt; private String name;&lt;br /&gt; &lt;br /&gt; @Column(length=128)&lt;br /&gt; @NotNull&lt;br /&gt; private String surname;&lt;br /&gt; &lt;br /&gt; @Email&lt;br /&gt; @NotNull&lt;br /&gt; @Column(length=128)&lt;br /&gt; private String email;&lt;br /&gt; &lt;br /&gt; @Min(0)&lt;br /&gt; @Max(130)&lt;br /&gt; @NotNull&lt;br /&gt; private int age;&lt;br /&gt;&lt;br /&gt; public int getId() {&lt;br /&gt;  return id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setId(int id) {&lt;br /&gt;  this.id = id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getName() {&lt;br /&gt;  return name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setName(String name) {&lt;br /&gt;  this.name = name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getSurname() {&lt;br /&gt;  return surname;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setSurname(String sureName) {&lt;br /&gt;  this.surname = sureName;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getEmail() {&lt;br /&gt;  return email;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setEmail(String email) {&lt;br /&gt;  this.email = email;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int getAge() {&lt;br /&gt;  return age;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setAge(int age) {&lt;br /&gt;  this.age = age;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i generuję do niej prostego CRUDa poleceniem&lt;br /&gt;&lt;span class="pre"&gt;./seam generate-ui&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mateusz@mateusz-laptop:/opt/jboss-seam-2.1.1.GA$ ./seam generate-ui&lt;br /&gt;SEAM_HOME: /opt/jboss-seam-2.1.1.GA&lt;br /&gt;Using seam-gen sources from: /opt/jboss-seam-2.1.1.GA/seam-gen&lt;br /&gt;Buildfile: /opt/jboss-seam-2.1.1.GA/seam-gen/build.xml&lt;br /&gt;&lt;br /&gt;init:&lt;br /&gt;&lt;br /&gt;init-properties:&lt;br /&gt;     [echo] /opt/jboss-5.0.1.GA/&lt;br /&gt;&lt;br /&gt;validate-workspace:&lt;br /&gt;&lt;br /&gt;validate-project:&lt;br /&gt;&lt;br /&gt;init-generate:&lt;br /&gt;&lt;br /&gt;generate-ui:&lt;br /&gt;     [echo] Building project 'seam_test' to generate views and controllers&lt;br /&gt;&lt;br /&gt;init:&lt;br /&gt;&lt;br /&gt;groovy.compile:&lt;br /&gt;&lt;br /&gt;groovy.copy:&lt;br /&gt;&lt;br /&gt;compile:&lt;br /&gt;&lt;br /&gt;copyclasses:&lt;br /&gt;&lt;br /&gt;jar:&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/exploded-archives/seam_test.ear/seam_test.jar/META-INF&lt;br /&gt;     [copy] Copying 1 file to /home/mateusz/priv/workspace/seam_test/exploded-archives/seam_test.ear/seam_test.jar&lt;br /&gt;[hibernate] Executing Hibernate Tool with a JPA Configuration&lt;br /&gt;[hibernate] 1. task: generic exportertemplate: view/list.xhtml.ftl&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.annotations.Version &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: Hibernate Annotations 3.3.0.GA&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: Hibernate 3.2.4.sp1&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: hibernate.properties not found&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment buildBytecodeProvider&lt;br /&gt;[hibernate] INFO: Bytecode provider name : cglib&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.cfg.Environment &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: using JDK 1.4 java.sql.Timestamp handling&lt;br /&gt;[hibernate] 2009-08-01 18:56:21 org.hibernate.ejb.Version &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: Hibernate EntityManager 3.3.1.GA&lt;br /&gt;[hibernate] 2009-08-01 18:56:22 org.hibernate.cfg.AnnotationBinder bindClass&lt;br /&gt;[hibernate] INFO: Binding entity from annotated class: pl.matt.model.Employee&lt;br /&gt;[hibernate] 2009-08-01 18:56:22 org.hibernate.cfg.annotations.EntityBinder bindTable&lt;br /&gt;[hibernate] INFO: Bind entity pl.matt.model.Employee on table employees&lt;br /&gt;[hibernate] 2009-08-01 18:56:22 org.hibernate.validator.Version &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: Hibernate Validator 3.0.0.GA&lt;br /&gt;[hibernate] 2009-08-01 18:56:22 org.hibernate.tool.Version &lt;clinit&gt;&lt;br /&gt;[hibernate] INFO: Hibernate Tools 3.2.2.GA&lt;br /&gt;[hibernate] 2. task: generic exportertemplate: view/view.xhtml.ftl&lt;br /&gt;[hibernate] 3. task: generic exportertemplate: view/view.page.xml.ftl&lt;br /&gt;[hibernate] 4. task: generic exportertemplate: view/edit.xhtml.ftl&lt;br /&gt;[hibernate] 5. task: generic exportertemplate: view/edit.page.xml.ftl&lt;br /&gt;[hibernate] 6. task: generic exportertemplate: src/EntityList.java.ftl&lt;br /&gt;[hibernate] 7. task: generic exportertemplate: view/list.page.xml.ftl&lt;br /&gt;[hibernate] 8. task: generic exportertemplate: src/EntityHome.java.ftl&lt;br /&gt;[hibernate] 9. task: generic exportertemplate: view/layout/menu.xhtml.ftl&lt;br /&gt;[javaformatter] Java formatting of 3 files completed. Skipped 0 file(s).&lt;br /&gt;     [echo] Type './seam restart' and go to http://localhost:8080/seam_test&lt;br /&gt;&lt;br /&gt;BUILD SUCCESSFUL&lt;br /&gt;Total time: 4 seconds&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Uruchamiam JBossa i wchodzę na adres:&lt;br /&gt;&lt;span class="pre"&gt;http://localhost:8080/seam_test/&lt;/span&gt;&lt;br /&gt;moim oczom ukazuje się znzna już aplikacja&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_KxCJvjRke2k/Snn3Ruf7iRI/AAAAAAAAALA/b0XAFL5hg3A/s1600-h/0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://1.bp.blogspot.com/_KxCJvjRke2k/Snn3Ruf7iRI/AAAAAAAAALA/b0XAFL5hg3A/s320/0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5366592314900449554" /&gt;&lt;/a&gt;&lt;br /&gt;Dodaję zatem jednego użytkownika&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/Snn3R-erqwI/AAAAAAAAALI/4XlbUP3h7vc/s1600-h/1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/Snn3R-erqwI/AAAAAAAAALI/4XlbUP3h7vc/s320/1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5366592319190182658" /&gt;&lt;/a&gt;&lt;br /&gt;i otwieram w trzech zakładkach. Na konsoli JBossa obserwuję zapytania SQL jakie wykonuje aplikacja:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;INFO  [STDOUT] Hibernate: &lt;br /&gt;    select&lt;br /&gt;        employee0_.id as id2_0_,&lt;br /&gt;        employee0_.age as age2_0_,&lt;br /&gt;        employee0_.email as email2_0_,&lt;br /&gt;        employee0_.name as name2_0_,&lt;br /&gt;        employee0_.surname as surname2_0_ &lt;br /&gt;    from&lt;br /&gt;        employees employee0_ &lt;br /&gt;    where&lt;br /&gt;        employee0_.id=?&lt;br /&gt;INFO  [STDOUT] Hibernate: &lt;br /&gt;    select&lt;br /&gt;        employee0_.id as id2_0_,&lt;br /&gt;        employee0_.age as age2_0_,&lt;br /&gt;        employee0_.email as email2_0_,&lt;br /&gt;        employee0_.name as name2_0_,&lt;br /&gt;        employee0_.surname as surname2_0_ &lt;br /&gt;    from&lt;br /&gt;        employees employee0_ &lt;br /&gt;    where&lt;br /&gt;        employee0_.id=?&lt;br /&gt;INFO  [STDOUT] Hibernate: &lt;br /&gt;    select&lt;br /&gt;        employee0_.id as id2_0_,&lt;br /&gt;        employee0_.age as age2_0_,&lt;br /&gt;        employee0_.email as email2_0_,&lt;br /&gt;        employee0_.name as name2_0_,&lt;br /&gt;        employee0_.surname as surname2_0_ &lt;br /&gt;    from&lt;br /&gt;        employees employee0_ &lt;br /&gt;    where&lt;br /&gt;        employee0_.id=?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jak widać, trzy razy tem sam SELECT.&lt;br /&gt;&lt;br /&gt;Zakładając, że tylko nasza aplikacja kożysta z bazy danych test, możemy się pokusić, o włączenie pamięci podręcznej drugiego poziomu, która umożliwi wyrugowanie powtarzających się zapytań.&lt;br /&gt;&lt;br /&gt;Dostawców pamięci drugiego poziomu jest &lt;a href="http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html#performance-cache"&gt;kilku&lt;/a&gt;. Ja się zdecyduję na najbardziej chyba popularny &lt;a href="http://ehcache.sourceforge.net/"&gt;EhCache&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Uzupełniam zatem spis plików &lt;span class="pre"&gt;jar&lt;/span&gt;, znajdujący się w pliku&lt;br /&gt;&lt;span class="pre"&gt;deployed-jars-ear.list&lt;/span&gt;, które chcę aby znalazły się w aplikacji ear o wpisy:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;commons-lang.jar&lt;br /&gt;commons-collections.jar&lt;br /&gt;commons-beanutils.jar&lt;br /&gt;richfaces-ui.jar&lt;br /&gt;commons-digester.jar&lt;br /&gt;commons-beanutils.jar&lt;br /&gt;commons-lang.jar&lt;br /&gt;hibernate.jar&lt;br /&gt;hibernate-all.jar&lt;br /&gt;hibernate-annotations.jar&lt;br /&gt;hibernate-commons-annotations.jar&lt;br /&gt;hibernate-entitymanager.jar&lt;br /&gt;hibernate-validator.jar&lt;br /&gt;cglib.jar&lt;br /&gt;asm.jar&lt;br /&gt;ehcache.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;w pliku &lt;br /&gt;&lt;span class="pre"&gt;persistence-dev.xml&lt;/span&gt;&lt;br /&gt;dodaję wpisy&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;property name="hibernate.cache.use_second_level_cache" value="true" /&amp;gt;&lt;br /&gt;&amp;lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Cały plik wygląda następująco:&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt; &amp;lt;!-- Persistence deployment descriptor for dev profile --&amp;gt;&lt;br /&gt;&amp;lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"&lt;br /&gt; version="1.0"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;persistence-unit name="seam_test"&amp;gt;&lt;br /&gt;  &amp;lt;provider&amp;gt;org.hibernate.ejb.HibernatePersistence&amp;lt;/provider&amp;gt;&lt;br /&gt;  &amp;lt;jta-data-source&amp;gt;java:/seam_testDatasource&amp;lt;/jta-data-source&amp;gt;&lt;br /&gt;  &amp;lt;properties&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.hbm2ddl.auto" value="update" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.show_sql" value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.format_sql" value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="jboss.entity.manager.factory.jndi.name"&lt;br /&gt;    value="java:/seam_testEntityManagerFactory" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.cache.use_second_level_cache"&lt;br /&gt;    value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" /&amp;gt;&lt;br /&gt;  &amp;lt;/properties&amp;gt;&lt;br /&gt; &amp;lt;/persistence-unit&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/persistence&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;natomiast klasę Employee dekoruję adnotacją&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i restartuję aplikację.&lt;br /&gt;Start serwera kończy się komunikatem błędu:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=seam_test.ear/seam_test.jar#seam_test state=Create&lt;br /&gt;java.lang.IllegalArgumentException: Cache name cannot contain '/' characters.&lt;br /&gt; at net.sf.ehcache.Cache.setName(Cache.java:1272)&lt;br /&gt; at net.sf.ehcache.CacheManager.addCache(CacheManager.java:501)&lt;br /&gt; at org.hibernate.cache.EhCacheProvider.buildCache(EhCacheProvider.java:87)&lt;br /&gt; at org.hibernate.cache.CacheFactory.createCache(CacheFactory.java:61)&lt;br /&gt; at org.hibernate.impl.SessionFactoryImpl.&lt;init&gt;(SessionFactoryImpl.java:214)&lt;br /&gt; at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)&lt;br /&gt; at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:915)&lt;br /&gt; at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:730)&lt;br /&gt; at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:127)&lt;br /&gt; at org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:301)&lt;br /&gt; at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br /&gt; at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)&lt;br /&gt; at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)&lt;br /&gt; at java.lang.reflect.Method.invoke(Method.java:597)&lt;br /&gt; at org.jboss.reflect.plugins.introspection.ReflectionUtils.invoke(ReflectionUtils.java:59)&lt;br /&gt; at org.jboss.reflect.plugins.introspection.ReflectMethodInfoImpl.invoke(ReflectMethodInfoImpl.java:150)&lt;br /&gt; at org.jboss.joinpoint.plugins.BasicMethodJoinPoint.dispatch(BasicMethodJoinPoint.java:66)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.KernelControllerContextAction$JoinpointDispatchWrapper.execute(KernelControllerContextAction.java:241)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.ExecutionWrapper.execute(ExecutionWrapper.java:47)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchExecutionWrapper(KernelControllerContextAction.java:109)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchJoinPoint(KernelControllerContextAction.java:70)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.LifecycleAction.installActionInternal(LifecycleAction.java:221)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction(InstallsAwareAction.java:54)&lt;br /&gt; at org.jboss.kernel.plugins.dependency.InstallsAwareAction.installAction(InstallsAwareAction.java:42)&lt;br /&gt; at org.jboss.dependency.plugins.action.SimpleControllerContextAction.simpleInstallAction(SimpleControllerContextAction.java:62)&lt;br /&gt; at org.jboss.dependency.plugins.action.AccessControllerContextAction.install(AccessControllerContextAction.java:71)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractControllerContextActions.install(AbstractControllerContextActions.java:51)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1598)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:934)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1062)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:984)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:774)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:540)&lt;br /&gt; at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(BeanMetaDataDeployer.java:121)&lt;br /&gt; at org.jboss.deployers.vfs.deployer.kernel.BeanMetaDataDeployer.deploy(BeanMetaDataDeployer.java:51)&lt;br /&gt; at org.jboss.deployers.spi.deployer.helpers.AbstractSimpleRealDeployer.internalDeploy(AbstractSimpleRealDeployer.java:62)&lt;br /&gt; at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(AbstractRealDeployer.java:50)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:171)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.doDeploy(DeployersImpl.java:1439)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1157)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1178)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1210)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.install(DeployersImpl.java:1098)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1598)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:934)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1062)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:984)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:822)&lt;br /&gt; at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:553)&lt;br /&gt; at org.jboss.deployers.plugins.deployers.DeployersImpl.process(DeployersImpl.java:781)&lt;br /&gt; at org.jboss.deployers.plugins.main.MainDeployerImpl.process(MainDeployerImpl.java:698)&lt;br /&gt; at org.jboss.system.server.profileservice.ProfileServiceBootstrap.loadProfile(ProfileServiceBootstrap.java:304)&lt;br /&gt; at org.jboss.system.server.profileservice.ProfileServiceBootstrap.start(ProfileServiceBootstrap.java:205)&lt;br /&gt; at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:405)&lt;br /&gt; at org.jboss.Main.boot(Main.java:209)&lt;br /&gt; at org.jboss.Main$1.run(Main.java:547)&lt;br /&gt; at java.lang.Thread.run(Thread.java:619)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O co chodzi?&lt;br /&gt;&lt;br /&gt;Otuż... chodz o błąd, który byłem tak uprzejmy i &lt;a href="https://jira.jboss.org/jira/browse/JBAS-6870?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&amp;focusedCommentId=12471858#action_12471858"&gt;zgłosiłem&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;JBoss wstawia slashe do nazw fragmentów pamięci podręcznej, a EhCache próbuje tworzyć pliki o nazwie takiej jak nazwa fragmentu pamięci podręcznej i ZONK. Co z tym fantem zrobić?&lt;br /&gt;&lt;br /&gt;Napisać własny CacheProvider. Wbrew pozorom nie jest to takie trudne.&lt;br /&gt;Tworzę więc klasę&lt;br /&gt;&lt;span class="pre"&gt;JBoss5EhCacheProvider&lt;/span&gt;&lt;br /&gt;która zamieni w nazwach pamięci podręcznej znaki '/' na '_'.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;package pl.matt.cache;&lt;br /&gt;&lt;br /&gt;import java.util.Properties;&lt;br /&gt;&lt;br /&gt;import org.hibernate.cache.Cache;&lt;br /&gt;import org.hibernate.cache.CacheException;&lt;br /&gt;import org.hibernate.cache.CacheProvider;&lt;br /&gt;&lt;br /&gt;public class JBoss5EhCacheProvider implements CacheProvider {&lt;br /&gt;&lt;br /&gt; private CacheProvider delegate = new org.hibernate.cache.EhCacheProvider();&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public Cache buildCache(String name, Properties props) throws CacheException {&lt;br /&gt;  name = changeName(name);&lt;br /&gt;  return delegate.buildCache(name, props);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; private String changeName(String name) {&lt;br /&gt;  if (name != null) {&lt;br /&gt;   return name.replace('/', '_');&lt;br /&gt;  }&lt;br /&gt;  return name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean isMinimalPutsEnabledByDefault() {&lt;br /&gt;  return delegate.isMinimalPutsEnabledByDefault();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public long nextTimestamp() {&lt;br /&gt;  return delegate.nextTimestamp();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void start(Properties arg0) throws CacheException {&lt;br /&gt;  delegate.start(arg0);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void stop() {&lt;br /&gt;  delegate.stop();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i ustawiam ją w pliku &lt;span class="pre"&gt;persistence-dev.xml&lt;/span&gt; jako CacjeProvider.&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&lt;br /&gt;&amp;lt;property name="hibernate.cache.provider_class" value="pl.matt.cache.JBoss5EhCacheProvider" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Czas na kolejny restart aplikacji. Chyba się udało...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[ServerImpl] JBoss (Microcontainer) [5.0.1.GA (build: SVNTag=JBoss_5_0_1_GA date=200902232048)] Started in 1m:4s:297ms&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Otwieram kilka razy pracownika w różnych zakładkach.&lt;br /&gt;W konsoli widzę:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[STDOUT] Hibernate: &lt;br /&gt;    select&lt;br /&gt;        employee0_.id as id0_,&lt;br /&gt;        employee0_.age as age0_,&lt;br /&gt;        employee0_.email as email0_,&lt;br /&gt;        employee0_.name as name0_,&lt;br /&gt;        employee0_.surname as surname0_ &lt;br /&gt;    from&lt;br /&gt;        employees employee0_ limit ?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;tylko raz. Kilka zapytań o obiekty, a do bazy zapytanie poszło jedno.&lt;br /&gt;Sukces pełną gębą.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-6281563841099565434?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/XFB7v7sIfZo/seam-z-ehcache.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_KxCJvjRke2k/Snn3Ruf7iRI/AAAAAAAAALA/b0XAFL5hg3A/s72-c/0.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/08/seam-z-ehcache.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-7234703139493294792</guid><pubDate>Sun, 28 Jun 2009 14:56:00 +0000</pubDate><atom:updated>2009-07-22T14:16:26.126-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jboss Tools</category><category domain="http://www.blogger.com/atom/ns#">JBoss Seam</category><title>Para buch, koła w ruch... czyli aplikacja CRUD z JBoss Seam w 5... no może 15 minut ;).</title><description>Stoi na stacji lokomotywa, ciężka ogromna, aż pot z niej spływa... że tak zacznę słowami &lt;a href="http://jc.neostrada.pl/studio/Lokomotywa_1.mp3"&gt;poety&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Z końmi, grubasami i armatą, które rozmieszczone są w kolejnych wagonach ciągniętych przez pojazd się przy okazji dzisiejszego wpisu nie spotkamy, ale... z parą jak najbardziej.&lt;br /&gt;&lt;br /&gt;Przedstawię jak najprościej wygenerować aplikację CRUD z wykorzystaniem szkieletu aplikacyjnego &lt;a href="http://seamframework.org/"&gt;JBoss Seam&lt;/a&gt;. Posłużę się środowiskiem &lt;a href="http://download.eclipse.org/eclipse/downloads/drops/R-3.4.2-200902111700/index.php"&gt;Eclipse 3.4.2&lt;/a&gt; z zainstalowaną wtyczką &lt;a href="http://www.jboss.org/tools/download.html"&gt;JBoss Tools 3.0&lt;/a&gt;. Użyję też bazy MySql 5.0 oraz serwera aplikacji Java EE JBoss 5.0.1.GA. Niezbędna okaże się również instalacja Seama. Użyję wersji &lt;a href="http://sourceforge.net/project/downloading.php?group_id=22866&amp;filename=jboss-seam-2.1.1.GA.zip&amp;a=79953978"&gt;2.1.1.GA&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jeżeli potrzebujesz aplikacji webowej, aby zaliczyć projekt, świetnie trafiłeś. Wystarczy przerwa między zajęciami, ale ad rem...&lt;br /&gt;&lt;br /&gt;Instaluję &lt;a href="http://download.eclipse.org/eclipse/downloads/drops/R-3.4.2-200902111700/index.php"&gt;Eclipse&lt;/a&gt;, bazę &lt;a href="http://dev.mysql.com/downloads/mysql/5.0.html#downloads"&gt;MySQL&lt;/a&gt;, &lt;a href="http://sourceforge.net/projects/jboss/files/#"&gt;JBossa 5.0.1.GA&lt;/a&gt; oraz wtyczkę &lt;a href="http://www.jboss.org/tools/download.html"&gt;JBoss Tools&lt;/a&gt; oraz &lt;a href="http://sites.google.com/site/pudelekeclipseplugin/"&gt;Pudelek Eclipse Plugin&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;W Eclipsie, konfiguruje środowisko uruchomieniowe JBossa. W tym celu otwieram menu preferencji&lt;br /&gt;&lt;span class="pre"&gt;Window -&gt; Preferences&lt;/span&gt;&lt;br /&gt;i znajduję tam zakładkę &lt;br /&gt;&lt;span class="pre"&gt;Server / Runtime Environments&lt;/span&gt;&lt;br /&gt;na której klikam przycisk&lt;br /&gt;&lt;span class="pre"&gt;Add...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Odszukuję pozycję&lt;br /&gt;&lt;span class="pre"&gt;JBoss 5.0 Runtime&lt;/span&gt;&lt;br /&gt;która znajduje się w katalogu&lt;br /&gt;&lt;span class="pre"&gt;JBoss Comunity&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIhk3xEeI/AAAAAAAAAIg/Ot9zl7EcdjY/s1600-h/2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 254px; height: 320px;" src="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIhk3xEeI/AAAAAAAAAIg/Ot9zl7EcdjY/s320/2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361052148101616098" /&gt;&lt;/a&gt;&lt;br /&gt;Klikam&lt;br /&gt;&lt;span class="pre"&gt;Next&lt;/span&gt;&lt;br /&gt;wskazuję katalog z zainstalowanym JBossem&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIhx1cyLI/AAAAAAAAAIo/Z0hPiKYY2H4/s1600-h/3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 252px; height: 320px;" src="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIhx1cyLI/AAAAAAAAAIo/Z0hPiKYY2H4/s320/3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361052151581558962" /&gt;&lt;/a&gt;&lt;br /&gt;i klikam&lt;br /&gt;&lt;span class="pre"&gt;Finish&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pora stworzyć nowy projekt. Z menu&lt;br /&gt;&lt;span class="pre"&gt;File -&gt; New -&gt; Project...&lt;/span&gt;&lt;br /&gt;wybieram&lt;br /&gt;&lt;span class="pre"&gt;Seam Web Project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZIhQfQi-I/AAAAAAAAAIQ/_8dgszZOV5M/s1600-h/0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 307px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZIhQfQi-I/AAAAAAAAAIQ/_8dgszZOV5M/s320/0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361052142630112226" /&gt;&lt;/a&gt;&lt;br /&gt;Nadaję nazwę projektowi (radzę zacząć małą literą):&lt;br /&gt;&lt;span class="pre"&gt;seamApplication&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Z menu&lt;br /&gt;&lt;span class="pre"&gt;Configuration&lt;/span&gt;&lt;br /&gt;wybieram&lt;br /&gt;&lt;span class="pre"&gt;Dynamic Web Project With Seam 2.1 (technology preview)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIiccS1lI/AAAAAAAAAIw/A5sXMhLLJGM/s1600-h/4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 320px;" src="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIiccS1lI/AAAAAAAAAIw/A5sXMhLLJGM/s320/4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361052163018774098" /&gt;&lt;/a&gt;&lt;br /&gt;Klikam kilka razy&lt;br /&gt;&lt;span class="pre"&gt;Next &amp;gt;&lt;/span&gt;&lt;br /&gt;i zatrzymuję się na zakładce, na której muszę wskazać środowisko uruchomieniowe Seam&lt;br /&gt;&lt;span class="pre"&gt;Seam Runtume&lt;/span&gt;.&lt;br /&gt;W tej samej zakładce wybieram rodzaj aplikacji jako &lt;br /&gt;&lt;span class="pre"&gt;ear&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJvCi1FCI/AAAAAAAAAI4/iTtrRehKL24/s1600-h/5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 320px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJvCi1FCI/AAAAAAAAAI4/iTtrRehKL24/s320/5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053478916789282" /&gt;&lt;/a&gt;&lt;br /&gt;Definiuję środowisko uruchomieniowe Seama, klikając&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;Add...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_KxCJvjRke2k/SmZJvvPOTyI/AAAAAAAAAJA/ZuwJ9myiEHc/s1600-h/6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 317px; height: 320px;" src="http://1.bp.blogspot.com/_KxCJvjRke2k/SmZJvvPOTyI/AAAAAAAAAJA/ZuwJ9myiEHc/s320/6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053490914152226" /&gt;&lt;/a&gt;&lt;br /&gt;i wskazuję katalog, w którym zainstalowałem Seama 2.1.1.GA.&lt;br /&gt;&lt;br /&gt;Na tej samej zakładce konfiguruję połączenie z bazą danych. Pobieram sterownik &lt;a href="http://dev.mysql.com/downloads/connector/j/5.1.html"&gt;JDBC MySQL Connector&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;W sekcji Database wybieram typ bazy danych jako &lt;br /&gt;&lt;span class="pre"&gt;MySQL (InnoDB)&lt;/span&gt;&lt;br /&gt;oraz tworze nowy profil połączenia z bazą. Jako &lt;br /&gt;&lt;span class="pre"&gt;Profile Type&lt;/span&gt;&lt;br /&gt;wybieram&lt;br /&gt;&lt;span class="pre"&gt;MySQL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_KxCJvjRke2k/SmZJvqS6e4I/AAAAAAAAAJI/oNVC7qGG8UY/s1600-h/7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 320px;" src="http://1.bp.blogspot.com/_KxCJvjRke2k/SmZJvqS6e4I/AAAAAAAAAJI/oNVC7qGG8UY/s320/7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053489587452802" /&gt;&lt;/a&gt;&lt;br /&gt;Klikam &lt;br /&gt;&lt;span class="pre"&gt;Next &amp;gt;&lt;/span&gt; &lt;br /&gt;i definiuję nowy sterownik&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJv_k-sBI/AAAAAAAAAJQ/kxABkhxvQiE/s1600-h/8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJv_k-sBI/AAAAAAAAAJQ/kxABkhxvQiE/s320/8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053495300370450" /&gt;&lt;/a&gt;&lt;br /&gt;Na zakładce&lt;br /&gt;&lt;span class="pre"&gt;Jar List&lt;/span&gt;&lt;br /&gt;wskazuję plik jar który znajdował się w paczce z pobranym sterownikiem JDBC.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJwB994jI/AAAAAAAAAJY/LmzlwhnBpiY/s1600-h/9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZJwB994jI/AAAAAAAAAJY/LmzlwhnBpiY/s320/9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053495942046258" /&gt;&lt;/a&gt;&lt;br /&gt;Podaję nazwę bazy danych oraz nazwę użytkownika i hasło do bazy&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKGeDg_8I/AAAAAAAAAJg/1xZe10cKHBI/s1600-h/10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 212px; height: 320px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKGeDg_8I/AAAAAAAAAJg/1xZe10cKHBI/s320/10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053881438633922" /&gt;&lt;/a&gt;&lt;br /&gt;Od razu tworzę taką bazę wydając polecenie w konsoli mysql&lt;br /&gt;&lt;pre class="brush: sql;"&gt;&lt;br /&gt;create database test default character set utf8;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;a w Eclipsie klikam&lt;br /&gt;&lt;span class="pre"&gt;Finish&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Komputer chwilkę pomyśli, po czym stworzy 4 projekty:&lt;br /&gt;&lt;span class="pre"&gt;seamApplication&lt;/span&gt; z aplikacją webową&lt;br /&gt;&lt;span class="pre"&gt;seamApplication-ear&lt;/span&gt; z deskryptorem aplikacji EAR&lt;br /&gt;&lt;span class="pre"&gt;seamApplication-ejb&lt;/span&gt; z aplikacją EJB&lt;br /&gt;&lt;span class="pre"&gt;seamApplication-test&lt;/span&gt; z testami aplikacji&lt;br /&gt;&lt;br /&gt;Startuję serwer aby sprawdzić, czy aplikacja się uruchamia.&lt;br /&gt;Po wpisaniu w przeglądarkę adresu:&lt;br /&gt;&lt;span class="pre"&gt;http://localhost:8080/seamApplication/&lt;/span&gt;&lt;br /&gt;moim oczom ukazuje się aplikacja:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KxCJvjRke2k/SmZKGtF4RyI/AAAAAAAAAJo/FXUolZnpoKo/s1600-h/11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 141px;" src="http://3.bp.blogspot.com/_KxCJvjRke2k/SmZKGtF4RyI/AAAAAAAAAJo/FXUolZnpoKo/s320/11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053885475079970" /&gt;&lt;/a&gt;&lt;br /&gt;So far, so good...&lt;br /&gt;&lt;br /&gt;Jako, że mamy do stworzenia aplikację CRUD, trzeba by stworzyć encję, którą będziemy mogli edytować. Tworzę więc klasę &lt;br /&gt;&lt;span class="pre"&gt;pl.matt.model.Employee&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java;"&gt;&lt;br /&gt;package pl.matt.model;&lt;br /&gt;&lt;br /&gt;import javax.persistence.Column;&lt;br /&gt;import javax.persistence.Entity;&lt;br /&gt;import javax.persistence.GeneratedValue;&lt;br /&gt;import javax.persistence.GenerationType;&lt;br /&gt;import javax.persistence.Id;&lt;br /&gt;import javax.persistence.Table;&lt;br /&gt;&lt;br /&gt;import org.hibernate.validator.Email;&lt;br /&gt;import org.hibernate.validator.Length;&lt;br /&gt;import org.hibernate.validator.Max;&lt;br /&gt;import org.hibernate.validator.Min;&lt;br /&gt;import org.hibernate.validator.NotNull;&lt;br /&gt;&lt;br /&gt;@Entity&lt;br /&gt;@Table(name="employees")&lt;br /&gt;public class Employee {&lt;br /&gt;&lt;br /&gt; @Id&lt;br /&gt; @GeneratedValue(strategy=GenerationType.IDENTITY)&lt;br /&gt; private int id; &lt;br /&gt; &lt;br /&gt; @Length(max=128)&lt;br /&gt; @NotNull&lt;br /&gt; private String name;&lt;br /&gt; &lt;br /&gt; @Column(length=128)&lt;br /&gt; @NotNull&lt;br /&gt; private String surname;&lt;br /&gt; &lt;br /&gt; @Email&lt;br /&gt; @NotNull&lt;br /&gt; @Column(length=128)&lt;br /&gt; private String email;&lt;br /&gt; &lt;br /&gt; @Min(0)&lt;br /&gt; @Max(130)&lt;br /&gt; @NotNull&lt;br /&gt; private int age;&lt;br /&gt;&lt;br /&gt; public int getId() {&lt;br /&gt;  return id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setId(int id) {&lt;br /&gt;  this.id = id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getName() {&lt;br /&gt;  return name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setName(String name) {&lt;br /&gt;  this.name = name;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getSurname() {&lt;br /&gt;  return surname;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setSurname(String surname) {&lt;br /&gt;  this.surname = surname;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getEmail() {&lt;br /&gt;  return email;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setEmail(String email) {&lt;br /&gt;  this.email = email;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int getAge() {&lt;br /&gt;  return age;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setAge(int age) {&lt;br /&gt;  this.age = age;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Następnie generuję do niej interfejs użytkownika. Klikam prawym przyciskiem myszy na projekcie, wybieram&lt;br /&gt;&lt;span class="pre"&gt;New... -&gt; Other&lt;/span&gt;&lt;br /&gt;i&lt;br /&gt;&lt;span class="pre"&gt;Seam Generate Entities&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KxCJvjRke2k/SmZKG2TnQWI/AAAAAAAAAJw/tCs9YiyuQxU/s1600-h/12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 300px;" src="http://3.bp.blogspot.com/_KxCJvjRke2k/SmZKG2TnQWI/AAAAAAAAAJw/tCs9YiyuQxU/s320/12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053887948603746" /&gt;&lt;/a&gt;&lt;br /&gt;Zaznaczam opcję&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;Use existing entities&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKHMs14qI/AAAAAAAAAJ4/96kFPgADjp4/s1600-h/13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKHMs14qI/AAAAAAAAAJ4/96kFPgADjp4/s320/13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053893960000162" /&gt;&lt;/a&gt;&lt;br /&gt;i klikam &lt;br /&gt;&lt;span class="pre"&gt;Finish&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Restartuję JBossa i aplikacja gotowa.&lt;br /&gt;&lt;br /&gt;Pojawiła się lista pracowników, ich wyszukiwarka oraz strony umożliwiające ich dodawanie, kasowania oraz aktualizację.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKHe-svKI/AAAAAAAAAKA/VZUpdWHfz-8/s1600-h/14.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 92px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKHe-svKI/AAAAAAAAAKA/VZUpdWHfz-8/s320/14.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361053898866736290" /&gt;&lt;/a&gt;&lt;br /&gt;Do tego działa logowanie użytkowników, ajaxowa  walidacja adresu email, wieku i wymagalności pól.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKVAaFnZI/AAAAAAAAAKI/8n6-pgIRUUo/s1600-h/16.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 79px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SmZKVAaFnZI/AAAAAAAAAKI/8n6-pgIRUUo/s320/16.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361054131178282386" /&gt;&lt;/a&gt;&lt;br /&gt;Żyć nie umierać.&lt;br /&gt;Kod źródłowy przykładu zamieszczam &lt;a href="https://sites.google.com/site/najawie/Home/seamApplication20090722.7z.001"&gt;tutaj&lt;/a&gt;, &lt;a href="https://sites.google.com/site/najawie/Home/seamApplication20090722.7z.002"&gt;tu&lt;/a&gt;, &lt;a href="https://sites.google.com/site/najawie/Home/seamApplication20090722.7z.003"&gt;tu&lt;/a&gt; i &lt;a href="https://sites.google.com/site/najawie/Home/seamApplication20090722.7z.004"&gt;tu&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-7234703139493294792?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/OKWezlrl6zM/para-buch-koa-w-ruch-czyli-aplikacja.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_KxCJvjRke2k/SmZIhk3xEeI/AAAAAAAAAIg/Ot9zl7EcdjY/s72-c/2.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/06/para-buch-koa-w-ruch-czyli-aplikacja.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-275025971310894436</guid><pubDate>Sun, 14 Jun 2009 13:55:00 +0000</pubDate><atom:updated>2009-06-14T07:01:19.377-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Eclipse Demo Camp</category><title>Filmy się obrobiły</title><description>Stało się.&lt;br /&gt;&lt;br /&gt;Wszystkie filmy z warszawskiego &lt;a href="http://groups.google.com/group/warszawa-jug/web/eclipse-democamp-2009"&gt;Eclipse Demo Campu&lt;/a&gt; pojawiły się na stronie:&lt;br /&gt;&lt;a href="http://javatv.pl/"&gt;http://javatv.pl/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Muszę przyznać, że jakoś jest niezła, a i 15 minutowe nagrania ogląda się przyjemniej niż 2 godzinne.&lt;br /&gt;&lt;br /&gt;Oto moje wystąpienie:&lt;br /&gt;&lt;embed src="http://82.177.196.103:8080/wjug/player.swf" height="280" width="600" allowscriptaccess="always" allowfullscreen="true" flashvars="streamer=lighttpd&amp;file=http%3A%2F%2F82.177.196.103%3A8080%2Fwjug%2Ffilms%2F2009%2F02.06.2009_democamp%2F3.mp4&amp;plugins=viral-1d"&gt;&lt;br /&gt;&lt;/embed&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-275025971310894436?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/TM3IPQ-L664/filmy-sie-obrobiy.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/06/filmy-sie-obrobiy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-1481557605675992566</guid><pubDate>Mon, 08 Jun 2009 20:54:00 +0000</pubDate><atom:updated>2009-06-08T15:09:11.681-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Eclipse</category><category domain="http://www.blogger.com/atom/ns#">Eclipse Galileo</category><title>Garść wrażeń po warszawskim Eclipse DemoCamp Galileo 2009</title><description>W ubiegły wtorek, 2giego czerwca w Warszawie w budynku MIMUW przy ul. Banacha 2 odbyły się warsztaty poświęcone najnowszemu wydaniu Eclipse IDE (jeszcze w wersji &lt;a href="http://download.eclipse.org/eclipse/downloads/drops/S-3.5RC4-200906051444/index.php"&gt;RC&lt;/a&gt;) &lt;a href="http://groups.google.com/group/warszawa-jug/web/eclipse-democamp-2009"&gt;Eclipse DemoCamp Galileo 2009&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Warsztaty poprzedził poczęstunek z pizzy, co okazało się sprawką patrona &lt;a href="http://code-house.org/"&gt;Code-House.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Formuła imprezy była dość nietypowa, przynajmniej jak na warszawskie spotkania. Warsztaty składały się z 6ciu 15 minutowych wystąpień. Jednym z nich, było wystąpienie "Wtyczka do Eclipse w 5 ... no może 15 minut" autorstwa... mojego autorstwa.&lt;br /&gt;&lt;br /&gt;Zaczęło się całkiem nietypowo, bo od kłopotów technicznych. Projektor odmówił współpracy z moim Ubuntu w rozdzielczości wyższej niż 800x600. A że prezentacja trwała 15 minut... to i skończyło się nietypowo, ponieważ tworząc wtyczkę nie mogłem zaznaczyć odpowiednich opcji konfiguracyjnych. Nie mieściły się one po prostu na ekranie. I tak zamiast odtwarzacza mp3jek Eclipse zamienił się tylko w prymitywny manager plików.&lt;br /&gt;&lt;br /&gt;Jeżeli ktoś miałby ochotę zobaczyć co chciałem osiągnąć, a nie tylko to co mi się udało "programując przez dziurkę od klucza" jak to określił słuchacz w pierwszym rzędzie, kod wtyczki odtwarzającej pliki MP3 zamieszczam &lt;a href="http://sites.google.com/site/najawie/Home/mp3Player.zip"&gt;tutaj&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Niedługo możecie spodziewać się krótkiego poradnika, a ja nie mogę doczekać się nagrania z konferencji.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-1481557605675992566?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/7uYwNxkXHn8/garsc-wrazen-po-warszawskim-eclipse.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/06/garsc-wrazen-po-warszawskim-eclipse.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-7558573664007070557</guid><pubDate>Fri, 17 Apr 2009 22:34:00 +0000</pubDate><atom:updated>2009-04-17T15:47:14.773-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">pudelek</category><category domain="http://www.blogger.com/atom/ns#">eclipse plugin</category><title>Pudelek Eclipse Plug-in</title><description>Zastanawiałeś się jak zwiększyć wydajność pracy Java Teamu w Twojej firmie? Wiesz ile czasu tracą programiści przełączając się pomiędzy &lt;a href="http://www.eclipse.org/"&gt;Eclipsem&lt;/a&gt; a przeglądarką internetową, żeby przejrzeć najnowsze wiadomości?&lt;br /&gt;To na szczęście już przeszłość.&lt;br /&gt;&lt;br /&gt;Dzięki wtyczce &lt;a href="http://sites.google.com/site/pudelekeclipseplugin/"&gt;&lt;span style="color: rgb(234, 153, 153);"&gt;Pudelek Eclipse Plug-in&lt;/span&gt;&lt;/a&gt; zintegrujesz swoje ulubione środowisko deweloperskie, z najpopularniejszym serwisem plotkarskim. Dzięki intuicyjnemu interfejsowi użytkownika (artykuły widziane są jako pliki .java), od razu połapiesz się co i jak.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://sites.google.com/site/pudelekeclipseplugin/_/rsrc/1239478414982/Home/package-view.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 351px; height: 694px;" src="http://sites.google.com/site/pudelekeclipseplugin/_/rsrc/1239478414982/Home/package-view.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I to wszystko za darmo.&lt;br /&gt;Zapraszam do instalacji, używania, komentowania i rozpowszechniania wtyczki.&lt;br /&gt;Strona domowa projektu:&lt;br /&gt;&lt;a href="http://sites.google.com/site/pudelekeclipseplugin/"&gt;http://sites.google.com/site/pudelekeclipseplugin/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-7558573664007070557?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/4uGWHCnNuwI/pudelek-eclipse-plug-in.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/04/pudelek-eclipse-plug-in.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-5590281359575077675</guid><pubDate>Wed, 15 Apr 2009 19:48:00 +0000</pubDate><atom:updated>2009-04-15T13:03:59.833-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jazoon09</category><title>Jazoon09 rozkład jazdy</title><description>Całkiem niedawno pojawił się plan konferencji Jazoon09 (czerwiec 2009).&lt;br /&gt;I tak w&lt;br /&gt;&lt;a href="http://jazoon.com/en/conference/monday.html"&gt;poniedziałek&lt;/a&gt; dominuje GlassFish i OSGi,&lt;br /&gt;we &lt;a href="http://jazoon.com/en/conference/tuesday.html"&gt;wtorek&lt;/a&gt; kupę smakołyków. Między innymi Spring 3, Glassfish 3 i JBoss AS 5.0&lt;br /&gt;w &lt;a href="http://jazoon.com/en/conference/wednesday.html"&gt;środę&lt;/a&gt; między innymi Jazoon Rookie, Java FX&lt;br /&gt;we &lt;a href="http://jazoon.com/en/conference/thursday.html"&gt;czwartek&lt;/a&gt; oprócz lunchu &lt;a href="http://jazoon.com/en/conference/presentationdetails.html?type=sid&amp;detail=6200"&gt;dopieszczanie GC&lt;/a&gt; i co nieco o &lt;a href="http://jazoon.com/en/conference/presentationdetails.html?type=sid&amp;detail=8461"&gt;JPA 2.0&lt;/a&gt;.&lt;br /&gt;a w &lt;a href="http://jazoon.com/en/conference/friday.html"&gt;piątek&lt;/a&gt; rządzić będzie bezpieczeństwo.&lt;br /&gt;Zapowiada się bardzo interesująco, tylko gdzie impreza integracyjna?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-5590281359575077675?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/6wHYtQVhEVo/jazoon09-rozkad-jazdy.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/04/jazoon09-rozkad-jazdy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-1837008342169117086</guid><pubDate>Sun, 12 Apr 2009 19:59:00 +0000</pubDate><atom:updated>2009-04-28T15:45:48.907-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">hibernate</category><title>leniwe ładowanie właściwości w Hibernate</title><description>Święta, święta i... jeszcze został jeden dzień obżarstwa. Tu barszczyk, tam kiełbaska, mięsko, sałatka, mazurek. Wszystkiego trzeba spróbować. A gdyby tak jeść tylko to, co jest w danej chwili niezbędne? Po prostu nie przejadać się. Chyba byłoby zdrowiej...&lt;br /&gt;&lt;br /&gt;To takie moje świąteczne przemyślenia. W programowaniu jednak jest trochę jak w życiu. Często mamy do czynienia z podobnymi sytuacjami. Nie zjadamy co prawda w naszych programach wszystkiego, co jest pod ręką, ale wyciągając z bazy danych obiekty przy użyciu narzędzi ORM (Object Relational Mapping), pobieramy je wyciągając wszystkie kolumny z bazy danych. Inicjujemy wszystkie, nawet te niepotrzebne w danej chwili właściwości obiektów.&lt;br /&gt;&lt;br /&gt;O ile zazwyczaj nikomu to nie przeszkadza, o tyle w przypadku pobierania właściwości o dużych rozmiarach (np. duże obiekty binarne, tekstowe) może to się odbić czkawką i negatywnie wpłynąć na wydajność aplikacji.&lt;br /&gt;&lt;br /&gt;Na szczęście &lt;a href="http://www.hibernate.org"&gt;Hibernate&lt;/a&gt;, będący chyba najpopularniejszym narzędziem mapowania obiektowo relacyjnego, umożliwia selektywne pobieranie właściwości obiektów. Wyboru, które kolumny pobieramy wyciągając obiekt z relacyjnej bazy danych dokonujemy za pomocą parametru &lt;span class="pre"&gt;fetch&lt;/span&gt; adnotacji &lt;span class="pre"&gt;@Basic&lt;/span&gt;. Jeżeli konfigurację przejścia obiektowo relacyjnego przechowujemy w plikach XML, za to zachowanie odpowiedzialny jest atrybut &lt;span class="pre"&gt;lazy&lt;/span&gt; znacznika &lt;span class="pre"&gt;property&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Domyślnie pobierane są wszystkie atrybuty obiektów, nie będące kolekcjami, co odpowiada ustawieniom:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;@Basic(fetch = FetchType.EAGER)&lt;br /&gt;&lt;/pre&gt;oraz&lt;pre class="brush:xml"&gt;&lt;br /&gt;        &amp;lt;property lazy="false" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Sprawdźmy więc w akcji, jak działa konfiguracja leniwego pobierania wybranych właściwości obiektów w &lt;a href="http://www.hibernate.org"&gt;Hibernate&lt;/a&gt;. Mój przykładowy program powstał na podstawie &lt;a href="http://www.hibernate.org/hib_files/jpwh-gettingstarted-070401.zip"&gt;przykładów&lt;/a&gt; ze strony projektu &lt;a href="http://www.hibernate.org"&gt;Hibernate&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pobierał będę encję &lt;span class="pre"&gt;Message&lt;/span&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package pl.matt.model;&lt;br /&gt;&lt;br /&gt;public class Message {&lt;br /&gt;    private Long id;&lt;br /&gt;    private String text;&lt;br /&gt;&lt;br /&gt;    Message() {}&lt;br /&gt;&lt;br /&gt;    public Message(String text) {&lt;br /&gt;        this.text = text;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Long getId() {&lt;br /&gt;        return id;&lt;br /&gt;    }&lt;br /&gt;    private void setId(Long id) {&lt;br /&gt;        this.id = id;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getText() {&lt;br /&gt;        return text;&lt;br /&gt;    }&lt;br /&gt;    public void setText(String text) {&lt;br /&gt;        this.text = text;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;konfigurację przejścia obiektowo relacyjnego zawarłem w pliku XML &lt;span class="pre"&gt;Message.hbm.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE hibernate-mapping PUBLIC&lt;br /&gt;    "-//Hibernate/Hibernate Mapping DTD//EN"&lt;br /&gt;    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-mapping&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;class&lt;br /&gt;        name="pl.matt.model.Message"&lt;br /&gt;        table="MESSAGES"&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;id&lt;br /&gt;            name="id"&lt;br /&gt;            column="MESSAGE_ID"&lt;br /&gt;            &amp;gt;&lt;br /&gt;            &amp;lt;generator class="native"/&amp;gt;&lt;br /&gt;        &amp;lt;/id&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;property&lt;br /&gt;            name="text"&lt;br /&gt;            column="MESSAGE_TEXT"&lt;br /&gt;            lazy="false"&lt;br /&gt;            /&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;/class&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/hibernate-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Na prosty program pobierający obiekt z bazy danych składa klasa Main&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package pl.matt.main;&lt;br /&gt;&lt;br /&gt;import org.hibernate.Session;&lt;br /&gt;import org.hibernate.Transaction;&lt;br /&gt;&lt;br /&gt;import pl.matt.model.Message;&lt;br /&gt;import pl.matt.utils.HibernateUtil;&lt;br /&gt;&lt;br /&gt;public class Main {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Session session = HibernateUtil.getSessionFactory().openSession();&lt;br /&gt;        Transaction tx = session.beginTransaction();&lt;br /&gt;&lt;br /&gt;        Message message = (Message) session.get(Message.class, 1l);&lt;br /&gt;        System.out.println(message.getId());&lt;br /&gt;        &lt;br /&gt;        tx.commit();&lt;br /&gt;        session.close();&lt;br /&gt;&lt;br /&gt;        HibernateUtil.shutdown();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;Klasa narzędziowa &lt;span class="pre"&gt;HibernateUtil&lt;/span&gt; zawiera kilka metod ułatwiających pracę z &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package pl.matt.utils;&lt;br /&gt;&lt;br /&gt;import org.hibernate.*;&lt;br /&gt;import org.hibernate.cfg.*;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Startup Hibernate and provide access to the singleton SessionFactory&lt;br /&gt; */&lt;br /&gt;public class HibernateUtil {&lt;br /&gt;&lt;br /&gt;  private static SessionFactory sessionFactory;&lt;br /&gt;&lt;br /&gt;  static {&lt;br /&gt;    try {&lt;br /&gt;       sessionFactory = new Configuration().configure().buildSessionFactory();&lt;br /&gt;    } catch (Throwable ex) {&lt;br /&gt;       throw new ExceptionInInitializerError(ex);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public static SessionFactory getSessionFactory() {&lt;br /&gt;      // Alternatively, we could look up in JNDI here&lt;br /&gt;      return sessionFactory;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public static void shutdown() {&lt;br /&gt;      // Close caches and connection pools&lt;br /&gt;      getSessionFactory().close();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;W pliku &lt;span class="pre"&gt;hibernate.cfg.xml&lt;/span&gt; konfiguruję połączenie z bazą danych HSQL oraz ustawiam wartość &lt;span class="pre"&gt;true&lt;/span&gt; parametru &lt;span class="pre"&gt;show_sql&lt;/span&gt; który umożliwia podglądanie zapytań SQL wykonywanych przez &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='utf-8'?&amp;gt; &amp;lt;!DOCTYPE hibernate-configuration&lt;br /&gt;        PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"&lt;br /&gt;        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt;    &amp;lt;session-factory&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;property name="hibernate.connection.driver_class"&amp;gt;org.hsqldb.jdbcDriver&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name="hibernate.connection.url"&amp;gt;jdbc:hsqldb:hsql://localhost&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name="hibernate.connection.username"&amp;gt;sa&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!-- SQL to stdout logging --&amp;gt;&lt;br /&gt;        &amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name="format_sql"&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;        &amp;lt;property name="use_sql_comments"&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;        &lt;br /&gt;        &amp;lt;property name="hibernate.hbm2ddl.auto"&amp;gt;update&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.HSQLDialect&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;mapping resource="pl/matt/model/Message.hbm.xml"/&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;/session-factory&amp;gt;&lt;br /&gt;&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Uruchamiam program i zgodnie z oczekiwaniami widzę zapytanie pobierające 2 właściwości z tabeli &lt;span class="pre"&gt;MESSAGES&lt;/span&gt;:&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;Hibernate: &lt;br /&gt;    /* load pl.matt.model.Message */ select&lt;br /&gt;        message0_.MESSAGE_ID as MESSAGE1_0_0_,&lt;br /&gt;        message0_.MESSAGE_TEXT as MESSAGE2_0_0_ &lt;br /&gt;    from&lt;br /&gt;        MESSAGES message0_ &lt;br /&gt;    where&lt;br /&gt;        message0_.MESSAGE_ID=?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;zmieniam w pliku &lt;span class="pre"&gt;Message.hbm.xml&lt;/span&gt; wartość atrybutu &lt;span class="pre"&gt;lazy&lt;/span&gt; na &lt;span class="pre"&gt;true&lt;/span&gt;. Uruchamiam ponownie program i tym razem niezgodnie z oczekiwaniami widzę ponownie:&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;Hibernate: &lt;br /&gt;    /* load pl.matt.model.Message */ select&lt;br /&gt;        message0_.MESSAGE_ID as MESSAGE1_0_0_,&lt;br /&gt;        message0_.MESSAGE_TEXT as MESSAGE2_0_0_ &lt;br /&gt;    from&lt;br /&gt;        MESSAGES message0_ &lt;br /&gt;    where&lt;br /&gt;        message0_.MESSAGE_ID=?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hmm... słabo.&lt;br /&gt;Zagłębiłem się w dokumentację i już widzę, że nie będzie łatwo:&lt;br /&gt;&lt;span class="pre"&gt;&lt;br /&gt;Note&lt;br /&gt;&lt;br /&gt;To enable property level lazy fetching, your classes have to be instrumented: bytecode is added to the original one to enable such feature, please refer to the Hibernate reference documentation. If your classes are not instrumented, property level lazy loading is silently ignored.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Nawet nie wiedziałem, że jest taki czasownik &lt;span class="pre"&gt;instrument&lt;/span&gt;. W każdym razie moje ustawienia zostały po cichu zignorowane, jak to ładnie określiła dokumentacja Hibernate. Trzeba by to zmienić. Szperam więc dalej w poszukiwaniu sposobu zinstrumetowania klas.&lt;br /&gt;&lt;br /&gt;Wykonać ten proces można antowym zadaniem:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt; &amp;lt;target name="instrument" depends="compile"&amp;gt;&lt;br /&gt;     &amp;lt;taskdef name="instrument" classname="org.hibernate.tool.instrument.cglib.InstrumentTask"&amp;gt;&lt;br /&gt;         &amp;lt;classpath path="${build.dir}"/&amp;gt;&lt;br /&gt;         &amp;lt;classpath refid="project.classpath"/&amp;gt;&lt;br /&gt;     &amp;lt;/taskdef&amp;gt;&lt;br /&gt;&lt;br /&gt;     &amp;lt;instrument verbose="true"&amp;gt;&lt;br /&gt;         &amp;lt;fileset dir="${build.dir}/pl/matt/model"&amp;gt;&lt;br /&gt;             &amp;lt;include name="*.class"/&amp;gt;&lt;br /&gt;         &amp;lt;/fileset&amp;gt;&lt;br /&gt;     &amp;lt;/instrument&amp;gt;&lt;br /&gt; &amp;lt;/target&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;W dokumentacji &lt;a href="http://www.hibernate.org"&gt;Hibernate&lt;/a&gt; jest mały błąd, gdyż klasa zadania instrument &lt;span class="pre"&gt;InstrumentTask&lt;/span&gt; nie znajduje się w pakiecie &lt;span class="pre"&gt;org.hibernate.tool.instrument&lt;/span&gt; tylko w &lt;span class="pre"&gt;org.hibernate.tool.instrument.cglib&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Jako, że powyższe zadanie zmienia kod plików &lt;span class="pre"&gt;*.class&lt;/span&gt;, muszę uruchamiać te skompilowane i zmienione przez &lt;a href="http://ant.apache.org/"&gt;ANTa&lt;/a&gt; pliki. Posłużę się do tego celu poniższym plikiem &lt;span class="pre"&gt;build.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;project name="hibernateLazyBasic" default="compile" basedir="."&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Name of project and version --&amp;gt;&lt;br /&gt;    &amp;lt;property name="proj.name"      value="hibernateLazyBasic"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="proj.shortname" value="hibernateLazyBasic"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="version"        value="1.0"/&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Global properties for this build --&amp;gt;&lt;br /&gt;    &amp;lt;property name="database.dir"           value="database"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="src.java.dir"           value="src/java"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="lib.dir"                value="lib"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="build.dir"              value="build"/&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Classpath declaration --&amp;gt;&lt;br /&gt;    &amp;lt;path id="project.classpath"&amp;gt;&lt;br /&gt;        &amp;lt;fileset dir="${lib.dir}"&amp;gt;&lt;br /&gt;            &amp;lt;include name="**/*.jar"/&amp;gt;&lt;br /&gt;            &amp;lt;include name="**/*.zip"/&amp;gt;&lt;br /&gt;        &amp;lt;/fileset&amp;gt;&lt;br /&gt;    &amp;lt;/path&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Useful shortcuts --&amp;gt;&lt;br /&gt;    &amp;lt;patternset id="meta.files"&amp;gt;&lt;br /&gt;        &amp;lt;include name="**/*.xml"/&amp;gt;&lt;br /&gt;        &amp;lt;include name="**/*.properties"/&amp;gt;&lt;br /&gt;    &amp;lt;/patternset&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Clean up --&amp;gt;&lt;br /&gt;    &amp;lt;target name="clean" description="Clean the build directory"&amp;gt;&lt;br /&gt;        &amp;lt;delete dir="${build.dir}"/&amp;gt;&lt;br /&gt;        &amp;lt;mkdir dir="${build.dir}"/&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Compile Java source --&amp;gt;&lt;br /&gt;    &amp;lt;target name="compile"&amp;gt;&lt;br /&gt;        &amp;lt;mkdir dir="${build.dir}"/&amp;gt;&lt;br /&gt;        &amp;lt;javac srcdir="${src.java.dir}"&lt;br /&gt;               destdir="${build.dir}"&lt;br /&gt;               classpathref="project.classpath"/&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- Copy metadata to build classpath --&amp;gt;&lt;br /&gt;    &amp;lt;target name="copymetafiles"&amp;gt;&lt;br /&gt;        &amp;lt;mkdir dir="${build.dir}"/&amp;gt;&lt;br /&gt;        &amp;lt;copy todir="${build.dir}"&amp;gt;&lt;br /&gt;            &amp;lt;fileset dir="${src.java.dir}"&amp;gt;&lt;br /&gt;                &amp;lt;patternset refid="meta.files"/&amp;gt;&lt;br /&gt;            &amp;lt;/fileset&amp;gt;&lt;br /&gt;        &amp;lt;/copy&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;target name="run-instrumented" depends="clean, instrument, copymetafiles"&amp;gt;&lt;br /&gt;        &amp;lt;java fork="true"&lt;br /&gt;              classname="pl.matt.main.Main"&lt;br /&gt;              classpathref="project.classpath"&amp;gt;&lt;br /&gt;            &amp;lt;classpath path="${build.dir}"/&amp;gt;&lt;br /&gt;        &amp;lt;/java&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;target name="run" depends="clean, compile, copymetafiles"&amp;gt;&lt;br /&gt;        &amp;lt;java fork="true"&lt;br /&gt;              classname="pl.matt.main.Main"&lt;br /&gt;              classpathref="project.classpath"&amp;gt;&lt;br /&gt;            &amp;lt;classpath path="${build.dir}"/&amp;gt;&lt;br /&gt;        &amp;lt;/java&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt; &lt;br /&gt; &lt;br /&gt;    &amp;lt;target name="instrument" depends="compile"&amp;gt;&lt;br /&gt;        &amp;lt;taskdef name="instrument" classname="org.hibernate.tool.instrument.cglib.InstrumentTask"&amp;gt;&lt;br /&gt;           &amp;lt;classpath path="${build.dir}"/&amp;gt;&lt;br /&gt;           &amp;lt;classpath refid="project.classpath"/&amp;gt;&lt;br /&gt;        &amp;lt;/taskdef&amp;gt;&lt;br /&gt;        &amp;lt;instrument verbose="true"&amp;gt;&lt;br /&gt;            &amp;lt;fileset dir="${build.dir}/pl/matt/model"&amp;gt;&lt;br /&gt;                &amp;lt;include name="*.class"/&amp;gt;&lt;br /&gt;            &amp;lt;/fileset&amp;gt;&lt;br /&gt;        &amp;lt;/instrument&amp;gt;&lt;br /&gt;    &amp;lt;/target&amp;gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;zadanie o nazwie &lt;span class="pre"&gt;run-instrumented&lt;/span&gt; kompiluje, przeprowadza instrumentację klas z pakiedu &lt;span class="pre"&gt;pl.matt.model&lt;/span&gt; i uruchamia program.&lt;br /&gt;&lt;br /&gt;Po jego wykonaniu, otrzymuję na konsoli:&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;     [java] Hibernate: &lt;br /&gt;     [java]     /* load pl.matt.model.Message */ select&lt;br /&gt;     [java]         message0_.MESSAGE_ID as MESSAGE1_0_0_ &lt;br /&gt;     [java]     from&lt;br /&gt;     [java]         MESSAGES message0_ &lt;br /&gt;     [java]     where&lt;br /&gt;     [java]         message0_.MESSAGE_ID=?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ładowane jest tylko pole &lt;span class="pre"&gt;ID&lt;/span&gt; z tabeli &lt;span class="pre"&gt;MESSAGES&lt;/span&gt;, czyli zgodnie z oczekiwaniami. Kolumna &lt;span class="pre"&gt;MESSAGE_TEXT&lt;/span&gt; pobierana jest z bazy osobnym zapytaniem:&lt;br /&gt;&lt;pre class="brush:sql"&gt;&lt;br /&gt;     [java] Hibernate: &lt;br /&gt;     [java]     /* sequential select&lt;br /&gt;     [java]         pl.matt.model.Message */ select&lt;br /&gt;     [java]             message_.MESSAGE_TEXT as MESSAGE2_0_ &lt;br /&gt;     [java]         from&lt;br /&gt;     [java]             MESSAGES message_ &lt;br /&gt;     [java]         where&lt;br /&gt;     [java]             message_.MESSAGE_ID=?&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;dopiero wtedy, kiedy będzie potrzebna.&lt;br /&gt;&lt;br /&gt;Generalnie wszystko działa, tylko trzeba odrobinę zmienić proces kompilacji programu.&lt;br /&gt;Kod źródłowy przedstawiający powyższe rozwiązanie znajdziesz &lt;a href="http://sites.google.com/site/najawie/Home/hibernateLazyBasic20090312.zip?attredirects=0"&gt;tutaj&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;a że święta już w połowie, pozostaje mi życzyć Wam mokrego dyngusa.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-1837008342169117086?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/EKgwC_WgGA8/leniwe-adowanie-wasciwosci-w-hibernate.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/04/leniwe-adowanie-wasciwosci-w-hibernate.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-968408149300944622</guid><pubDate>Tue, 31 Mar 2009 22:43:00 +0000</pubDate><atom:updated>2009-03-31T15:57:03.804-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jazoon09</category><title>Jazoon Cutting Edge</title><description>Jeżeli zawsze chciałeś opowiedzieć coś ciekawego programistom Java, świetnie trafiłeś. Masz pomysł na prezentację, ale boisz się, że nie będziesz w stanie zająć 60, czy 90 minut?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jazoon.com/en/contribute.html"&gt;Jazoon Cutting Edge&lt;/a&gt; - These 20 minutes talks address the most recent developments in the Java industry.&lt;br /&gt;Call for papers: 15 April 2009&lt;br /&gt;Submission deadline: 15 May 2009&lt;br /&gt;&lt;br /&gt;i wszystko wiadomo.&lt;br /&gt;&lt;br /&gt;Do zgarnięcia darmowa wejściówka czerwcowy &lt;a href="http://jazoon.com/"&gt;Jazoon&lt;/a&gt; i 50% zniżki dla osoby towarzyszącej (również w prezentacji).&lt;br /&gt;Miło byłoby usłyszeć kogoś z Polski.&lt;br /&gt;&lt;br /&gt;Może &lt;a href="http://blog.kunicki.org/"&gt;Jacek&lt;/a&gt; się zgłosi, ze swoimi &lt;a href="http://jdn.pl/node/1735"&gt;zabawkami&lt;/a&gt;? Kto nie był dziś na spotkaniu &lt;a href="http://groups.google.com/group/warszawa-jug"&gt;warszawskiego JUGa&lt;/a&gt; niech żałuje.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-968408149300944622?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/BJhXOTmFu-E/jazoon-cutting-edge.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/03/jazoon-cutting-edge.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-2969837839775083860</guid><pubDate>Sun, 22 Mar 2009 22:32:00 +0000</pubDate><atom:updated>2009-03-22T16:36:15.724-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">EJB 3</category><category domain="http://www.blogger.com/atom/ns#">Remote</category><category domain="http://www.blogger.com/atom/ns#">Local</category><title>Ziarna sesyjne - czar prysł.</title><description>&lt;a href="http://na-jawie.blogspot.com/2009/01/gry-i-zabawy-ze-szklana-rybka.html"&gt;Dopiero co&lt;/a&gt; zachwycałem się nad lokalnym i zdalnym sposobem wywoływania usług ziaren EJB. Przyszła wiosna, śnieg stopniał i czar prysł. Otóż pomiędzy wywołaniem danej metody poprzez interfejs oznaczony adnotacją &lt;span&gt;@Local&lt;/span&gt; a wywołaniem za pomocą interfejsu &lt;span&gt;@Remote&lt;/span&gt; mogą być subtelne różnice. Bierze się to stąd, że parametry metod wywoływanych lokalnie (&lt;span&gt;@Local&lt;/span&gt;) przekazywane są poprzez referencje, parametry metod zdalnych (&lt;span&gt;@Remote&lt;/span&gt;) przez wartość.&lt;br /&gt;&lt;br /&gt;Zobaczmy o co chodzi na podstawie prostego przykładu. Stworzę z tej okazji w &lt;a href="http://www.netbeans.org/"&gt;NetBeans&lt;/a&gt; IDE 6.5.1 projekt ziarna EJB oraz projekt klienta EJB.&lt;br /&gt;&lt;br /&gt;Zaczynam od aplikacji EJB:&lt;br /&gt;Z menu &lt;span&gt;File&lt;/span&gt; wybieram pozycję &lt;span&gt;New Project&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHkuw1iYI/AAAAAAAAANM/iuQ6axkC8CY/s1600-h/02.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 209px;" src="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHkuw1iYI/AAAAAAAAANM/iuQ6axkC8CY/s320/02.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155843999533442" /&gt;&lt;/a&gt;&lt;br /&gt;następnie wybieram kategorię &lt;span&gt;Java EE&lt;/span&gt; i projekt &lt;span&gt;EJB Module&lt;/span&gt; &lt;br /&gt;klikam &lt;span&gt;Next&lt;/span&gt;, po czym na zakładce &lt;span&gt;Server and Settings&lt;/span&gt; dodaję nową konfigurację serwera, klikając przycisk &lt;span&gt;Add...&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHleqKfSI/AAAAAAAAANU/97UoalbBKpA/s1600-h/01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 213px;" src="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHleqKfSI/AAAAAAAAANU/97UoalbBKpA/s320/01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155856856448290" /&gt;&lt;/a&gt;&lt;br /&gt;Przykład będę uruchamiał na serwerze &lt;a href="http://www.jboss.org/jbossas"&gt;JBoss&lt;/a&gt; 4.2.2.GA&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/ScbHli3jVwI/AAAAAAAAANc/-zieoRQSWQk/s1600-h/04.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 189px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/ScbHli3jVwI/AAAAAAAAANc/-zieoRQSWQk/s320/04.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155857986344706" /&gt;&lt;/a&gt;&lt;br /&gt;więc wskazuję jego położenie na dysku:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/ScbHmNjZttI/AAAAAAAAANk/okDmav-r43k/s1600-h/05.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 193px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/ScbHmNjZttI/AAAAAAAAANk/okDmav-r43k/s320/05.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155869444552402" /&gt;&lt;/a&gt;&lt;br /&gt;klikam &lt;span&gt;Next&gt;&lt;/span&gt; i &lt;span&gt;Finish&lt;/span&gt;. Projekt gotowy.&lt;br /&gt;&lt;br /&gt;W projekcie stworzę proste ziarno, które będzie udostępniało metodę dodającą podany jako parametr element do podanej jako parametr kolekcji:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;    public Collection add(Collection collection, Object element) {&lt;br /&gt;        collection.add(element);&lt;br /&gt;        return collection;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ziarno będzie implementowało interfejs lokalny oraz zdalny. Ziarno oraz interfejsy przedstawiają się następująco:&lt;br /&gt;&lt;br /&gt;Kod ziarna &lt;span&gt;StatelessBean&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.session;&lt;br /&gt;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;import javax.ejb.Local;&lt;br /&gt;import javax.ejb.Remote;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;@javax.ejb.Stateless&lt;br /&gt;@Remote(StatelessRemote.class)&lt;br /&gt;@Local(StatelessLocal.class)&lt;br /&gt;public class StatelessBean implements StatelessRemote, StatelessLocal {&lt;br /&gt;&lt;br /&gt;    public Collection add(Collection collection, Object element) {&lt;br /&gt;        collection.add(element);&lt;br /&gt;        return collection;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;interfejs zdalny &lt;span&gt;StatelessRemote&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.session;&lt;br /&gt;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;import javax.ejb.Remote;&lt;br /&gt;&lt;br /&gt;public interface StatelessRemote {&lt;br /&gt;    &lt;br /&gt;    Collection add(Collection collection, Object element);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i identyczny interfejs lokalny &lt;span&gt;StatelessLocal&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.session;&lt;br /&gt;&lt;br /&gt;import java.util.Collection;&lt;br /&gt;import javax.ejb.Remote;&lt;br /&gt;&lt;br /&gt;public interface StatelessLocal {&lt;br /&gt;    &lt;br /&gt;    Collection add(Collection collection, Object element);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Całość uzupełnia ziarno testujące dodawanie elementów do kolekcji, które próbuje zarówno zdalnie jak i lokalnie dodać 3 napisy do listy:&lt;br /&gt;&lt;br /&gt;interfejs &lt;span&gt;TestRemote&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.session;&lt;br /&gt;&lt;br /&gt;public interface TestRemote {&lt;br /&gt;    void test();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;oraz jego implementacja:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.session;&lt;br /&gt;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.List;&lt;br /&gt;import javax.ejb.Remote;&lt;br /&gt;import javax.naming.Context;&lt;br /&gt;import javax.naming.InitialContext;&lt;br /&gt;&lt;br /&gt;@javax.ejb.Stateless&lt;br /&gt;@Remote(TestRemote.class)&lt;br /&gt;public class TestBean implements TestRemote {&lt;br /&gt;&lt;br /&gt;    public void test() {&lt;br /&gt;        try {&lt;br /&gt;            Context context = new InitialContext();&lt;br /&gt;            StatelessLocal statelessLocal = (StatelessLocal) context.lookup("StatelessBean/local");&lt;br /&gt;            StatelessRemote statelessRemote = (StatelessRemote) context.lookup("StatelessBean/remote");&lt;br /&gt;            List&amp;lt;String&amp;gt; localList = new ArrayList();&lt;br /&gt;            statelessLocal.add(localList, "1");&lt;br /&gt;            statelessLocal.add(localList, "2");&lt;br /&gt;            statelessLocal.add(localList, "3");&lt;br /&gt;            System.out.println("local list: " + localList);&lt;br /&gt;&lt;br /&gt;            List&amp;lt;String&amp;gt; remoteList = new ArrayList();&lt;br /&gt;            statelessRemote.add(remoteList, "1");&lt;br /&gt;            statelessRemote.add(remoteList, "2");&lt;br /&gt;            statelessRemote.add(remoteList, "3");&lt;br /&gt;            System.out.println("remote list: " + remoteList);&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Do wywołania metody ziarna &lt;span&gt;TestBean&lt;/span&gt; potrzebuję klienta EJB. Tworzę go wybierając ponownie pozycję &lt;span&gt;New Project...&lt;/span&gt; z menu &lt;span&gt;File&lt;/span&gt;. Następnie z kategorii &lt;span&gt;Java EE&lt;/span&gt; wybieram projekt &lt;span&gt;Enterprise Application Client&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHmSX24zI/AAAAAAAAANs/NujoB7fz_T0/s1600-h/06.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 208px;" src="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHmSX24zI/AAAAAAAAANs/NujoB7fz_T0/s320/06.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155870738309938" /&gt;&lt;/a&gt;&lt;br /&gt;Do tak stworzonego projektu dodaję jako zależność stworzony uprzednio projekt EJB&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_62lNJlh-10g/ScbHqnpGRJI/AAAAAAAAAN0/kG2H8BKcisE/s1600-h/07.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 245px;" src="http://1.bp.blogspot.com/_62lNJlh-10g/ScbHqnpGRJI/AAAAAAAAAN0/kG2H8BKcisE/s320/07.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316155945167242386" /&gt;&lt;/a&gt;&lt;br /&gt;Dzięki temu, będę w nim mógł uzyskać dostęp do interfejsu testującego. Całość kodu klienta zawarta jest w metodzie &lt;span&gt;main()&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt;&lt;br /&gt;&lt;br /&gt;import javax.naming.Context;&lt;br /&gt;import javax.naming.InitialContext;&lt;br /&gt;import pl.matt.session.TestRemote;&lt;br /&gt;&lt;br /&gt;public class Main {&lt;br /&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        try {&lt;br /&gt;            System.out.println("start");&lt;br /&gt;            Context context = new InitialContext();&lt;br /&gt;            TestRemote test = (TestRemote) context.lookup("TestBean/remote");&lt;br /&gt;            test.test();&lt;br /&gt;            System.out.println("finished");&lt;br /&gt;        } catch (Exception e) {&lt;br /&gt;            e.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pozostało uruchomienie i przekonanie się, jak to wszystko będzie działać. Klikam prawym przyciskiem myszy na projekcie EJB, wybieram opcję &lt;span&gt;Run&lt;/span&gt;. Następnie to samo robię na projekcie klienta EJB. JBoss się uruchamia, po chwili widzę w konsoli:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;22:27:55,969 INFO  [STDOUT] local list: [1, 2, 3]&lt;br /&gt;22:27:55,974 INFO  [STDOUT] remote list: []&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;2 razy wywołałem tę samą metodę, raz przez interfejs &lt;span&gt;@Remote&lt;/span&gt;, raz przez &lt;span&gt;@Local&lt;/span&gt; i wynik jej działania jest inny. Do kolekcji, przekazanej przez wartość elementy nie zostały dodane (tzn. zostały, ale do kopii tej kolekcji, przekazanej do ziarna EJB).&lt;br /&gt;&lt;br /&gt;Trzeba uważać.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-2969837839775083860?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/Vt7XGH-x6qE/ziarna-sesyjne-czar-prys.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_62lNJlh-10g/ScbHkuw1iYI/AAAAAAAAANM/iuQ6axkC8CY/s72-c/02.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/03/ziarna-sesyjne-czar-prys.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-8578970202330935780</guid><pubDate>Wed, 25 Feb 2009 17:15:00 +0000</pubDate><atom:updated>2009-02-25T09:52:00.280-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jazoon09</category><title>Jazoon Rookie</title><description>Jesteś młody, żądny przygód? Masz mniej niż 26 lat? Masz coś ciekawego do powiedzenia o Javie? Doskonale się składa. Zawody &lt;a href="http://jazoon.com/en/contribute/rookie.html"&gt;Jazoon Rookie&lt;/a&gt; są właśnie dla Ciebie. &lt;br /&gt;Jesteś młody, żądny przygód? Masz mniej niż 26 lat? Nie masz nic ciekawego do powiedzenia o Javie? Jeszcze lepiej. Zawody &lt;a href="http://jazoon.com/en/contribute/rookie.html"&gt;Jazoon Rookie&lt;/a&gt; są właśnie dla Ciebie.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jazoon.com/en/contribute/rookie.html"&gt;Jazoon Rookie&lt;/a&gt; to zawody, w których zmierzy się trzech prelegentów wraz ze swoimi 20 minutowymi prelekcjami. Aby stać się jednym z nich, wystarczy przygotować abstrakt 20 minutowej prezentacji i &lt;a href="https://jazoon.com/submission?l=en"&gt;zgłosić się&lt;/a&gt; do 15 marca 2008. Termin ten był już 2 razy przekładany, więc zgłoszeń nie ma chyba zbyt dużo. Warto więc spróbować.&lt;br /&gt;&lt;br /&gt;Spośród zgłoszeń zostanie wybranych dziesięciu uczestników. Nagrają oni fragment swoich prelekcji. Spośród tych nagrań zostanie wyłoniona trójka finalistów. Każdy z nich zaprezentuje się na konferencji &lt;a href="http://jazoon.com"&gt;Jazoon'09&lt;/a&gt;. Do tego otrzyma darmową wejściówkę na konferencje, transport i zakwaterowanie.&lt;br /&gt;&lt;br /&gt;Szczegółowe informacje znajdziesz na stronie &lt;a href="http://jazoon.com/en/contribute/rookie.html"&gt;Jazoon Rookie&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Zgłoś się koniecznie. Najwyższy czas, żeby ktoś z Polski pokazał, kto rządzi w Javie.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-8578970202330935780?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/hEDBKv0Vc-k/jazoon-rookie.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/02/jazoon-rookie.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-7853391648846172166</guid><pubDate>Thu, 05 Feb 2009 23:22:00 +0000</pubDate><atom:updated>2009-04-28T06:33:02.252-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">EJB 3</category><category domain="http://www.blogger.com/atom/ns#">Jboss Tools</category><category domain="http://www.blogger.com/atom/ns#">JSF</category><category domain="http://www.blogger.com/atom/ns#">JBoss</category><title>aplikacja JSF i EJB 3.0 w JBoss Tools</title><description>W dzisiejszym odcinku, stworzymy aplikację webową (a jakże) korzystającą z EJB 3.0 i &lt;a href="http://java.sun.com/javaee/javaserverfaces/"&gt;JSF&lt;/a&gt;. Ktoś może się zapytać po co? Przecież mamy znakomity szkielet na literę S... Owszem mamy, ale może nie znamy, albo może nie potrzebujemy jego możliwości... Różnie to w życiu bywa. Poza tym modułowa budowa, którą narzuca nam podział aplikacji na webową i biznesową wydaje się całkiem rozsądnym rozwiązaniem.&lt;br /&gt;Zobaczmy zatem, co i jak... Do pracy nad aplikacją użyję środowiska &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; 3.3 Europa z zainstalowaną wtyczką &lt;a href="http://www.jboss.org/tools/"&gt;JBoss Tools&lt;/a&gt; 2.1.2.GA (ostatnia finalna wersja). Jako środowisko uruchomieniowe posłuży mi kontener &lt;a href="http://jboss.org/jbossas/"&gt;JBoss AS&lt;/a&gt; 4.2.0.GA. Bazą danych będzie &lt;a href="http://www.mysql.com/"&gt;MySQL&lt;/a&gt; 5.0.&lt;br /&gt;Strukturę aplikacji tworzy archiwum EAR (Enterprise Application Archive) zawierające aplikację EJB (archiwum ejb-jar) oraz aplikację webową (archiwum war).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SYy56gmROWI/AAAAAAAAAL0/4IouTxJoh2U/s1600-h/0struktura.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 183px; height: 238px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SYy56gmROWI/AAAAAAAAAL0/4IouTxJoh2U/s320/0struktura.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815276342229346" /&gt;&lt;/a&gt;&lt;br /&gt;Ten na pozór skomplikowany podział może okazać się bardzo przydatny w większych, żeby nie powiedzieć korporacyjnych rozwiązaniach. Z warstwy usług zaimplementowanej w aplikacji EJB korzystać może nie tylko nasza aplikacja JSF, ale także inne, niekoniecznie nawet webowe aplikacje.&lt;br /&gt;&lt;br /&gt;Stworzona aplikacja, będzie typową aplikacją CRUD, umożliwiającą tworzenie, odczyt, aktualizację i kasowanie pracowników. Potrzebować zatem będziemy 3 projekty. Projekt ejb, jsf oraz zawierający je projekt aplikacji ear.&lt;br /&gt;Zacznijmy od EJB. Klikam &lt;span class="pre"&gt;File / New / Other...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/SYy7xUqcnhI/AAAAAAAAAM0/_AqnqfJT89A/s1600-h/1new.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 305px; height: 320px;" src="http://4.bp.blogspot.com/_62lNJlh-10g/SYy7xUqcnhI/AAAAAAAAAM0/_AqnqfJT89A/s320/1new.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299817317542960658" /&gt;&lt;/a&gt;&lt;br /&gt; i z listy wybieram &lt;span class="pre"&gt;EJB Project&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SYy566zAzPI/AAAAAAAAAME/6ZOiTMJIkMQ/s1600-h/2ejb.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 318px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SYy566zAzPI/AAAAAAAAAME/6ZOiTMJIkMQ/s320/2ejb.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815283375000818" /&gt;&lt;/a&gt;&lt;br /&gt;Podaję nazwę projektu &lt;span class="pre"&gt;ejbProject&lt;/span&gt; i klikam &lt;span class="pre"&gt;Next &amp;gt; &lt;/span&gt; Na następnej zakładce zaznaczam &lt;span class="pre"&gt;EJB module&lt;/span&gt; &lt;span class="pre"&gt;Java&lt;/span&gt; i &lt;span class="pre"&gt;Java Persistence&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SYy562hEwVI/AAAAAAAAAMM/vqVSJzWzPfY/s1600-h/3ejb.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 320px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SYy562hEwVI/AAAAAAAAAMM/vqVSJzWzPfY/s320/3ejb.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815282226020690" /&gt;&lt;/a&gt;&lt;br /&gt;klikam 2 razy &lt;span class="pre"&gt;Next &amp;gt;&lt;/span&gt;, odznaczam &lt;span class="pre"&gt;create orm.xml&lt;/span&gt; (będę używał adnotacji) i klikam &lt;span class="pre"&gt;Finish&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tworzę w projekcie encję &lt;span class="pre"&gt;Employee&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.model;&lt;br /&gt;&lt;br /&gt;import javax.persistence.Column;&lt;br /&gt;import javax.persistence.Entity;&lt;br /&gt;import javax.persistence.GeneratedValue;&lt;br /&gt;import javax.persistence.Id;&lt;br /&gt;import javax.persistence.NamedQueries;&lt;br /&gt;import javax.persistence.NamedQuery;&lt;br /&gt;&lt;br /&gt;@NamedQueries({ &lt;br /&gt; @NamedQuery(name = "Employee.findAllOrderByName", query = "FROM Employee e ORDER BY e.lastName, e.firstName")&lt;br /&gt;})&lt;br /&gt;@Entity&lt;br /&gt;public class Employee {&lt;br /&gt;&lt;br /&gt; private int id;&lt;br /&gt; private String password;&lt;br /&gt; private String username;&lt;br /&gt; private String firstName;&lt;br /&gt; private String lastName;&lt;br /&gt;&lt;br /&gt; @Id&lt;br /&gt; @GeneratedValue&lt;br /&gt; public int getId() {&lt;br /&gt;  return id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setId(int id) {&lt;br /&gt;  this.id = id;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Column(nullable = false)&lt;br /&gt; public String getPassword() {&lt;br /&gt;  return password;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setPassword(String password) {&lt;br /&gt;  this.password = password;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Column(nullable = false)&lt;br /&gt; public String getUsername() {&lt;br /&gt;  return username;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setUsername(String username) {&lt;br /&gt;  this.username = username;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Column(nullable = false)&lt;br /&gt; public String getFirstName() {&lt;br /&gt;  return firstName;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setFirstName(String firstName) {&lt;br /&gt;  this.firstName = firstName;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Column(nullable = false)&lt;br /&gt; public String getLastName() {&lt;br /&gt;  return lastName;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setLastName(String lastName) {&lt;br /&gt;  this.lastName = lastName;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;warstwę dostępu do danych (DAO):&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.dao;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import pl.matt.model.Employee;&lt;br /&gt;&lt;br /&gt;public interface EmployeeDao {&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public List&amp;lt;Employee&amp;gt; getAllOrderByName();&lt;br /&gt; /**&lt;br /&gt;  * @param employee&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public Employee create(Employee employee);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employee&lt;br /&gt;  */&lt;br /&gt; public void update(Employee employee);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employeeId&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public Employee load(int employeeId);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employeeId&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public void delete(Employee employee); &lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.dao.impl;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import javax.ejb.Stateless;&lt;br /&gt;import javax.persistence.EntityManager;&lt;br /&gt;import javax.persistence.PersistenceContext;&lt;br /&gt;&lt;br /&gt;import pl.matt.dao.EmployeeDao;&lt;br /&gt;import pl.matt.model.Employee;&lt;br /&gt;&lt;br /&gt;@Stateless&lt;br /&gt;public class JpaEmployeeDao implements EmployeeDao {&lt;br /&gt;&lt;br /&gt; @PersistenceContext&lt;br /&gt; private EntityManager entityManager;&lt;br /&gt; &lt;br /&gt; @SuppressWarnings("unchecked")&lt;br /&gt; public List&amp;lt;Employee&amp;gt; getAllOrderByName() {&lt;br /&gt;  return entityManager.createNamedQuery("Employee.findAllOrderByName").getResultList();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Employee create(Employee employee) {&lt;br /&gt;  entityManager.persist(employee);&lt;br /&gt;  return employee;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void update(Employee employee) {&lt;br /&gt;  entityManager.merge(employee);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Employee load(int employeeId) {&lt;br /&gt;  return entityManager.find(Employee.class, employeeId);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void delete(Employee employee) {&lt;br /&gt;  entityManager.remove(employee);&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;i może trochę na wyrost warstwę usług biznesowych&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.service;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import pl.matt.model.Employee;&lt;br /&gt;&lt;br /&gt;public interface EmployeeService {&lt;br /&gt; /**&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public List&amp;lt;Employee&amp;gt; getAllOrderByName();&lt;br /&gt; /**&lt;br /&gt;  * @param employee&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public Employee create(Employee employee);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employee&lt;br /&gt;  */&lt;br /&gt; public void update(Employee employee);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employeeId&lt;br /&gt;  * @return&lt;br /&gt;  */&lt;br /&gt; public Employee load(int employeeId);&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * @param employeeId&lt;br /&gt;  */&lt;br /&gt; public void delete(int employeeId);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.service.impl;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import javax.ejb.EJB;&lt;br /&gt;import javax.ejb.Stateless;&lt;br /&gt;&lt;br /&gt;import pl.matt.dao.EmployeeDao;&lt;br /&gt;import pl.matt.model.Employee;&lt;br /&gt;import pl.matt.service.EmployeeService;&lt;br /&gt;&lt;br /&gt;@Stateless&lt;br /&gt;public class EmployeeServiceImpl implements EmployeeService {&lt;br /&gt;&lt;br /&gt; @EJB&lt;br /&gt; private EmployeeDao employeeDao;&lt;br /&gt;&lt;br /&gt; public Employee create(Employee employee) {&lt;br /&gt;  return employeeDao.create(employee);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public List&amp;lt;Employee&amp;gt; getAllOrderByName() {&lt;br /&gt;  return employeeDao.getAllOrderByName();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void update(Employee employee) {&lt;br /&gt;  employeeDao.update(employee);&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Employee load(int employeeId) {&lt;br /&gt;  return employeeDao.load(employeeId);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void delete(int employeeId) {&lt;br /&gt;  Employee employee = load(employeeId);&lt;br /&gt;  if (employee != null) {&lt;br /&gt;   employeeDao.delete(employee);&lt;br /&gt;  }  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ponieważ korzystam z bazy danych za pośrednictwem JPA, nie obejdzie się bez pliku &lt;span class="pre"&gt;META-INF/persistence.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;persistence xmlns="http://java.sun.com/xml/ns/persistence"&lt;br /&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"&lt;br /&gt;  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence&lt;br /&gt;  http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"&amp;gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;   &amp;lt;persistence-unit name="seam_war_project" transaction-type="JTA"&amp;gt;&lt;br /&gt;      &amp;lt;provider&amp;gt;org.hibernate.ejb.HibernatePersistence&amp;lt;/provider&amp;gt;&lt;br /&gt;      &amp;lt;jta-data-source&amp;gt;java:/empAppDatasource&amp;lt;/jta-data-source&amp;gt;&lt;br /&gt;      &amp;lt;properties&amp;gt;&lt;br /&gt;         &amp;lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/&amp;gt;&lt;br /&gt;         &amp;lt;property name="hibernate.hbm2ddl.auto" value="update"/&amp;gt;&lt;br /&gt;         &amp;lt;property name="hibernate.show_sql" value="true"/&amp;gt;&lt;br /&gt;      &amp;lt;/properties&amp;gt;&lt;br /&gt;   &amp;lt;/persistence-unit&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/persistence&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;potrzebuję też źródła danych (Data Source) &lt;span class="pre"&gt;empAppDatasource&lt;/span&gt;. Tworzę ją w pliku &lt;span class="pre"&gt;empApp-ds.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!DOCTYPE datasources&lt;br /&gt;    PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"&lt;br /&gt;    "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd"&amp;gt;&lt;br /&gt;    &lt;br /&gt;&amp;lt;datasources&amp;gt;&lt;br /&gt;   &lt;br /&gt;   &amp;lt;local-tx-datasource&amp;gt;&lt;br /&gt;      &amp;lt;jndi-name&amp;gt;empAppDatasource&amp;lt;/jndi-name&amp;gt;&lt;br /&gt;        &amp;lt;connection-url&amp;gt;jdbc:mysql://localhost:3306/jpabasics?characterEncoding=latin2&amp;lt;/connection-url&amp;gt; &lt;br /&gt;        &amp;lt;driver-class&amp;gt;com.mysql.jdbc.Driver&amp;lt;/driver-class&amp;gt; &lt;br /&gt;        &amp;lt;user-name&amp;gt;root&amp;lt;/user-name&amp;gt; &lt;br /&gt;        &amp;lt;password&amp;gt;root&amp;lt;/password&amp;gt; &lt;br /&gt;   &amp;lt;/local-tx-datasource&amp;gt;&lt;br /&gt;    &lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;który umieszczam w katalogu &lt;span class="pre"&gt;server/default/deploy/&lt;/span&gt; JBossa.&lt;br /&gt;&lt;br /&gt;Przejdźmy do aplikacji JSF. Tworzę ją wybierając z menu Eclipse &lt;span class="pre"&gt;File / New / Other... / JSF Project&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SYy56-Q1sMI/AAAAAAAAAMU/orJSemDri2M/s1600-h/4jsf.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 315px;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SYy56-Q1sMI/AAAAAAAAAMU/orJSemDri2M/s320/4jsf.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815284305408194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Jako środowisko JSF ustawiam JSF 1.2 z &lt;a href="https://facelets.dev.java.net/"&gt;Faceletami&lt;/a&gt;, podaję nazwę projektu &lt;span class="pre"&gt;jsfModule&lt;/span&gt; i klikam &lt;span class="pre"&gt;Finish&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;W projekcie tworzę prosty szablon stron &lt;span class="pre"&gt;WebContent/templates/common.xhtml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt; xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt; xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt; xmlns:f="http://java.sun.com/jsf/core"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;&amp;lt;ui:insert name="pageTitle"&amp;gt;Page Title&amp;lt;/ui:insert&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;style type="text/css"&amp;gt;&lt;br /&gt;body {&lt;br /&gt; font-family: Verdana, Arial, Helvetica, sans-serif;&lt;br /&gt; font-size: 14px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.header {&lt;br /&gt; font-family: Verdana, Arial, Helvetica, sans-serif;&lt;br /&gt; font-size: 18px;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.bottom {&lt;br /&gt; font-family: Verdana, Arial, Helvetica, sans-serif;&lt;br /&gt; font-size: 9px;&lt;br /&gt; text-align: center;&lt;br /&gt; vertical-align: middle;&lt;br /&gt; color: #8E969D;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;td.column1 {&lt;br /&gt; width: 15%;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;td.column2 {&lt;br /&gt; width: 25%;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;td.column3 {&lt;br /&gt; width: 60%;&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body bgcolor="#ffffff"&amp;gt;&lt;br /&gt;&amp;lt;table style="border: 1px solid #CAD6E0" align="center" cellpadding="0"&lt;br /&gt; cellspacing="0" border="0" width="400"&amp;gt;&lt;br /&gt; &amp;lt;tbody&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;tr&amp;gt;&lt;br /&gt;   &amp;lt;td class="header" height="42" align="center" valign="middle"&lt;br /&gt;    width="100%" bgcolor="#E4EBEB"&amp;gt;&amp;lt;ui:insert name="pageHeader"&amp;gt;Page Header&amp;lt;/ui:insert&amp;gt;&lt;br /&gt;   &amp;lt;/td&amp;gt;&lt;br /&gt;  &amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;tr&amp;gt;&lt;br /&gt;   &amp;lt;td height="1" width="100%" bgcolor="#CAD6E0"&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;  &amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;tr&amp;gt;&lt;br /&gt;   &amp;lt;td width="100%" colspan="2"&amp;gt;&lt;br /&gt;   &amp;lt;table width="100%" style="height: 150px" align="left"&lt;br /&gt;    cellpadding="0" cellspacing="0" border="0"&amp;gt;&lt;br /&gt;    &amp;lt;tbody&amp;gt;&lt;br /&gt;     &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;td align="left" width="800px" valign="middle"&amp;gt;&amp;lt;ui:insert&lt;br /&gt;       name="body"&amp;gt;Page Body&amp;lt;/ui:insert&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;     &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;/tbody&amp;gt;&lt;br /&gt;   &amp;lt;/table&amp;gt;&lt;br /&gt;   &amp;lt;/td&amp;gt;&lt;br /&gt;  &amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;tr&amp;gt;&lt;br /&gt;   &amp;lt;td colspan="2" valign="bottom" height="1" width="100%"&lt;br /&gt;    bgcolor="#CAD6E0"&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;  &amp;lt;/tr&amp;gt;&lt;br /&gt; &amp;lt;/tbody&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;plik wyświetlający listę pracowników &lt;span class="pre"&gt;WebContent/pages/employeeList.xhtml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt; xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt; xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt; xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt; xmlns:c="http://java.sun.com/jstl/core"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ui:composition template="/templates/common.xhtml"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="pageTitle"&amp;gt;Lista pracowników&amp;lt;/ui:define&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="pageHeader"&amp;gt;Lista pracowników&amp;lt;/ui:define&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="body"&amp;gt;&lt;br /&gt;  &amp;lt;div style="text-align: center"&amp;gt;&amp;lt;h:form&amp;gt;&lt;br /&gt;   &amp;lt;h:commandLink action="ADD_EMP" value="Dodaj pracownika" /&amp;gt;&lt;br /&gt;   &amp;lt;br /&amp;gt;&lt;br /&gt;   &amp;lt;br /&amp;gt;&lt;br /&gt;   &amp;lt;ui:repeat value="#{employeeBean.employees}" var="emp"&amp;gt;&lt;br /&gt;    &amp;lt;h:outputLink value="editEmployee.jsf?employeeId=#{emp.id}"&amp;gt;&lt;br /&gt;     &amp;lt;h:outputText value="#{emp.firstName} #{emp.lastName}" /&amp;gt;&lt;br /&gt;    &amp;lt;/h:outputLink&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value=" " /&amp;gt;&lt;br /&gt;    &amp;lt;h:commandLink action="#{employeeBean.delete}" value="[usuń]"&amp;gt;&lt;br /&gt;     &amp;lt;f:param name="toDelete" value="#{emp.id}" /&amp;gt;&lt;br /&gt;    &amp;lt;/h:commandLink&amp;gt;&lt;br /&gt;    &amp;lt;br /&amp;gt;&lt;br /&gt;   &amp;lt;/ui:repeat&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/h:form&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;/ui:define&amp;gt;&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;oraz plik umożliwiający edycję pojedynczego pracownika &lt;span class="pre"&gt;WebContent/pages/editEmployee.xhtml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt; xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt; xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt; xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt; xmlns:c="http://java.sun.com/jstl/core"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ui:composition template="/templates/common.xhtml"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="pageTitle"&amp;gt;Edycja&amp;lt;/ui:define&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="pageHeader"&amp;gt;Edycja pracownika&amp;lt;/ui:define&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;ui:define name="body"&amp;gt;&lt;br /&gt;  &amp;lt;h:outputLink value="employeeList.jsf"&amp;gt;Powrót&amp;lt;/h:outputLink&amp;gt;&lt;br /&gt;  &amp;lt;h:form id="employeeForm"&amp;gt;&lt;br /&gt;   &amp;lt;h:inputHidden id="employeeId" value="#{employeeBean.employee.id}" /&amp;gt;&lt;br /&gt;   &amp;lt;h:panelGrid columns="3" width="800"&lt;br /&gt;   columnClasses="column1,column2,column3"&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="Imię" /&amp;gt;&lt;br /&gt;    &amp;lt;h:inputText value="#{employeeBean.employee.firstName}"&lt;br /&gt;     id="firstName" required="true" /&amp;gt;&lt;br /&gt;    &amp;lt;h:message for="firstName" style="color:red;" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="Nazwisko" /&amp;gt;&lt;br /&gt;    &amp;lt;h:inputText value="#{employeeBean.employee.lastName}" id="lastName"&lt;br /&gt;     required="true" /&amp;gt;&lt;br /&gt;    &amp;lt;h:message for="lastName" style="color:red;" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="Login" /&amp;gt;&lt;br /&gt;    &amp;lt;h:inputText value="#{employeeBean.employee.username}" id="username"&lt;br /&gt;     required="true" /&amp;gt;&lt;br /&gt;    &amp;lt;h:message for="username" style="color:red;" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="haslo" /&amp;gt;&lt;br /&gt;    &amp;lt;h:inputSecret id="password"&lt;br /&gt;     value="#{employeeBean.employee.password}" required="true" redisplay="true" /&amp;gt; &lt;br /&gt;    &amp;lt;h:message for="password" style="color:red;" /&amp;gt;&lt;br /&gt;    &amp;lt;h:commandButton action="#{employeeBean.save}" value="zapisz" /&amp;gt;&lt;br /&gt;   &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;   &amp;lt;h:outputLink value="employeeList.jsf"&amp;gt;Powrót&amp;lt;/h:outputLink&amp;gt;&lt;br /&gt;  &amp;lt;/h:form&amp;gt;&lt;br /&gt; &amp;lt;/ui:define&amp;gt;&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Potrzebne będzie też ziarno zarządzane JSF&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package pl.matt.view;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import javax.ejb.EJB;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;&lt;br /&gt;import pl.matt.model.Employee;&lt;br /&gt;import pl.matt.service.EmployeeService;&lt;br /&gt;&lt;br /&gt;public class EmployeeBean {&lt;br /&gt;&lt;br /&gt; private List&amp;lt;Employee&amp;gt; employees;&lt;br /&gt; private Employee employee;&lt;br /&gt; private Integer employeeId;&lt;br /&gt; &lt;br /&gt; @EJB(name="eeProject/EmployeeServiceImpl/local")&lt;br /&gt; private EmployeeService employeeService;&lt;br /&gt; &lt;br /&gt; public List&amp;lt;Employee&amp;gt; getEmployees() {&lt;br /&gt;  if (employees == null) {&lt;br /&gt;   employees = employeeService.getAllOrderByName();&lt;br /&gt;  }&lt;br /&gt;  return employees;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Employee getEmployee() {&lt;br /&gt;  if (employee == null) {&lt;br /&gt;   if (employeeId != null) {&lt;br /&gt;    employee = employeeService.load(employeeId);&lt;br /&gt;   } else {&lt;br /&gt;    employee = new Employee();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return employee;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setEmployee(Employee employee) {&lt;br /&gt;  this.employee = employee;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public String save() {&lt;br /&gt;  if (employee.getId() &gt; 0) {&lt;br /&gt;   employeeService.update(employee);&lt;br /&gt;  } else {&lt;br /&gt;   employeeService.create(employee);&lt;br /&gt;  }&lt;br /&gt;  employees = null;&lt;br /&gt;  return "LIST_EMP";&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Integer getEmployeeId() {&lt;br /&gt;  return employeeId;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setEmployeeId(Integer employeeId) {&lt;br /&gt;  this.employeeId = employeeId;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public String delete() {&lt;br /&gt;  System.out.println("EmployeeBean.delete()");&lt;br /&gt;  Integer id = Integer.valueOf(&lt;br /&gt;    FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("toDelete"));&lt;br /&gt;  if (id != null) {&lt;br /&gt;   employeeService.delete(id);&lt;br /&gt;  }&lt;br /&gt;  employees = null;&lt;br /&gt;  return "LIST_EMP";&lt;br /&gt; } &lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;JBoss umieszcza w interfejsie JNDI ziarna EJB korzystając z trochę dziwnej konwencji:&lt;br /&gt;nazwaModułu/klasaZiarna/local|remote stąd konieczność podania parametru &lt;span class="pre"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="java:nocontrols"&gt;@EJB(name="eeProject/EmployeeServiceImpl/local")&lt;/pre&gt;&lt;br /&gt;przy adnotacji @EJB.&lt;br /&gt;Jak będzie wyglądała sytuacja w momencie, kiedy ziarno EJB będzie implementowało kilka interfejsów zdalnych lub lokalnych? Niestety nie mam pojęca.&lt;br /&gt;&lt;br /&gt;Do kompletu brakuje jeszcze pliku &lt;span class="pre"&gt;WebContent/WEB-INF/faces-config.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt; xmlns:xi="http://www.w3.org/2001/XInclude"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"&amp;gt;&lt;br /&gt; &amp;lt;managed-bean&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-name&amp;gt;employeeBean&amp;lt;/managed-bean-name&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-class&amp;gt;pl.matt.view.EmployeeBean&amp;lt;/managed-bean-class&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-scope&amp;gt;request&amp;lt;/managed-bean-scope&amp;gt;&lt;br /&gt;  &amp;lt;managed-property&amp;gt;&lt;br /&gt;   &amp;lt;property-name&amp;gt;employeeId&amp;lt;/property-name&amp;gt;&lt;br /&gt;   &amp;lt;value&amp;gt;#{param.employeeId}&amp;lt;/value&amp;gt;&lt;br /&gt;  &amp;lt;/managed-property&amp;gt;&lt;br /&gt; &amp;lt;/managed-bean&amp;gt;&lt;br /&gt; &amp;lt;navigation-rule&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;ADD_EMP&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/pages/editEmployee.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;LIST_EMP&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/pages/employeeList.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;&lt;br /&gt; &amp;lt;/navigation-rule&amp;gt;&lt;br /&gt; &amp;lt;application&amp;gt;&lt;br /&gt;  &amp;lt;view-handler&amp;gt;com.sun.facelets.FaceletViewHandler&amp;lt;/view-handler&amp;gt;&lt;br /&gt; &amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/faces-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;oraz &lt;span class="pre"&gt;WebContent/WEB-INF/web.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;&lt;br /&gt; &amp;lt;description&amp;gt;Facelets StarterKit&amp;lt;/description&amp;gt;&lt;br /&gt; &amp;lt;display-name&amp;gt;jsfModule&amp;lt;/display-name&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;javax.faces.DEFAULT_SUFFIX&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;.xhtml&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;facelets.REFRESH_PERIOD&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;2&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;facelets.DEVELOPMENT&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;javax.faces.STATE_SAVING_METHOD&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;client&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;com.sun.faces.validateXml&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;com.sun.faces.verifyObjects&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;true&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;servlet&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;servlet-class&amp;gt;javax.faces.webapp.FacesServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;  &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt; &amp;lt;/servlet&amp;gt;&lt;br /&gt; &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;url-pattern&amp;gt;*.jsf&amp;lt;/url-pattern&amp;gt;&lt;br /&gt; &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt; &amp;lt;login-config&amp;gt;&lt;br /&gt;  &amp;lt;auth-method&amp;gt;BASIC&amp;lt;/auth-method&amp;gt;&lt;br /&gt; &amp;lt;/login-config&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Aplikacja JSF gotowa. Aplikacja EJB gotowa. Czas je wyswatać i pożenić. Pomoże nam w tym projekt EAR. Z menu kontekstowego Eclipse wybieram zatem &lt;span class="pre"&gt;File / New / Other... / Enterprise Application Project&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SYy6WWvDJ6I/AAAAAAAAAMc/yHLLaHI9Vig/s1600-h/5ear.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 320px;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SYy6WWvDJ6I/AAAAAAAAAMc/yHLLaHI9Vig/s320/5ear.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815754731038626" /&gt;&lt;/a&gt;&lt;br /&gt;Podaję nazwę projektu &lt;span class="pre"&gt;eeProject&lt;/span&gt; klikam 2 razy &lt;span class="pre"&gt;Next &amp;gt;&lt;/span&gt; i wybieram oba stworzone uprzednio moduły. Będą to składowe naszej aplikacji. Dodatkowo zaznaczam opcję &lt;span class="pre"&gt;Generate Deployment Descriptor&lt;/span&gt; i klikam &lt;span class="pre"&gt;Finish&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_62lNJlh-10g/SYy6WsS4nyI/AAAAAAAAAMk/2Qg3wbElv5I/s1600-h/6ear.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 320px;" src="http://1.bp.blogspot.com/_62lNJlh-10g/SYy6WsS4nyI/AAAAAAAAAMk/2Qg3wbElv5I/s320/6ear.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815760518487842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;W tym projekcie znajduje się tylko plik &lt;span class="pre"&gt;EarContent/META-INF/application.xml&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" id="Application_ID" version="5"&amp;gt;&lt;br /&gt;  &amp;lt;module&amp;gt;&lt;br /&gt;    &amp;lt;ejb&amp;gt;ejbProject.jar&amp;lt;/ejb&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;  &amp;lt;module&amp;gt;&lt;br /&gt;    &amp;lt;web&amp;gt;&lt;br /&gt;      &amp;lt;web-uri&amp;gt;jsfModule.war&amp;lt;/web-uri&amp;gt;&lt;br /&gt;      &amp;lt;context-root&amp;gt;jsfModule&amp;lt;/context-root&amp;gt;&lt;br /&gt;    &amp;lt;/web&amp;gt;&lt;br /&gt;  &amp;lt;/module&amp;gt;&lt;br /&gt;&amp;lt;/application&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Plik ten opisuje moduły naszej aplikacji. Moduł webowy &lt;span class="pre"&gt;jsfModule&lt;/span&gt; i moduł EJB &lt;span class="pre"&gt;ejbProject.jar&lt;/span&gt;. Wdrożenie aplikacji pozostawiam wtyczce JBoss Tools. Startuję więc serwer i... aplikacja działa.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SYy6WjjJQQI/AAAAAAAAAMs/y23_UHXCqsA/s1600-h/7app.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 154px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SYy6WjjJQQI/AAAAAAAAAMs/y23_UHXCqsA/s320/7app.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5299815758170767618" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Kod źródłowy powyższej aplikacji dostępny jest &lt;a href="http://sites.google.com/site/najawie/Home/jsfEjbJboss_20090428.zip"&gt;tutaj&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Cóż, pora jechać na narty...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-7853391648846172166?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/KcwhJ7De32w/aplikacja-jsf-i-ejb-30-w-jboss-tools.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SYy56gmROWI/AAAAAAAAAL0/4IouTxJoh2U/s72-c/0struktura.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/02/aplikacja-jsf-i-ejb-30-w-jboss-tools.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-332969792985303349</guid><pubDate>Mon, 26 Jan 2009 16:27:00 +0000</pubDate><atom:updated>2009-01-31T13:14:58.158-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">EJB 3</category><category domain="http://www.blogger.com/atom/ns#">glassfish</category><title>gry i zabawy ze szklaną rybką</title><description>Zdarzyło się tak, że w nowym 2009 roku wpadła w moje śliskie łapska niezła cegła.&lt;br /&gt;&lt;a href="http://www.theserverside.com/tt/books/wiley/masteringEJB3/index.tss"&gt;Mastering Enterprise JavaBeans 3.0&lt;/a&gt;. Ponad 700 stron lektury. Jak przebrnę przez wszystko, postaram się zamieścić recenzję. Mam nadzieję, że wyrobię się przed rokiem pańskim 2010.&lt;br /&gt;&lt;a href="http://www.theserverside.com/tt/books/wiley/masteringEJB3/index.tss"&gt;Mastering Enterprise JavaBeans 3.0&lt;/a&gt; traktuje całkiem szczegółowo o EJB 3.0. Czas zatem rozpocząć wycieczkę w tamte rejony. Wycieczki są fajne, wszak podróże kształcą. Jednak wycieczki w pojedynkę bywają nudne. Na szczęście udało mi się namówić do wyprawy serwer aplikacyjny &lt;a href="https://glassfish.dev.java.net/"&gt;GlassFish&lt;/a&gt;. We dwójkę raźniej.&lt;br /&gt;&lt;br /&gt;Zacząłem od instalacji mojego towarzysza. Pobrałem serwer &lt;a href="http://java.net/download/javaee5/v2.1_branch/promoted/Linux/glassfish-installer-v2.1-b60e-linux.jar"&gt;GlassFish 2&lt;/a&gt;. Co ciekawe, do instalacji nie wystarczy odpalenie pobranego pliku &lt;span class="pre"&gt;glassfish-installer-v2.1-b60e-linux.jar&lt;/span&gt;. Aby w pełni zainstalować serwer, należy jeszcze uruchomić antem znajdujący się w jego katalogu głównym plik &lt;span class="pre"&gt;setup.xml&lt;/span&gt;. Czyli:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code"&gt;  &lt;br /&gt;java -jar glassfish-installer-v2.1-b60e-linux.jar&lt;br /&gt;cd glassfish&lt;br /&gt;ant -f setup.xml&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Dopiero teraz możemy się cieszyć w pełni działającym serwerem Java EE.&lt;br /&gt;Żeby go uruchomić, wchodzę do katalogu &lt;span class="pre"&gt;bin&lt;/span&gt; GlassFisha i startuję domenę &lt;span class="pre"&gt;domain1&lt;/span&gt;.&lt;br /&gt;&lt;pre name="code"&gt; &lt;br /&gt;./asadmin start-domain domain1&lt;br /&gt;Starting Domain domain1, please wait.&lt;br /&gt;Log redirected to /opt/glassfish/domains/domain1/logs/server.log.&lt;br /&gt;Redirecting output to /opt/glassfish/domains/domain1/logs/server.log&lt;br /&gt;Domain domain1 is ready to receive client requests. Additional services are being started in background. &lt;br /&gt;Domain [domain1] is running [Sun Java System Application Server 9.1_02 (build b04-fcs)] with its configuration and logs at: [/opt/glassfish/domains].&lt;br /&gt;Admin Console is available at [http://localhost:4848].&lt;br /&gt;Use the same port [4848] for "asadmin" commands.&lt;br /&gt;User web applications are available at these URLs:&lt;br /&gt;[http://localhost:8080 https://localhost:8181 ].&lt;br /&gt;Following web-contexts are available:&lt;br /&gt;[/web1  /__wstx-services ].&lt;br /&gt;Standard JMX Clients (like JConsole) can connect to JMXServiceURL:&lt;br /&gt;[service:jmx:rmi:///jndi/rmi://jt-laptop:8686/jmxrmi] for domain management purposes.&lt;br /&gt;Domain listens on at least following ports for connections:&lt;br /&gt;[8080 8181 4848 3700 3820 3920 8686 ].&lt;br /&gt;Domain does not support application server clusters and other standalone instances.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Wchodzę na stronę &lt;br /&gt;&lt;span class="pre"&gt;http://localhost:8080&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SX785RGUwQI/AAAAAAAAAKc/1qO8u-rMdlg/s1600-h/blog01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SX785RGUwQI/AAAAAAAAAKc/1qO8u-rMdlg/s320/blog01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5295948272606953730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wszystko ładnie działa.&lt;br /&gt;&lt;br /&gt;W EJB 3.0, mamy 3.0 rodzaje ziaren. Ziarna sesyjne, ziarna sterowane wiadomością i ziarna encyjne, które są, ale jakby ich nie było... Dziś zajmę się tymi pierwszymi i to tylko częściowo. Ziarna sesyjne bowiem występują w dwóch odmianach, stanowej i bezstanowej. Zarówno jedne, jak i drugie zazwyczaj wykonują tak zwaną logikę biznesową. Robią to niby wydajnie, skalowalnie, och i ach, ale moim skromnym zdaniem siła EJB ukryta jest tutaj zupełnie gdzie indziej. Otóż w sposób poniekąd przezroczysty dla programisty pozwalają na zarówno lokalne jak i zdalne wywoływanie usług. Możemy je wykonywać w ramach jednej maszyny wirtualnej (np. aplikacja webowa) jak i z osobnych (gruby klient). Zobaczmy jak to działa.&lt;br /&gt;&lt;br /&gt;Żeby nie było za nudno, stworzę 2 aplikacje EJB i odpalę je w różnych domenach GlassFisha. Następnie "grubym" klientem wykonam metody jednego i drugiego ziarna. Do dzieła.&lt;br /&gt;&lt;br /&gt;EJB 3.0 uprościło się znacznie od zamierzchłych czasów wersji 2.x. Żeby stworzyć ziarno sesyjne i jego zdalny interfejs, potrzebuję tylko... interfejs i jego implementację.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;  &lt;br /&gt;interfejs Hello.java&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public interface Hello {&lt;br /&gt;&lt;br /&gt;    public String hello();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;i jego implementacja&lt;br /&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Remote(Hello.class)&lt;br /&gt;public class HelloBean implements Hello {&lt;br /&gt;              &lt;br /&gt;    public String hello() {&lt;br /&gt;        return "domain1";&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;@Stateless&lt;/span&gt; oznacza, że jest to ziarno bezstanowe&lt;br /&gt;&lt;span class="pre"&gt;@Remote(Hello.class)&lt;/span&gt; informuje kontener EJB (czyli w moim przypadku GlassFisha), że jest to imlpementacja zdalnego interfejsu &lt;span class="pre"&gt;Hello&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;No i to już wszystko.&lt;br /&gt;&lt;!--&lt;br /&gt; Prawie, bowiem aplikacja EJB wymaga również deskryptora EJB, pliku &lt;span class="pre"&gt;ejb-jar.xml&lt;/span&gt;. W tym przypadku będzie to w zasadzie pusty plik, wszystkie niezbędne informacje są zawarte w adnotacjach.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;  &lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"&lt;br /&gt; version="3.0"&lt;br /&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;enterprise-beans&amp;gt;&lt;br /&gt; &amp;lt;/enterprise-beans&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/ejb-jar&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Plik &lt;span class="pre"&gt;ejb-jar.xml&lt;/span&gt; powinien się znaleźć w katalogu &lt;span class="pre"&gt;META-INF&lt;/span&gt; aplikacji EJB.&lt;br /&gt;--&gt;&lt;br /&gt;Powyższą aplikację EJB buduję Mavenem 2.&lt;br /&gt;Oto pom.xml:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;  &lt;br /&gt;&amp;lt;project &lt;br /&gt;  xmlns="http://maven.apache.org/POM/4.0.0" &lt;br /&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;pl.matt&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;ejb3-slsb&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;packaging&amp;gt;ejb&amp;lt;/packaging&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;properties&amp;gt;    &lt;br /&gt;    &amp;lt;JAVA_HOME&amp;gt;/usr/lib/jvm/java-6-sun&amp;lt;/JAVA_HOME&amp;gt;&lt;br /&gt;  &amp;lt;/properties&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;dependencies&amp;gt;        &lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.apache.geronimo.specs&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;geronimo-ejb_3.0_spec&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;   &lt;br /&gt;  &amp;lt;/dependencies&amp;gt;    &lt;br /&gt;&lt;br /&gt;  &amp;lt;build&amp;gt; &lt;br /&gt;    &amp;lt;finalName&amp;gt;ejb3-slsb&amp;lt;/finalName&amp;gt;&lt;br /&gt;    &amp;lt;directory&amp;gt;/tmp/mvn-target/&amp;lt;/directory&amp;gt;&lt;br /&gt;    &amp;lt;resources&amp;gt;&lt;br /&gt;      &amp;lt;resource&amp;gt;&lt;br /&gt;        &amp;lt;targetPath&amp;gt;/META-INF&amp;lt;/targetPath&amp;gt;&lt;br /&gt;        &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;&lt;br /&gt;        &amp;lt;directory&amp;gt;${basedir}/src/main/resources&amp;lt;/directory&amp;gt;&lt;br /&gt;        &amp;lt;includes&amp;gt;&lt;br /&gt;          &amp;lt;include&amp;gt;ejb-jar.xml&amp;lt;/include&amp;gt;&lt;br /&gt;        &amp;lt;/includes&amp;gt;        &lt;br /&gt;      &amp;lt;/resource&amp;gt;      &lt;br /&gt;    &amp;lt;/resources&amp;gt;    &lt;br /&gt;    &amp;lt;plugins&amp;gt;&lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;maven-ejb-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;configuration&amp;gt;&lt;br /&gt;          &amp;lt;ejbVersion&amp;gt;3.0&amp;lt;/ejbVersion&amp;gt;&lt;br /&gt;        &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;          &lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;configuration&amp;gt;&lt;br /&gt;          &amp;lt;verbose&amp;gt;true&amp;lt;/verbose&amp;gt;&lt;br /&gt;          &amp;lt;fork&amp;gt;true&amp;lt;/fork&amp;gt;&lt;br /&gt;          &amp;lt;executable&amp;gt;${JAVA_HOME}/bin/javac&amp;lt;/executable&amp;gt;&lt;br /&gt;          &amp;lt;compilerVersion&amp;gt;1.6&amp;lt;/compilerVersion&amp;gt;&lt;br /&gt;          &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;          &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;          &amp;lt;debug&amp;gt;true&amp;lt;/debug&amp;gt;&lt;br /&gt;          &amp;lt;optimize&amp;gt;false&amp;lt;/optimize&amp;gt;&lt;br /&gt;        &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;                &lt;br /&gt;    &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Zwracam uwagę na &lt;span class="pre"&gt;&amp;lt;packaging&amp;gt;ejb&amp;lt;/packaging&amp;gt;&lt;/span&gt; dzięki czemu Maven zbuduje aplikację EJB.&lt;br /&gt;&lt;br /&gt;Tworzę również drugą aplikację EJB, która odrobinę różni się od pierwszej implementacją interfejsu Hello.class&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Remote(Hello.class)&lt;br /&gt;public class HelloBean implements Hello {&lt;br /&gt;              &lt;br /&gt;    public String hello() {&lt;br /&gt;        return "domain2";&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Aplikację w tej wersji, wdrożę na osobnej domenie serwera GlassFish.&lt;br /&gt;&lt;br /&gt;GlassFish po instalacji skonfigurowany jest z domeną &lt;span class="pre"&gt;domain1&lt;/span&gt;. Nową, o nazwie &lt;span class="pre"&gt;domain2&lt;/span&gt; tworzę poleceniem, które wykonuje w katalogu &lt;span class="pre"&gt;bin&lt;/span&gt; GlassFIsha.&lt;br /&gt;&lt;pre name="code"&gt;  &lt;br /&gt;./asadmin create-domain --adminport 4849 domain2&lt;br /&gt;&lt;br /&gt;Please enter the admin user name&gt;admin&lt;br /&gt;Please enter the admin password&gt;&lt;br /&gt;Please enter the admin password again&gt;&lt;br /&gt;Please enter the master password [Enter to accept the default]:&gt;&lt;br /&gt;Please enter the master password again [Enter to accept the default]:&gt;&lt;br /&gt;Using port 4849 for Admin.&lt;br /&gt;Default port 8080 for HTTP Instance is in use. Using 47039&lt;br /&gt;Default port 7676 for JMS is in use. Using 59523&lt;br /&gt;Default port 3700 for IIOP is in use. Using 38742&lt;br /&gt;Default port 8181 for HTTP_SSL is in use. Using 34802&lt;br /&gt;Default port 3820 for IIOP_SSL is in use. Using 36960&lt;br /&gt;Default port 3920 for IIOP_MUTUALAUTH is in use. Using 48963&lt;br /&gt;Default port 8686 for JMX_ADMIN is in use. Using 55733&lt;br /&gt;Domain being created with profile:developer, as specified by variable AS_ADMIN_PROFILE in configuration file.&lt;br /&gt;The file in given locale [pl_PL] at: [/opt/glassfish/lib/install/templates/locales/pl_PL/index.html] could not be found. Using default (en_US) index.html instead.&lt;br /&gt;Security Store uses: JKS&lt;br /&gt;Domain domain2 created.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Podaję kilka haseł i tyle.&lt;br /&gt;Port konsoli administracyjnej to 4849. Port IIOP, którego używa EJB to 38742.&lt;br /&gt;&lt;br /&gt;Czas wdrożyć aplikacje w obu domenach. Wchodzę więc do panelu administracyjnego, dla domeny &lt;span class="pre"&gt;domain1&lt;/span&gt; będzie to adres:&lt;br /&gt;&lt;span class="pre"&gt;http://localhost:4848/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;dla domeny &lt;span class="pre"&gt;dmain2&lt;/span&gt;&lt;br /&gt;&lt;span class="pre"&gt;http://localhost:4849/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Loguję się jako administrator. Domyślnie jest to użytkonwik o nazwie admin i haśle adminadmin.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_62lNJlh-10g/SX785WSTNmI/AAAAAAAAAKk/6i13Xkj8_Ds/s1600-h/blog02.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://1.bp.blogspot.com/_62lNJlh-10g/SX785WSTNmI/AAAAAAAAAKk/6i13Xkj8_Ds/s320/blog02.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5295948273999361634" /&gt;&lt;/a&gt;&lt;br /&gt;wchodzę w pozycję bocznego menu &lt;span class="pre"&gt;Applications/EJB Modules&lt;/span&gt; i klikam ikonkę &lt;span class="pre"&gt;deploy&lt;/span&gt;.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SX785vMcMCI/AAAAAAAAAKs/UDsQJSJJWso/s1600-h/blog03.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 256px;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SX785vMcMCI/AAAAAAAAAKs/UDsQJSJJWso/s320/blog03.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5295948280685670434" /&gt;&lt;/a&gt;&lt;br /&gt;Jako &lt;span class="pre"&gt;Packaged file to be uploaded to the server&lt;/span&gt; wskazuję plik jar &lt;span class="pre"&gt;ejb3-slsb.jar&lt;/span&gt;. Plik ten utworzył Maven w katalogu &lt;span class="pre"&gt;/tmp/mvn-target/&lt;/span&gt;&lt;br /&gt;Teraz już tylko OK. Aplikacje w różnych wersjach osadzam w obu domenach.&lt;br /&gt;&lt;br /&gt;Czas na klienta EJB, który wywoła metody z ziaren zdnajdujących się w różnych domenach. To już zwykła aplikacja w postaci jednej klasy.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class HelloClients {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  Context ctx = new InitialContext();&lt;br /&gt;  Hello hello = (Hello) ctx.lookup("pl.matt.interfaces.Hello");&lt;br /&gt;&lt;br /&gt;  System.out.println(hello.hello());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Referencję do ziarna EJB otrzymujemy poprzez wywołanie metody &lt;span class="pre"&gt;lookup&lt;/span&gt; na obiekcie &lt;span class="pre"&gt;Context&lt;/span&gt;. Domyślnie konstruktor &lt;span class="pre"&gt;new InitialContext()&lt;/span&gt; będzie korzystał z serwera o adresie &lt;span class="pre"&gt;localhost&lt;/span&gt; i porcie 3700 (w tym przypadku będzie to domena &lt;span class="pre"&gt;domain1&lt;/span&gt;). Aby to zmienić i skorzystać z ziarna w domenie &lt;span class="pre"&gt;domain2&lt;/span&gt;, trzeba skorzystać z konstruktora &lt;span class="pre"&gt;new InitialContext(Properties properties)&lt;/span&gt;.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class HelloClients {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  Context ctx = new InitialContext();&lt;br /&gt;  Hello hello = (Hello) ctx.lookup("pl.matt.interfaces.Hello");&lt;br /&gt;&lt;br /&gt;  System.out.println(hello.hello());&lt;br /&gt;&lt;br /&gt;  Properties properties = new Properties();&lt;br /&gt;  properties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");&lt;br /&gt;  properties.setProperty("org.omg.CORBA.ORBInitialPort", "38742");&lt;br /&gt;&lt;br /&gt;  Context context = new InitialContext(properties);&lt;br /&gt;  hello = (Hello) context.lookup("pl.matt.interfaces.Hello");&lt;br /&gt;  System.out.println(hello.hello());&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;podając odpowiednie ustawienia właściwości &lt;span class="pre"&gt;org.omg.CORBA.ORBInitialHost&lt;/span&gt; i &lt;span class="pre"&gt;org.omg.CORBA.ORBInitialPort&lt;/span&gt; uzyskuję dostęp do ziarna EJB z domeny &lt;span class="pre"&gt;domain2&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Aplikacja wymaga w swojej ścieżce klas plików &lt;span class="pre"&gt;appserv-rt.jar&lt;/span&gt; oraz &lt;span class="pre"&gt;j2ee.jar&lt;/span&gt;, które znajdują się w podkatalogu &lt;span class="pre"&gt;lib&lt;/span&gt; GlassFisha.&lt;br /&gt;&lt;br /&gt;Do kompletu brakuje jeszcze pliku &lt;span class="pre"&gt;pom.xml&lt;/span&gt; aplikacji klienckiej:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;project &lt;br /&gt;  xmlns="http://maven.apache.org/POM/4.0.0" &lt;br /&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;pl.matt&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;ejb3-client&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;properties&amp;gt;    &lt;br /&gt;    &amp;lt;JAVA_HOME&amp;gt;/usr/lib/jvm/java-6-sun&amp;lt;/JAVA_HOME&amp;gt;      &lt;br /&gt;  &amp;lt;/properties&amp;gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;dependencies&amp;gt;&lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;pl.matt&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;ejb3-slsb&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;        &lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.apache.geronimo.specs&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;geronimo-ejb_3.0_spec&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;   &lt;br /&gt;  &amp;lt;/dependencies&amp;gt;    &lt;br /&gt;&lt;br /&gt;  &amp;lt;build&amp;gt; &lt;br /&gt;    &amp;lt;finalName&amp;gt;ejb3-client&amp;lt;/finalName&amp;gt;&lt;br /&gt;    &amp;lt;directory&amp;gt;/tmp/mvn-target/&amp;lt;/directory&amp;gt;&lt;br /&gt;    &amp;lt;plugins&amp;gt;             &lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;configuration&amp;gt;&lt;br /&gt;          &amp;lt;verbose&amp;gt;true&amp;lt;/verbose&amp;gt;&lt;br /&gt;          &amp;lt;fork&amp;gt;true&amp;lt;/fork&amp;gt;&lt;br /&gt;          &amp;lt;executable&amp;gt;${JAVA_HOME}/bin/javac&amp;lt;/executable&amp;gt;&lt;br /&gt;          &amp;lt;compilerVersion&amp;gt;1.6&amp;lt;/compilerVersion&amp;gt;&lt;br /&gt;          &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;&lt;br /&gt;          &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;&lt;br /&gt;          &amp;lt;debug&amp;gt;true&amp;lt;/debug&amp;gt;&lt;br /&gt;          &amp;lt;optimize&amp;gt;false&amp;lt;/optimize&amp;gt;&lt;br /&gt;        &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;                &lt;br /&gt;    &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;zależność&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;pl.matt&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;ejb3-slsb&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;wprowadza widoczność zdalnego interfejsu &lt;span class="pre"&gt;Hello&lt;/span&gt; w aplikacji klienckiej.&lt;br /&gt;&lt;br /&gt;Czas aplikację uruchomić.&lt;br /&gt;Na konsoli wypisuje się odpowiednio:&lt;br /&gt;&lt;pre name="code"&gt;&lt;br /&gt;domain1&lt;br /&gt;domain2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Czyli odpalone zostało ziarno EJB w różnych domenach. Pełen sukces.&lt;br /&gt;&lt;br /&gt;&lt;!--&lt;br /&gt;Kod aplikacji klienckiej znajdzie się tutaj. EJB będzie tutaj.&lt;br /&gt;--&gt;&lt;br /&gt;&lt;br /&gt;Natknąłem się na informacje, że ziarna EJB 3 można uruchamiać klientami napisanymi w technologii EJB 2. Udało się wam to osiągnąć?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-332969792985303349?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/EuIMR8RWaks/gry-i-zabawy-ze-szklana-rybka.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SX785RGUwQI/AAAAAAAAAKc/1qO8u-rMdlg/s72-c/blog01.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2009/01/gry-i-zabawy-ze-szklana-rybka.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-300007549295604840</guid><pubDate>Fri, 26 Dec 2008 20:49:00 +0000</pubDate><atom:updated>2008-12-26T16:06:16.960-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jazoon09</category><title>Jazoon09 już w czerwcu, już w Zurychu</title><description>Na moim lokalnym, &lt;a href="http://groups.google.com/group/warszawa-jug"&gt;WJUGowym&lt;/a&gt; podwórku 2 razy do roku odbwają interesujące konferencje. Wiosenna &lt;a href="http://javarsovia.mocna-kawa.com/"&gt;Jawarsovia&lt;/a&gt; i jesienna &lt;a href="http://warsjava.pl/"&gt;Warsjawa&lt;/a&gt;. Na naszym mniej lokalnym krajowym podwórzu mamy do tego &lt;a href="http://jdd.org.pl/"&gt;Java Developers' Day&lt;/a&gt; oraz nowość, międzynarodowy &lt;a href="http://www.geecon.org/"&gt;GeeCON&lt;/a&gt; (7-8 Maj). Mnie jak dotąd żadnej pozawarszawskiej konferencji nie udało się odwiedzić. Szkoda, wszak podróże kształcą. &lt;br /&gt;&lt;br /&gt;Okazji do zmiany tego stanu rzeczy będzie w nadchodzącym roku co niemiara. Oprócz polskich wydarzeń rokrocznie na jawowym kalendarzu pojawia się kilka europejskich i światowych pozycji. Jedną z nich będzie &lt;a href="http://jazoon.com/"&gt;Jazoon&lt;/a&gt;. Trzydniowa, czerwcowa konferencja w &lt;a href="http://maps.google.com/?q=zurich"&gt;Zurychu&lt;/a&gt;. Byłem już w Zurychu i było całkiem fajnie. Nie od dziś wiadomo, że "jestem umysł ścisły. Mnie się podobają melodie, które już raz słyszałem." więc i miejsca które już widziałem powinny być warte uwagi. Zatem mam nadzieję pojawić się tamże pomiędzy 22 a 25 czerwca 2009 przy okazji konferencji &lt;a href="http://jazoon.com/"&gt;Jazoon&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Niestety program &lt;a href="http://jazoon.com/"&gt;Jazoon09&lt;/a&gt; jest jeszcze wielką &lt;a href="http://jazoon.com/en/conference.html"&gt;niewiadomą&lt;/a&gt;. Znanych jest tylko kilku pierwszych prezenterów: Neal Ford, Danny Coward, Roberto Chinnici, Jérôme Dochez. Pozostali powinni się zgłosić do &lt;a href="http://jazoon.com/en/contribute.html"&gt;15 stycznia&lt;/a&gt;, więc pewnie niedługo poinformuję siebie i was bardziej szczegółowo.&lt;br /&gt;&lt;br /&gt;Nie do końca bezinteresownie, bo mam za to szansę na darmową wejściówkę. Impreza niestety nie jest bezpłatna, uczestnictwo kosztuje &lt;a href="http://jazoon.com/en/register/conferencefees.html"&gt;1450-1810&lt;/a&gt; franków szwajcarskich.&lt;br /&gt;&lt;br /&gt;Wybierasz się na &lt;a href="http://jazoon.com/"&gt;Jazoon09&lt;/a&gt;? Może byłeś na jakiejś innej konferencji? Podziel się opinią w komentarzu!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-300007549295604840?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/FWk80D_r5oI/jazoon09-ju-w-czerwcu-ju-w-zurychu.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/12/jazoon09-ju-w-czerwcu-ju-w-zurychu.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-3821849850705589546</guid><pubDate>Mon, 08 Dec 2008 22:50:00 +0000</pubDate><atom:updated>2008-12-10T13:30:57.783-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Spring Security</category><title>Bezpieczeństwo szybko, łatwo i przyjemnie czyli wstęp do Spring Security</title><description>W znakomitej większości aplikacji internetowych mamy jakiegoś użytkownika, mamy jakieś konto... Gdzieś się rejestrujemy, gdzieś się logujemy i hulaj dusza po serwisie. Podczas projektowania tychże aplikacji, pojawia się dylemat: czy skorzystać z gotowego rozwiązania, czy zaimplementować uwierzytelnianie i autoryzację samemu? Co będzie łatwiejsze, co będzie bezpieczniejsze, co będzie lepsze? Jeśli gotowe rozwiązanie, to jakie? i na co mi taka armata na muchę?&lt;br /&gt;Trudne pytania. Ja na nie odpowiedź mam jednak gotową: &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Niezależny od wykorzystywanego szkieletu aplikacji, posiadający ogromne możliwości a przy tym prosty w użyciu.&lt;br /&gt;&lt;br /&gt;No ale dość tych peanów. Zobaczmy jak to wygląda w akcji. Kilka tygodni temu opisywałem sposób na &lt;a href="http://na-jawie.blogspot.com/2008/11/uprowadzenie-sesji.html"&gt;uprowadzenie sesji HTTP&lt;/a&gt;. Zobaczmy, jak na przykładzie przedstawionej tam aplikacji JSF wprowadzić do projektu &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Najpierw trzeba dodać garść bibliotek:&lt;br /&gt;aopalliance-1.0.jar, spring-context-2.0.8.jar, spring-security-core-tiger-2.0.4.jar, aspectjrt-1.5.4.jar, spring-core-2.0.8.jar, spring-web-2.0.8.jar, spring-aop-2.0.8.jar, spring-dao-2.0.8.jar, spring-beans-2.0.8.jar, spring-security-core-2.0.4.jar&lt;br /&gt;&lt;br /&gt;Wszystkie są do znalezienia w paczce &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=73357&amp;package_id=270072&amp;release_id=630203"&gt;Spring Security 2.0.4&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jeżeli chcemy, aby obiekty napisanej przez nas klasy reprezentowały użytkowników aplikacji, klasa ta musi implementować interfejs &lt;span class="pre"&gt;org.springframework.security.userdetails.UserDetails&lt;/span&gt; która zawiera kilka metod, dzięki którym Spring Security orientuje się kto jest kto i co może zrobić w naszym systemie.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;public interface UserDetails extends Serializable {&lt;br /&gt;    /**&lt;br /&gt;     * Returns the authorities granted to the user. Cannot return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;     *&lt;br /&gt;     * @return the authorities, sorted by natural key (never &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;)&lt;br /&gt;     */&lt;br /&gt;    GrantedAuthority[] getAuthorities();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Returns the password used to authenticate the user. Cannot return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;     *&lt;br /&gt;     * @return the password (never &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;)&lt;br /&gt;     */&lt;br /&gt;    String getPassword();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Returns the username used to authenticate the user. Cannot return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;     *&lt;br /&gt;     * @return the username (never &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;)&lt;br /&gt;     */&lt;br /&gt;    String getUsername();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Indicates whether the user's account has expired. An expired account cannot be authenticated.&lt;br /&gt;     *&lt;br /&gt;     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the user's account is valid (ie non-expired), &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; if no longer valid&lt;br /&gt;     *         (ie expired)&lt;br /&gt;     */&lt;br /&gt;    boolean isAccountNonExpired();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Indicates whether the user is locked or unlocked. A locked user cannot be authenticated.&lt;br /&gt;     *&lt;br /&gt;     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the user is not locked, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; otherwise&lt;br /&gt;     */&lt;br /&gt;    boolean isAccountNonLocked();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Indicates whether the user's credentials (password) has expired. Expired credentials prevent&lt;br /&gt;     * authentication.&lt;br /&gt;     *&lt;br /&gt;     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the user's credentials are valid (ie non-expired), &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; if no longer&lt;br /&gt;     *         valid (ie expired)&lt;br /&gt;     */&lt;br /&gt;    boolean isCredentialsNonExpired();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Indicates whether the user is enabled or disabled. A disabled user cannot be authenticated.&lt;br /&gt;     *&lt;br /&gt;     * @return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; if the user is enabled, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; otherwise&lt;br /&gt;     */&lt;br /&gt;    boolean isEnabled();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Na uwagę zasługuje metoda &lt;span class="pre"&gt;GrantedAuthority[] getAuthorities()&lt;/span&gt;. Zwraca ona tablicę obiektów, reprezentujących role.&lt;br /&gt;&lt;br /&gt;Zmieniam zatem klasę &lt;span class="pre"&gt;pl.matt.model.User&lt;/span&gt; mojej aplikacji tak, aby implementowała ona wymieniony wyżej interfejs:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;public class User implements UserDetails {&lt;br /&gt; /**&lt;br /&gt;  * &lt;br /&gt;  */&lt;br /&gt; private static final long serialVersionUID = 853438034988558585L;&lt;br /&gt; private String login;&lt;br /&gt; private String password;&lt;br /&gt; private int balance;&lt;br /&gt; private GrantedAuthority[] authorities = new GrantedAuthority[] { new GrantedAuthorityImpl("ROLE_USER") };&lt;br /&gt;&lt;br /&gt; public String getLogin() {&lt;br /&gt;  return login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setLogin(String login) {&lt;br /&gt;  this.login = login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getPassword() {&lt;br /&gt;  return password;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setPassword(String password) {&lt;br /&gt;  this.password = password;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public int getBalance() {&lt;br /&gt;  return balance;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setBalance(int balance) {&lt;br /&gt;  this.balance = balance;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public GrantedAuthority[] getAuthorities() {&lt;br /&gt;  return authorities;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public String getUsername() {&lt;br /&gt;  return login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean isAccountNonExpired() {&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean isAccountNonLocked() {&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean isCredentialsNonExpired() {&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean isEnabled() {&lt;br /&gt;  return true;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Do działania modelu bezpieczeństwa niezbędna będzie jeszcze jedna klasa usługowa, implementująca interfejs &lt;span class="pre"&gt;org.springframework.security.userdetails.UserDetailsService&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Zawiera on tylko jedną metodę:&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;    UserDetails loadUserByUsername(String username)&lt;br /&gt;        throws UsernameNotFoundException, DataAccessException;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;która jak sama nazwa wskazuje, ładuje użytkownika o zadanej nazwie.&lt;br /&gt;&lt;br /&gt;Implementacja tego interfejsu w mojej aplikacji to klasa &lt;span class="pre"&gt;UserDetailsServiceImpl&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;public class UserDetailsServiceImpl implements UserDetailsService {&lt;br /&gt;&lt;br /&gt; private UserManager userManager = new UserManager();&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {&lt;br /&gt;  User user = userManager.loadUser(username);&lt;br /&gt;  if (user != null) {&lt;br /&gt;   return user;&lt;br /&gt;  }&lt;br /&gt;  throw new UsernameNotFoundException(username);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;klasę &lt;span class="pre"&gt;UserManager&lt;/span&gt; pozostawiam bez zmian. Z tym, że poprzednio była ona ziarnem zarządzanym JSF. Teraz nie ma już takiej potrzeby.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt; przychodzi z kilkoma implementacjami interfejsu &lt;span class="pre"&gt;UserDetailsServiceImpl&lt;/span&gt;, między innymi z implementacją korzystającą z użytkowników zapisanych w bazie danych lub przechowującą użytkowników w pamięci. Na potrzeby mojej aplikacji żadna z nich nie będzie przydatna.&lt;br /&gt;&lt;br /&gt;Oprócz dwóch powyższych klas stworzyłem również klasę &lt;span class="pre"&gt;UserLoginBean&lt;/span&gt; umożliwiającą wyświetlenie zalogowanego użytkownika na stronie JSF.&lt;br /&gt;&lt;pre name="code" class="java"&gt; &lt;br /&gt;public class UserLoginBean {&lt;br /&gt;&lt;br /&gt; private User loggedUser;&lt;br /&gt; &lt;br /&gt; public User getLoggedUser() {&lt;br /&gt;  if (loggedUser == null) {&lt;br /&gt;   HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();&lt;br /&gt;   UsernamePasswordAuthenticationToken principal = (UsernamePasswordAuthenticationToken) request.getUserPrincipal();&lt;br /&gt;   loggedUser = (User) principal.getPrincipal();&lt;br /&gt;  }&lt;br /&gt;  return loggedUser;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;UserLoginBean&lt;/span&gt; jest ziarnem zarządzanym JSF o zasięgu żądania. Dzięki temu na stronach JSF uzyskuję dostęp do zalogowanego użytkownika poprzez wyrażenie EL &lt;span class="pre"&gt;#{userLoginBean.loggedUser}&lt;/span&gt;&lt;br /&gt;Oto cały &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt; &lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt; xmlns:xi="http://www.w3.org/2001/XInclude"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"&amp;gt;&lt;br /&gt; &amp;lt;managed-bean&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-name&amp;gt;userLoginBean&amp;lt;/managed-bean-name&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-class&amp;gt;pl.matt.UserLoginBean&amp;lt;/managed-bean-class&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-scope&amp;gt;request&amp;lt;/managed-bean-scope&amp;gt;&lt;br /&gt; &amp;lt;/managed-bean&amp;gt;&lt;br /&gt; &amp;lt;navigation-rule&amp;gt;&lt;br /&gt;  &amp;lt;from-view-id&amp;gt;/pages/login.xhtml&amp;lt;/from-view-id&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;success&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/secure/home.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;faliture&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/pages/login.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;&lt;br /&gt; &amp;lt;/navigation-rule&amp;gt;&lt;br /&gt; &amp;lt;application&amp;gt;&lt;br /&gt;  &amp;lt;view-handler&amp;gt;com.sun.facelets.FaceletViewHandler&amp;lt;/view-handler&amp;gt;&lt;br /&gt; &amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/faces-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No i to by było na tyle... gdyby nie potrzeba konfiguracji &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;. Dodaję zatem do pliku web.xml po jednym jeden filtrze, słuchaczu i parametrze konfiguracyjnym&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt; &lt;br /&gt;&lt;br /&gt;   &amp;lt;context-param&amp;gt;&lt;br /&gt;        &amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;&lt;br /&gt;        &amp;lt;param-value&amp;gt;/WEB-INF/applicationContext-security.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;    &amp;lt;/context-param&amp;gt;   &lt;br /&gt;&lt;br /&gt; &amp;lt;listener&amp;gt;&lt;br /&gt;  &amp;lt;listener-class&amp;gt;org.springframework.web.context.ContextLoaderListener&amp;lt;/listener-class&amp;gt;&lt;br /&gt; &amp;lt;/listener&amp;gt;    &lt;br /&gt;    &lt;br /&gt;    &amp;lt;filter&amp;gt;&lt;br /&gt;        &amp;lt;filter-name&amp;gt;springSecurityFilterChain&amp;lt;/filter-name&amp;gt;&lt;br /&gt;        &amp;lt;filter-class&amp;gt;org.springframework.web.filter.DelegatingFilterProxy&amp;lt;/filter-class&amp;gt;&lt;br /&gt;    &amp;lt;/filter&amp;gt;&lt;br /&gt;    &amp;lt;filter-mapping&amp;gt;&lt;br /&gt;      &amp;lt;filter-name&amp;gt;springSecurityFilterChain&amp;lt;/filter-name&amp;gt;&lt;br /&gt;      &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;    &amp;lt;/filter-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wartość parametru &lt;span class="pre"&gt;contextConfigLocation&lt;/span&gt; wskazuje położenie pliku ze szczegułami konfiguracji &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;.&lt;br /&gt;Tworzę zatem i plik &lt;span class="pre"&gt;/WEB-INF/applicationContext-security.xml&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans:beans xmlns="http://www.springframework.org/schema/security"&lt;br /&gt; xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;global-method-security secured-annotations="enabled"&amp;gt;&lt;br /&gt; &amp;lt;/global-method-security&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;http auto-config="true"&amp;gt;&lt;br /&gt;  &amp;lt;intercept-url pattern="/secure/**" access="ROLE_USER" /&amp;gt;&lt;br /&gt;  &amp;lt;intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /&amp;gt;&lt;br /&gt;  &amp;lt;form-login login-page="/pages/login.jsf" /&amp;gt;&lt;br /&gt; &amp;lt;/http&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;beans:bean id="daoAuthenticationProvider"&lt;br /&gt;  class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&amp;gt;&lt;br /&gt;  &amp;lt;beans:property name="userDetailsService" ref="userDetailsService" /&amp;gt;&lt;br /&gt;  &amp;lt;custom-authentication-provider /&amp;gt;&lt;br /&gt; &amp;lt;/beans:bean&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;beans:bean id="userDetailsService" class="pl.matt.security.UserDetailsServiceImpl" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans:beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;W zasadzie na pierwszy rzut oka wiadomo o co chodzi.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt; &lt;br /&gt; &amp;lt;http auto-config="true"&amp;gt;&lt;br /&gt;  &amp;lt;intercept-url pattern="/secure/**" access="ROLE_USER" /&amp;gt;&lt;br /&gt;  &amp;lt;intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /&amp;gt;&lt;br /&gt;  &amp;lt;form-login login-page="/pages/login.jsf" /&amp;gt;&lt;br /&gt; &amp;lt;/http&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;&amp;lt;http auto-config="true"&amp;gt;&lt;/span&gt; włącza predefiniowane ustawienia konfiguracyjne, z których zmieniam położenie formularza do logowania na &lt;span class="pre"&gt;/pages/login.jsf&lt;/span&gt;, oraz określam które urle będą dostępne dla użytkowników o określonych uprawnieniach. W moim przypadku strony zaczynające się od &lt;span class="pre"&gt;/secure/&lt;/span&gt; będą widoczne tylko dla użytkowników o roli &lt;span class="pre"&gt;ROLE_USER&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W duecie &lt;span class="pre"&gt;daoAuthenticationProvider&lt;/span&gt; i &lt;span class="pre"&gt;userDetailsService&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt; &lt;br /&gt; &amp;lt;beans:bean id="daoAuthenticationProvider"&lt;br /&gt;  class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&amp;gt;&lt;br /&gt;  &amp;lt;beans:property name="userDetailsService" ref="userDetailsService" /&amp;gt;&lt;br /&gt;  &amp;lt;custom-authentication-provider /&amp;gt;&lt;br /&gt; &amp;lt;/beans:bean&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;beans:bean id="userDetailsService" class="pl.matt.security.UserDetailsServiceImpl" &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;który generalnie wskazuje, której usługi będziemy używać do autentykacji użytkowników (można używać wielu usług jednocześnie) na uwagę zasługuje znacznik &lt;span class="pre"&gt;&amp;lt;custom-authentication-provider /&amp;gt;&lt;/span&gt;. Imformuje on &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;, że nie będziemy używać domyślnej usługi przechowującej użytkowników w pamięci, ale naszej implementacji.&lt;br /&gt;&lt;br /&gt;Zobaczmy jeszcze stronę logowania  &lt;span class="pre"&gt;login.xhtml&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt; &lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt; xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt; xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt; xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt; xmlns:c="http://java.sun.com/jstl/core"&amp;gt;&lt;br /&gt;&amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt;&amp;lt;ui:composition template="/templates/common.xhtml"&amp;gt;&lt;br /&gt; &amp;lt;ui:define name="pageTitle"&amp;gt;Login form&amp;lt;/ui:define&amp;gt;&lt;br /&gt; &amp;lt;ui:define name="pageHeader"&amp;gt;Proszę się zalogować&amp;lt;/ui:define&amp;gt;&lt;br /&gt; &amp;lt;ui:define name="body"&amp;gt;&lt;br /&gt;  &amp;lt;form action="../j_spring_security_check"&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;   &amp;lt;tr&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;User:&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;&amp;lt;input type='text' name='j_username' /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;   &amp;lt;/tr&amp;gt;&lt;br /&gt;   &amp;lt;tr&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;Password:&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;&amp;lt;input type='password' name='j_password' /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;   &amp;lt;/tr&amp;gt;&lt;br /&gt;   &amp;lt;tr&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;&amp;lt;input type="checkbox" name="_spring_security_remember_me" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;td&amp;gt;Don't ask for my password for two weeks&amp;lt;/td&amp;gt;&lt;br /&gt;   &amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;tr&amp;gt;&lt;br /&gt;    &amp;lt;td colspan='2'&amp;gt;&amp;lt;input name="submit" type="submit" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;   &amp;lt;/tr&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;  &amp;lt;/form&amp;gt;&lt;br /&gt; &amp;lt;/ui:define&amp;gt;&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Specjalna wartość parametru &lt;span class="pre"&gt;action&lt;/span&gt; formularza, oraz jego nazwy pól pozwalają się zorientować &lt;a href="http://static.springframework.org/spring-security/site/"&gt;Spring Security&lt;/a&gt;, że podjęto próbę logowania.&lt;br /&gt;&lt;br /&gt;Całą aplikację można pobrać &lt;a href="http://sites.google.com/site/najawie/Home/ss-20081210.zip"&gt;tutaj&lt;/a&gt;.&lt;br /&gt;Dla chętnych pozostawiam sprawdzenie odporności tej wersji na atak uprowadzenia sesji i inne ataki.&lt;br /&gt;&lt;br /&gt;To by zatem było na tyle. Niewielkim nakładem pracy dodałem bardzo potężne narzędzie do zarządzania bezpieczeństwem aplikacji. Co prawda wykorzystałem tylko mały fragment jego możliwości, ale muszę jeszcze mieć o czym pisać na blogu...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-3821849850705589546?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/zdaGAWEb6yw/bezpieczestwo-szybko-atwo-i-przyjemnie.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/12/bezpieczestwo-szybko-atwo-i-przyjemnie.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-5760441361479953798</guid><pubDate>Thu, 27 Nov 2008 19:50:00 +0000</pubDate><atom:updated>2008-11-27T12:33:48.840-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">warsjawa</category><title>Się działo się... Warsjawa Eclipse DemoCamp 2008</title><description>Było minęło... ale, że było fajnie, opiszę pokrótce jak to miało miejsce.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://warsjawa.pl"&gt;Warsjawa Eclipse DemoCamp 2008&lt;/a&gt;, odbyła się w ubiegłą sobotę, 22 listopada na terenie wydziału MIMUW Uniwersytetu Warszawskiego. Swoją obecnością zaszczyciło nas ponad 150 słuchaczy, ale zacznijmy od początku (relacja z czuba i na żywo)...&lt;br /&gt;&lt;br /&gt;a na początku był &lt;a href="http://jdn.pl/blog/88"&gt;Waldemar Kot&lt;/a&gt;. Waldi po nieudanych inwestycjach w przemysł księgarski&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SS77gSkElDI/AAAAAAAAAJY/Z6z6QoyjKHw/s1600-h/waldi.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SS77gSkElDI/AAAAAAAAAJY/Z6z6QoyjKHw/s320/waldi.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5273428745854948402" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;powrócił w klimaty bliższe naszemu sercu. Jego prezentację dotyczącą mechanizmu Publish-Subscribe wysłuchała pełna sala.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh5.ggpht.com/_wSeV_DMR2uA/SSvDeASZD7I/AAAAAAAAB4g/pm8KguiyeKY/s800/IMG_0138.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 800px; height: 600px;" src="http://lh5.ggpht.com/_wSeV_DMR2uA/SSvDeASZD7I/AAAAAAAAB4g/pm8KguiyeKY/s800/IMG_0138.JPG" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Było jak zwykle u Waldiego. Ciekawie, fachowo i konkretnie. Po prostu rewelacja. Choć w sobotę rano nikt jeszcze w to nie wierzył, poziom widowiska nie opadł do sameog końca. Kolejna prelekcja "Taking SQL IDEs from the Stone Age to the 21st century" Wassima Mełhema tylko podsyciła apetyt.&lt;br /&gt;&lt;br /&gt;Szczęście w nieszczęściu, że zaraz potem był czas na przerwę. Obiadową. Na każdego czekał kotlecik oraz zupka. Mniam...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh6.ggpht.com/_wSeV_DMR2uA/SSu4wh00msI/AAAAAAAABmw/Aqm4k6O2XSQ/s800/IMG_0208.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 800px; height: 600px;" src="http://lh6.ggpht.com/_wSeV_DMR2uA/SSu4wh00msI/AAAAAAAABmw/Aqm4k6O2XSQ/s800/IMG_0208.JPG" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To co zapowiadała pierwsza część spotkania w drugiej stało się faktem. Worek z bramkami się rozwiązał. Co prawda Eclipse RPC nie do końca zmieścił się w przeglądarce Jacek Pospychały, ale to był dopiero początek emocji. Telekomunikacja w Javie pełna była pełna ostrej walki bark w bark Tomasz Zieleniewskiego oraz Waldemara Kota. Na szczęście sędziowie byli stanowczy i konsekwentni. O żadnych zadymach nie mogło być zatem mowy. W dogrywce 2 krótsze prezentacje - Dojo Toolkit Łukasza Lenarta oraz Spring Dynamic Modules Agaty i Jacka Laskowskich i każdy mógł być zadowolony ze zwycięskiego remisu.&lt;br /&gt;&lt;br /&gt;Tenże uczciliśmy w Lolku. Co prawda nikt się nie spodziewał tylu zwycięzców i miejsc brakło, ale cóż. Taka okazja nie trafia się na co dzień...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SS8DJHOtR_I/AAAAAAAAAKA/uE2N4xSkHpY/s1600-h/impra.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SS8DJHOtR_I/AAAAAAAAAKA/uE2N4xSkHpY/s320/impra.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5273437143768582130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Było super. Pozostaje mi tylko mieć nadzieję, że to nie pierwszy i nie ostatni raz.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-5760441361479953798?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/g-dG7GquVkk/si-dziao-si-warsjawa-eclipse-democamp.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SS77gSkElDI/AAAAAAAAAJY/Z6z6QoyjKHw/s72-c/waldi.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/11/si-dziao-si-warsjawa-eclipse-democamp.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-4987271258747344000</guid><pubDate>Mon, 17 Nov 2008 17:52:00 +0000</pubDate><atom:updated>2008-11-17T10:07:44.297-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">warsjawa</category><category domain="http://www.blogger.com/atom/ns#">wjug</category><title>Warsjawa Eclipse DemoCamp 2008</title><description>Już w tą sobotę, 22 listopada w Warszawie w budynku &lt;a href="http://maps.google.com/?q=warszawa%2C%20ul%20banacha%202"&gt;MIMUW przy ul. Banacha 2&lt;/a&gt; w sali 5440 w godz. 9:00-17:00 odbędzie się konferencja Warsjawa Eclipse DemoCamp 2008 organizowana przez &lt;a href="http://groups.google.com/group/warszawa-jug"&gt;Warszawski JUG&lt;/a&gt;. Konferencja dotyczy tego, co w jawie piszczy, a dokładniej:&lt;br /&gt;&lt;br /&gt;09:00 - 09:45 Rejestracja (w trakcie: kawa/herbata, stół szwedzki)&lt;br /&gt;09:45 - 11:15 Comet, Bayeux i mechanizm Publish-Subscribe poprzez HTTP - Waldemar "waldi" Kot (Warszawa JUG)&lt;br /&gt;11:30 - 13:00 Taking SQL IDEs from the Stone Age to the 21st century - Wassim Melhem (Eclipse Foundation)&lt;br /&gt;13:00 - 14:00 Przerwa obiadowa (zarejestrowani bezpłatnie!)&lt;br /&gt;14:00 - 14:45 Czy Eclipse RCP mieści się w przeglądarce? - Jacek Pospychała (IBM Eclipse Support Center)&lt;br /&gt;14:50 - 15:35 Telekomunikacja w Javie - kilka słów o konwergencji i usługach w telekomunikacji - Tomasz Zieleniewski (TouK)&lt;br /&gt;15:40 - 16:10 Dojo Toolkit - Łukasz Lenart (Warszawa JUG)&lt;br /&gt;16:15 - 16:45 OSGi + Spring Framework = Spring Dynamic Modules - Jacek Laskowski (Warszawa JUG)&lt;br /&gt;16:45 - 17:00 Losowanie nagrody głównej - Kapituła Warsjavy&lt;br /&gt;17:00 Spotkania integracyjnego czas zacząć! - Kapituła Warsjavy&lt;br /&gt;&lt;br /&gt;Zauważyliście pewnie kilka frykasów: stół szwedzki, obiadek, imprezka, tajemnicza nagroda główna... To dzięki naszym wspaniałym sponsorom:&lt;br /&gt;&lt;a href="http://www.7n.com.pl/"&gt;7N&lt;/a&gt;, &lt;a href="http://www.javatech.com.pl/"&gt;Javatech&lt;/a&gt;, &lt;a href="http://www.e-point.pl/u235/navi/29709"&gt;e-point&lt;/a&gt;, &lt;a href="http://www.touk.pl/"&gt;Touk&lt;/a&gt;, &lt;a href="http://wiki.eclipse.org/Eclipse_DemoCamps_November_2008"&gt;Eclipse&lt;/a&gt;, &lt;a href="http://www.jetbrains.com/"&gt;JetBrains&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Konferencja jest całkowicie bezpłatna, pod warunkiem &lt;a href="http://oiola.com/e/244-warsjawa-eclipse-democamp-2008/"&gt;rejestracji&lt;/a&gt;. Osobiście będę sprawdzał listę obecności ;).&lt;br /&gt;&lt;br /&gt;Więcej informacji na stronie &lt;a href="http://warsjawa.pl/"&gt;warsjawa.pl&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;W imieniu organizatorów serdecznie zapraszam.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-4987271258747344000?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/-BdfgwteKhU/warsjawa-eclipse-democamp-2008.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/11/warsjawa-eclipse-democamp-2008.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-57902217804724933</guid><pubDate>Sat, 15 Nov 2008 15:33:00 +0000</pubDate><atom:updated>2008-11-15T10:38:13.461-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">kolorowanie składni</category><category domain="http://www.blogger.com/atom/ns#">blogspot</category><title>kolorowanie kodu źródłowego na blogu</title><description>Już od moich pierwszych spotkań z blogspotem brakowało mi możliwości ładnej prezentacji kodu źródłowego na jego stronach. Inne serwisy, takie jak &lt;a href="http://wikidot.com"&gt;wikidot.com&lt;/a&gt; pozostawiały (i pozostawiają) go daleko w tyle. W końcu jednak mi się udało coś na to poradzić...&lt;br /&gt;&lt;br /&gt;Dokładnie nie mi, tylko twórcom projektu &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt; syntaxhighlighter&lt;/a&gt;. To narzędzie, to nic więcej jak zestaw skryptów JavaScript, które kolorują i ozdabiają kod źródłowy.&lt;br /&gt;&lt;br /&gt;Aby skorzystać z tego wynalazku dołączyłem do swojego bloga dedykowany &lt;a href="http://fazibear.googlepages.com/blogger.html"&gt;widget&lt;/a&gt;. Na stronie &lt;a href="http://fazibear.googlepages.com/blogger.html"&gt;http://fazibear.googlepages.com/blogger.html&lt;/a&gt; kliknąłem w ikonkę &lt;span class="pre"&gt;Add to Blogger&lt;/span&gt;. Pasek tytułowy pozostawiłem pusty, dzięki temu widget pozostaje niewidoczny.&lt;br /&gt;&lt;br /&gt;Jeśli chodzi o instalację skryptów &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt; syntaxhighlighter&lt;/a&gt;, to by było na tyle. Uźycie ich, jest równie proste. Kod źródłowy wystarczy otoczyć tagami &lt;span class="pre"&gt;pre&lt;/span&gt; lub &lt;span class="pre"&gt;textarea&lt;/span&gt; o parametrach &lt;span class="pre"&gt; name="code" class="kod-języka"&lt;/span&gt;. Obsługiwane języki to:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;strong&gt;język&lt;/strong&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;strong&gt;kod języka&lt;/strong&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; C++ &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;cpp&lt;/tt&gt;, &lt;tt&gt;c&lt;/tt&gt;, &lt;tt&gt;c++&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; C# &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;c#&lt;/tt&gt;, &lt;tt&gt;c-sharp&lt;/tt&gt;, &lt;tt&gt;csharp&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; CSS &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;css&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Delphi &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;delphi&lt;/tt&gt;, &lt;tt&gt;pascal&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Java &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;java&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Java Script &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;js&lt;/tt&gt;, &lt;tt&gt;jscript&lt;/tt&gt;, &lt;tt&gt;javascript&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; PHP &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;php&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Python &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;py&lt;/tt&gt;, &lt;tt&gt;python&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Ruby &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;rb&lt;/tt&gt;, &lt;tt&gt;ruby&lt;/tt&gt;, &lt;tt&gt;rails&lt;/tt&gt;, &lt;tt&gt;ror&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Sql &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;sql&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; VB &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;vb&lt;/tt&gt;, &lt;tt&gt;vb.net&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; XML/HTML &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;xml&lt;/tt&gt;, &lt;tt&gt;html&lt;/tt&gt;, &lt;tt&gt;xhtml&lt;/tt&gt;, &lt;tt&gt;xslt&lt;/tt&gt; &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt; &lt;br /&gt;efekt jest mniej więcej taki:&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="sql" cols="60" rows="10"&gt;&lt;br /&gt;&amp;lt;textarea name="code" class="sql" cols="60" rows="10"&amp;gt;&lt;br /&gt;SELECT * FROM USER_ACCOUNTS;&lt;br /&gt;&amp;lt;/textarea&amp;gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Niezłe... ale to jeszcze nie koniec. Takie bloki kodu można konfigurować. W tym celu kod języka należy uzupełnić opcjami rozdzielonymi dwukropkiem. Dostępnych jest 5 parametrów konfiguracyjnych:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;nogutter&lt;/tt&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Ukrywa boczny pasek z numerami linii.&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;nocontrols&lt;/tt&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Ukrywa górne kontrolki. &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;collapse&lt;/tt&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Automatycznie wcięcia. &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;firstline[value]&lt;/tt&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Ustawia numer pierwszej linii &lt;tt&gt;value&lt;/tt&gt;. Domyślna wartość to 1. &lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; &lt;tt&gt;showcolumns&lt;/tt&gt; &lt;/td&gt;&lt;td style="border: 1px solid rgb(170, 170, 170); padding: 5px;"&gt; Pokaże numery kolumn &lt;/td&gt;&lt;/tr&gt; &lt;/tbody&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;i tak na przykład&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java:nocontrols:firstline[76]"&gt;&lt;br /&gt;&amp;lt;pre name="code" class="java:nocontrols:firstline[76]""&amp;gt;&lt;br /&gt;public class Hello {&lt;br /&gt;    private static final String HELLO_MSG = "Dzień dobry, cześć i czołem!"&lt;br /&gt;}&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;wyświetli blok kodu bez kontrolek, w dodatku pierwsza linia kodu będzie miała numer 76.&lt;br /&gt;&lt;br /&gt;No po prostu rewelacja. Niestety nie zupełnie. &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt; Syntaxhighlighter&lt;/a&gt; nie jest też pozbawiony bugów. Jeden z nich można podziwiać na przykładzie mojego poprzedniego posta &lt;a href="http://na-jawie.blogspot.com/2008/11/uprowadzenie-sesji.html"&gt;"Uprowadzenie sesji"&lt;/a&gt;. Prezentuję tam klasę:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class UserManager {&lt;br /&gt;&lt;br /&gt; private List&lt;user&gt; users;&lt;br /&gt;&lt;br /&gt; public UserManager() {&lt;br /&gt;  users = new ArrayList&lt;user&gt;(3);&lt;br /&gt;  User user1 = new User();&lt;br /&gt;  user1.setLogin("user1");&lt;br /&gt;  user1.setPassword("pass1");&lt;br /&gt;  user1.setBalance(54321);&lt;br /&gt;  User user2 = new User();&lt;br /&gt;  user2.setLogin("user2");&lt;br /&gt;  user2.setPassword("pass2");&lt;br /&gt;  user2.setBalance(65354);&lt;br /&gt;  User user3 = new User();&lt;br /&gt;  user3.setLogin("user3");&lt;br /&gt;  user3.setPassword("pass3");&lt;br /&gt;  user3.setBalance(91254);&lt;br /&gt;  users.add(user1);&lt;br /&gt;  users.add(user2);&lt;br /&gt;  users.add(user3);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public boolean check(String login, String password) {&lt;br /&gt;  User user = loadUser(login);&lt;br /&gt;  return user != null &amp;&amp; user.getPassword().equals(password);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public User loadUser(String login) {&lt;br /&gt;  for (User user : users) {&lt;br /&gt;   if (user.getLogin().equals(login)) {&lt;br /&gt;    return user;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setUsers(List&lt;user&gt; users) {&lt;br /&gt;  this.users = users;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;która po upiększeniu przez &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt; syntaxhighlighter&lt;/a&gt; wygląda tak:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class UserManager {&lt;br /&gt;&lt;br /&gt; private List&lt;user&gt; users;&lt;br /&gt;&lt;br /&gt; public UserManager() {&lt;br /&gt;  users = new ArrayList&lt;user&gt;(3);&lt;br /&gt;  User user1 = new User();&lt;br /&gt;  user1.setLogin("user1");&lt;br /&gt;  user1.setPassword("pass1");&lt;br /&gt;  user1.setBalance(54321);&lt;br /&gt;  User user2 = new User();&lt;br /&gt;  user2.setLogin("user2");&lt;br /&gt;  user2.setPassword("pass2");&lt;br /&gt;  user2.setBalance(65354);&lt;br /&gt;  User user3 = new User();&lt;br /&gt;  user3.setLogin("user3");&lt;br /&gt;  user3.setPassword("pass3");&lt;br /&gt;  user3.setBalance(91254);&lt;br /&gt;  users.add(user1);&lt;br /&gt;  users.add(user2);&lt;br /&gt;  users.add(user3);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public boolean check(String login, String password) {&lt;br /&gt;  User user = loadUser(login);&lt;br /&gt;  return user != null &amp;&amp; user.getPassword().equals(password);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public User loadUser(String login) {&lt;br /&gt;  for (User user : users) {&lt;br /&gt;   if (user.getLogin().equals(login)) {&lt;br /&gt;    return user;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setUsers(List&lt;user&gt; users) {&lt;br /&gt;  this.users = users;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Skąd na końcu &lt;span class="pre"&gt;&amp;lt;/user&amp;gt;&amp;lt;/user&amp;gt;&amp;lt;/user&amp;gt;&lt;/span&gt;?&lt;br /&gt;Nie wiadomo...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-57902217804724933?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/yoYEsKJPc7Q/kolorowanie-kodu-rdowego-na-blogu.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/11/kolorowanie-kodu-rdowego-na-blogu.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-1849590194239407367</guid><pubDate>Tue, 04 Nov 2008 23:02:00 +0000</pubDate><atom:updated>2008-12-10T11:01:27.321-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Spring Security</category><category domain="http://www.blogger.com/atom/ns#">bezpieczeństwo</category><title>uprowadzenie sesji</title><description>Dawno nic nie napisałem ciekawego. Ostatnio same zawirowania. Do tego zainstalowałem &lt;a href="http://pl.wikipedia.org/wiki/StarCraft"&gt;StarCrafta&lt;/a&gt; na Ubuntu oraz znalazłem sposób na kolorowanie kodu w tym oto blogu. Wydaje mi się on teraz nieco bardziej czytelny. Pomału na szczęście wychodzę na prostą, przynajmniej jeśli chodzi o bloga...&lt;br /&gt;&lt;br /&gt;Jako młode pachole, prawie każdy z nas chciał być strażakiem, policjantem, pilotem... Ja chciałem być pilotem, a najlepiej astronautą. Nic z tego niestety nie wyszło.&lt;br /&gt;&lt;br /&gt;Jako starsze pachole, już nie każdy, ale przynajmniej niektórzy chcieli być hakerami. Łamać hasła, włamywać się do NASA, wykradać materiały o UFO. Wszystkich, którzy wciąż mają takie zamiary, uprzejmie informuję, że ich do tego broń boże nie zachęcam. Jednak jak coś już wykradniesz z NASA, pochwal się w komentarzu.&lt;br /&gt;&lt;br /&gt;No ale do rzeczy. Dziś wpis z gatunku bezpieczeństwa. Pomysł nań nasunął mi się podczas rozważań co do mechanizmu logowania w prostej aplikacji WWW. Aplikacja prosta, więc możnaby autoryzację zaimplementować samemu. Można też użyć czegoś gotowego, np. &lt;a href="http://static.springframework.org/spring-security/site/index.html"&gt;SpringSecurity&lt;/a&gt;. Rozwiązanie to raczej pewne i sprawdzone, ale czy nie będzie to strzelanie armatą do muchy?&lt;br /&gt;&lt;br /&gt;Rozważmy zatem pierwsze podejście.&lt;br /&gt;&lt;br /&gt;Stworzyłem przykładową aplikację, która przechowuje poufne informacje o zarobkach pracowników. Na aplikację składają się 3 klasy:&lt;br /&gt;&lt;span class="pre"&gt;User&lt;/span&gt;, która zawiera informacje o pracowniku&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class User {&lt;br /&gt; private String login;&lt;br /&gt; private String password;&lt;br /&gt; private int balance;&lt;br /&gt; &lt;br /&gt; public String getLogin() {&lt;br /&gt;  return login;&lt;br /&gt; }&lt;br /&gt; public void setLogin(String login) {&lt;br /&gt;  this.login = login;&lt;br /&gt; }&lt;br /&gt; public String getPassword() {&lt;br /&gt;  return password;&lt;br /&gt; }&lt;br /&gt; public void setPassword(String password) {&lt;br /&gt;  this.password = password;&lt;br /&gt; }&lt;br /&gt; public int getBalance() {&lt;br /&gt;  return balance;&lt;br /&gt; }&lt;br /&gt; public void setBalance(int balance) {&lt;br /&gt;  this.balance = balance;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span class="pre"&gt;UserManager&lt;/span&gt; to klasa, która umożliwia proste operacje na użytkownikach. W prawdziwej aplikacji klasa zapewne będzie ukryta za interfejsem, korzystając do tego z obiektów DAO i inne takie. Na potrzeby jednak naszej aplikacji poniższy menadżer wystarczy:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class UserManager {&lt;br /&gt;&lt;br /&gt; private List&amp;lt;User&amp;gt; users;&lt;br /&gt;&lt;br /&gt; public UserManager() {&lt;br /&gt;  users = new ArrayList&amp;lt;User&amp;gt;(3);&lt;br /&gt;  User user1 = new User();&lt;br /&gt;  user1.setLogin("user1");&lt;br /&gt;  user1.setPassword("pass1");&lt;br /&gt;  user1.setBalance(54321);&lt;br /&gt;  User user2 = new User();&lt;br /&gt;  user2.setLogin("user2");&lt;br /&gt;  user2.setPassword("pass2");&lt;br /&gt;  user2.setBalance(65354);&lt;br /&gt;  User user3 = new User();&lt;br /&gt;  user3.setLogin("user3");&lt;br /&gt;  user3.setPassword("pass3");&lt;br /&gt;  user3.setBalance(91254);&lt;br /&gt;  users.add(user1);&lt;br /&gt;  users.add(user2);&lt;br /&gt;  users.add(user3);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public boolean check(String login, String password) {&lt;br /&gt;  User user = loadUser(login);&lt;br /&gt;  return user != null &amp;&amp; user.getPassword().equals(password);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public User loadUser(String login) {&lt;br /&gt;  for (User user : users) {&lt;br /&gt;   if (user.getLogin().equals(login)) {&lt;br /&gt;    return user;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setUsers(List&amp;lt;User&amp;gt; users) {&lt;br /&gt;  this.users = users;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Pozostała jeszcze klasa &lt;span class="pre"&gt;UserLoginBean&lt;/span&gt;, która odpowiada za zalogowanie użytkownika oraz sprawdza czy i jaki użytkownik jest w danym momencie zalogowany.&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class UserLoginBean {&lt;br /&gt; private String login;&lt;br /&gt; private String password;&lt;br /&gt; private User loggedUser;&lt;br /&gt; private UserManager userManager;&lt;br /&gt; &lt;br /&gt; public String login() {&lt;br /&gt;  if (userManager.check(login, password)) {&lt;br /&gt;   loggedUser = userManager.loadUser(login);&lt;br /&gt;   login = null;&lt;br /&gt;   password = null;&lt;br /&gt;   return "success";&lt;br /&gt;  }&lt;br /&gt;  return "faliture";&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public String logout() {&lt;br /&gt;  userManager = null;&lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public boolean isUserLogged() {&lt;br /&gt;  return loggedUser != null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public User getLoggedUser() {&lt;br /&gt;  return loggedUser;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setUserManager(UserManager userManager) {&lt;br /&gt;  this.userManager = userManager;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getLogin() {&lt;br /&gt;  return login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setLogin(String login) {&lt;br /&gt;  this.login = login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public String getPassword() {&lt;br /&gt;  return password;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void setPassword(String password) {&lt;br /&gt;  this.password = password;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Informacje o zalogowanym użytkowniku przechowywane są w sesji, stąd też taki zasięg ziarna &lt;span class="pre"&gt;UserLoginBean&lt;/span&gt;. Widać to w poniższym pliku &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt; xmlns:xi="http://www.w3.org/2001/XInclude"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"&amp;gt;&lt;br /&gt; &amp;lt;managed-bean&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-name&amp;gt;userManager&amp;lt;/managed-bean-name&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-class&amp;gt;pl.matt.UserManager&amp;lt;/managed-bean-class&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-scope&amp;gt;application&amp;lt;/managed-bean-scope&amp;gt;&lt;br /&gt; &amp;lt;/managed-bean&amp;gt;&lt;br /&gt; &amp;lt;managed-bean&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-name&amp;gt;userLoginBean&amp;lt;/managed-bean-name&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-class&amp;gt;pl.matt.UserLoginBean&amp;lt;/managed-bean-class&amp;gt;&lt;br /&gt;  &amp;lt;managed-bean-scope&amp;gt;session&amp;lt;/managed-bean-scope&amp;gt;&lt;br /&gt;  &amp;lt;managed-property&amp;gt;&lt;br /&gt;   &amp;lt;property-name&amp;gt;userManager&amp;lt;/property-name&amp;gt;&lt;br /&gt;   &amp;lt;value&amp;gt;#{userManager}&amp;lt;/value&amp;gt;&lt;br /&gt;  &amp;lt;/managed-property&amp;gt;&lt;br /&gt; &amp;lt;/managed-bean&amp;gt;&lt;br /&gt; &amp;lt;navigation-rule&amp;gt;&lt;br /&gt;  &amp;lt;from-view-id&amp;gt;/pages/login.xhtml&amp;lt;/from-view-id&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;success&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/pages/home.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;&lt;br /&gt;  &amp;lt;navigation-case&amp;gt;&lt;br /&gt;   &amp;lt;from-outcome&amp;gt;faliture&amp;lt;/from-outcome&amp;gt;&lt;br /&gt;   &amp;lt;to-view-id&amp;gt;/pages/login.xhtml&amp;lt;/to-view-id&amp;gt;&lt;br /&gt;  &amp;lt;/navigation-case&amp;gt;  &lt;br /&gt; &amp;lt;/navigation-rule&amp;gt;&lt;br /&gt; &amp;lt;application&amp;gt;&lt;br /&gt;  &amp;lt;view-handler&amp;gt;com.sun.facelets.FaceletViewHandler&amp;lt;/view-handler&amp;gt;&lt;br /&gt; &amp;lt;/application&amp;gt;&lt;br /&gt;&amp;lt;/faces-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;do kompletu aplikacji brakuje jeszcze pliku &lt;span class="pre"&gt;web.xml&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;&lt;br /&gt; &amp;lt;display-name&amp;gt;sessionHijacktion&amp;lt;/display-name&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;javax.faces.DEFAULT_SUFFIX&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;.xhtml&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;context-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;facelets.REFRESH_PERIOD&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;2&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/context-param&amp;gt;&lt;br /&gt; &amp;lt;servlet&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;servlet-class&amp;gt;javax.faces.webapp.FacesServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;  &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt; &amp;lt;/servlet&amp;gt;&lt;br /&gt; &amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;  &amp;lt;servlet-name&amp;gt;Faces Servlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;  &amp;lt;url-pattern&amp;gt;*.jsf&amp;lt;/url-pattern&amp;gt;&lt;br /&gt; &amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;oraz kilku stronek JSF. Dwie pierwsze, nie są specjalnie ciekawe. Strona &lt;span class="pre"&gt;login.xhtml&lt;/span&gt; zawiera prosty formularz, umożliwiający zalogowanie użytkownika do aplikacji&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;      xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;      xmlns:c="http://java.sun.com/jstl/core"&amp;gt;&lt;br /&gt;     &amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt;     &amp;lt;ui:composition template="/templates/common.xhtml"&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="pageTitle"&amp;gt;Login form&amp;lt;/ui:define&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="pageHeader"&amp;gt;Proszę się zalogować&amp;lt;/ui:define&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="body"&amp;gt;&lt;br /&gt;    &amp;lt;h:message showSummary="true" showDetail="false" style="color: red; font-weight: bold;" for="name" /&amp;gt;&lt;br /&gt;    &amp;lt;h:form id="helloForm"&amp;gt;&lt;br /&gt;     &amp;lt;h:panelGrid columns="2"&amp;gt;&lt;br /&gt;      &amp;lt;h:outputText value="login" /&amp;gt;&lt;br /&gt;      &amp;lt;h:inputText required="true" id="name" value="#{userLoginBean.login}" /&amp;gt;&lt;br /&gt;      &amp;lt;h:outputText value="password" /&amp;gt;&lt;br /&gt;      &amp;lt;h:inputSecret required="true" id="password" value="#{userLoginBean.password}" /&amp;gt;&lt;br /&gt;      &amp;lt;h:outputText value="" /&amp;gt;&lt;br /&gt;      &amp;lt;h:commandButton id="submit" action="#{userLoginBean.login}" value="zaloguj" /&amp;gt;&lt;br /&gt;     &amp;lt;/h:panelGrid&amp;gt;   &lt;br /&gt;    &amp;lt;/h:form&amp;gt;&lt;br /&gt;   &amp;lt;/ui:define&amp;gt;&lt;br /&gt;  &amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Natomiast strona &lt;span class="pre"&gt;home.xhtml&lt;/span&gt; przedstawia poufne informacje o każdym z użytkowników&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;      xmlns:f="http://java.sun.com/jsf/core"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt; &amp;lt;ui:composition template="/templates/common.xhtml"&amp;gt;&lt;br /&gt;   &amp;lt;ui:param name="loggedOnly" value="true" /&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="pageTitle"&amp;gt;Greeting to User&amp;lt;/ui:define&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="pageHeader"&amp;gt;Greeting Page&amp;lt;/ui:define&amp;gt;&lt;br /&gt;   &amp;lt;ui:define name="body"&amp;gt;&lt;br /&gt;    #{msg.greeting} #{userLoginBean.loggedUser.login} masz na koncie #{userLoginBean.loggedUser.balance}&lt;br /&gt;   &amp;lt;/ui:define&amp;gt;&lt;br /&gt; &amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Na uwagę zasługuje parametr&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;ui:param name="loggedOnly" value="true" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;dzięki któremu treść strony &lt;span class="pre"&gt;home.xhtml&lt;/span&gt; jest widoczna tylko dla zalogowanych użytkowników.&lt;br /&gt;Jak to działa? Wszystko staje się jasne, gdy obejrzymy plik &lt;span class="pre"&gt;/templates/common.xhtml&lt;/span&gt; zawierający szablon każdej strony aplikacji:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;      xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;      xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;      xmlns:f="http://java.sun.com/jsf/core"&amp;gt;&lt;br /&gt;      &lt;br /&gt;     &amp;lt;f:loadBundle basename="resources" var="msg" /&amp;gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;  &amp;lt;title&amp;gt;&amp;lt;ui:insert name="pageTitle"&amp;gt;Page Title&amp;lt;/ui:insert&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;body bgcolor="#ffffff"&amp;gt;&lt;br /&gt; &amp;lt;table style="border:1px solid #CAD6E0"  align="center" cellpadding="0" cellspacing="0" border="0" width="400"&amp;gt;&lt;br /&gt; &amp;lt;tbody&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;tr&amp;gt;&lt;br /&gt;  &amp;lt;td class="header" height="42" align="center" valign="middle" width="100%" bgcolor="#E4EBEB"&amp;gt;&lt;br /&gt;   &amp;lt;ui:insert name="pageHeader"&amp;gt;Page Header&amp;lt;/ui:insert&amp;gt;&lt;br /&gt;  &amp;lt;/td&amp;gt;&lt;br /&gt; &amp;lt;/tr&amp;gt;&lt;br /&gt; &amp;lt;tr&amp;gt;&lt;br /&gt;  &amp;lt;td height="1" width="100%" bgcolor="#CAD6E0"&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt; &amp;lt;/tr&amp;gt; &lt;br /&gt;&lt;br /&gt; &amp;lt;tr&amp;gt;&lt;br /&gt;  &amp;lt;td width="100%"  colspan="2"&amp;gt;&lt;br /&gt;   &amp;lt;table width="100%" style="height:150px" align="left" cellpadding="0" cellspacing="0" border="0"&amp;gt;&lt;br /&gt;   &amp;lt;tbody&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;     &amp;lt;td align="center" width="100%" valign="middle"&amp;gt;&lt;br /&gt;     &amp;lt;ui:fragment rendered="#{!loggedOnly || userLoginBean.userLogged}"&amp;gt;&lt;br /&gt;      &amp;lt;ui:insert name="body"&amp;gt;Page Body&amp;lt;/ui:insert&amp;gt;&lt;br /&gt;     &amp;lt;/ui:fragment&amp;gt;&lt;br /&gt;     &amp;lt;ui:fragment rendered="#{loggedOnly and !userLoginBean.userLogged}"&amp;gt;&lt;br /&gt;      Proszę się zalogować&lt;br /&gt;     &amp;lt;/ui:fragment&amp;gt;&lt;br /&gt;     &amp;lt;/td&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;   &amp;lt;/tbody&amp;gt;&lt;br /&gt;   &amp;lt;/table&amp;gt;&lt;br /&gt;  &amp;lt;/td&amp;gt;&lt;br /&gt; &amp;lt;/tr&amp;gt; &lt;br /&gt; &lt;br /&gt; &amp;lt;tr&amp;gt;&lt;br /&gt;  &amp;lt;td colspan="2"  valign="bottom" height="1" width="100%" bgcolor="#CAD6E0"&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt; &amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/tbody&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;  &lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;a dokładnie jego fragment:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;     &amp;lt;ui:fragment rendered="#{!loggedOnly || userLoginBean.userLogged}"&amp;gt;&lt;br /&gt;      &amp;lt;ui:insert name="body"&amp;gt;Page Body&amp;lt;/ui:insert&amp;gt;&lt;br /&gt;     &amp;lt;/ui:fragment&amp;gt;&lt;br /&gt;     &amp;lt;ui:fragment rendered="#{loggedOnly and !userLoginBean.userLogged}"&amp;gt;&lt;br /&gt;      Proszę się zalogować&lt;br /&gt;     &amp;lt;/ui:fragment&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Jeżeli parametr &lt;span class="pre"&gt;loggedOnly&lt;/span&gt; ustawiony jest na wartość &lt;span class="pre"&gt;true&lt;/span&gt;, zawartość strony zostanie wyświetlona, jedynie zalogowanemu użytkownikowi.&lt;br /&gt;&lt;br /&gt;Prosta aplikacja, proste zabezpieczenie, ale działają.&lt;br /&gt;Czy na pewno?&lt;br /&gt;&lt;br /&gt;Odpalam aplikację na serwerze JBoss 4.2.1.GA. &lt;br /&gt;Wyłączam w przeglądarce obsługę ciasteczek. Próbuję się zalogować, ale nie znam hasła.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_KxCJvjRke2k/SRDVbp1vloI/AAAAAAAAABw/WZm-ZXGd0o4/s1600-h/0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 127px;" src="http://4.bp.blogspot.com/_KxCJvjRke2k/SRDVbp1vloI/AAAAAAAAABw/WZm-ZXGd0o4/s320/0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5264942635460564610" /&gt;&lt;/a&gt;&lt;br /&gt;mogę się więc jedynie obejść smakiem:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KxCJvjRke2k/SRDVbsEujqI/AAAAAAAAAB4/UZAMcM7F5ds/s1600-h/1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 150px;" src="http://3.bp.blogspot.com/_KxCJvjRke2k/SRDVbsEujqI/AAAAAAAAAB4/UZAMcM7F5ds/s320/1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5264942636060282530" /&gt;&lt;/a&gt;&lt;br /&gt;Niby nic. Dla mojego żądania serwer otworzył nową sesję, a jej identyfikator dokleił do adresu URL. Nie ma się co dziwić, w końcu moja przeglądarka nie obsługuję ciasteczek. &lt;br /&gt;&lt;br /&gt;Teraz, jako, że nie znam hasła, a chcę się zalogować, kopiuję URL z identyfikatorem sesji i przesyłam mojej ofierze. Oczywiście proszę ją podstępnie o zalogowanie się.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_KxCJvjRke2k/SRDVb_SF2eI/AAAAAAAAACA/QJ9XWaAmi4A/s1600-h/2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 107px;" src="http://3.bp.blogspot.com/_KxCJvjRke2k/SRDVb_SF2eI/AAAAAAAAACA/QJ9XWaAmi4A/s320/2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5264942641216608738" /&gt;&lt;/a&gt;&lt;br /&gt;Ofiara moja grzecznie klika w URL i się loguje jako użytkownik "user3".&lt;br /&gt;&lt;br /&gt;A ja jeszcze grzeczniej, zmieniam w moim URLu adres z &lt;span class="pre"&gt;login.jsf&lt;/span&gt; na &lt;span class="pre"&gt;home.jsf&lt;/span&gt; (zostawiam identyfikator sesji) i...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_KxCJvjRke2k/SRDVcPH3FII/AAAAAAAAACI/44u-CTzKZy4/s1600-h/4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 128px;" src="http://2.bp.blogspot.com/_KxCJvjRke2k/SRDVcPH3FII/AAAAAAAAACI/44u-CTzKZy4/s320/4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5264942645468664962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Bingo. Też jestem zalogowany!&lt;br /&gt;&lt;br /&gt;Jak to się stało? Ano przesyłając adres z dopiętym identyfikatorem sesji, ofiara ataku zalogowała się do aplikacji korzystając mojej sesji. Ja następnie otworzyłem zabezpieczoną stronę, korzystając już z naszej wspólnej sesji, w której właśnie się ktoś zalogował.&lt;br /&gt;&lt;br /&gt;Jak się przed takim atakiem bronić? Najlepszym rozwiązaniem jest przydzielanie nowej sesji użytkownikowi przy logowaniu. Tak robi właśnie SpringSecurity. Przy okazji kopiuje on z automatu wszystkie obiekty ze starej sesji, do nowej. Tak więc fakt całej operacji jest dla użytkownika jest niezauważalny.&lt;br /&gt;Więcej o tym ataku znajdziesz na &lt;a href="http://pl.wikipedia.org/wiki/Session_hijacking"&gt;Wikipedii&lt;/a&gt;.&lt;br /&gt;Co ciekawe, przesiadka na JBossa 4.2.2.GA uniemożliwia już ten atak, przynajmniej w takiej prostej formie, jak ta opisana powyżej.&lt;br /&gt;&lt;br /&gt;Pozostaje tylko się domyślać, przed iloma jeszcze nieznanymi mi typami ataków chroni mnie i moją aplikację &lt;a href="http://static.springframework.org/spring-security/site/index.html"&gt;SpringSecurity&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-1849590194239407367?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/Kj_DuN_88RA/uprowadzenie-sesji.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_KxCJvjRke2k/SRDVbp1vloI/AAAAAAAAABw/WZm-ZXGd0o4/s72-c/0.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/11/uprowadzenie-sesji.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-6505444468874974990</guid><pubDate>Thu, 16 Oct 2008 13:35:00 +0000</pubDate><atom:updated>2008-11-15T08:16:23.819-08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql</category><category domain="http://www.blogger.com/atom/ns#">hibernate</category><title>Moc dialektów Hibernate</title><description>Od czasu do czasu mam przyjemność przeprowadzania rozmów rekrutacyjnych z kandydatami do pracy. Osobom, które deklarują znajomość Oracle PL/SQLa i przebrną przez pierwsze pytanie dotyczące sekwencji (a 2/3 znawców PL/SQLa nie wie, co to jest sekwencja) zadaję następujące zadanko:&lt;br /&gt;&lt;br /&gt;Przedstawiam encję &lt;span class="pre"&gt;Osoby&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SPdZ_nj-B3I/AAAAAAAAAIo/blaPKX7gNok/s1600-h/osoby.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SPdZ_nj-B3I/AAAAAAAAAIo/blaPKX7gNok/s320/osoby.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5257770039464822642" /&gt;&lt;/a&gt;&lt;br /&gt;i proszę o napisanie zapytania pokazującego 3 najmniej zarabiające osoby. Jeżeli kandydat zna również MySQL, proszę o napisanie tego zapytania w 2 wersjach. Bajer polega na tym, że w MySQLu do ograniczenia listy wyników do trzech wystarczy wykorzystać klauzulę &lt;span class="pre"&gt;limit&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="sql:nogutter"&gt;SELECT * FROM OSOBY ORDER BY OSOBY.PENSJA LIMIT 3;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;podczas gdy w Oracle takiej magicznej klauzuli nie ma. Jest tam za to możliwość wyświetlenia wierszy o określonym numerze (indeksie):&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;SELECT * FROM OSOBY WHERE NUMROW &lt;= 3 ORDER BY OSOBY.PENSJA;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ale numer wiersza jest sprzed sortowania, zatem powyższe zapytanie wyświetli trzech pierwszych użytkowników posortowanych po wielkości pensji. Aby osiągnąć zamierzony cel, trzeba skorzystać z podzapytania:&lt;br /&gt;&lt;br /&gt;&lt;span class="pre"&gt;SELECT * FROM (SELECT * FROM OSOBY OSOBY ORDER BY OSOBY.PENSJA ) WHERE NUMROW &lt;= 3;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Zapytanie o to samo, a jednak inaczej skonstruowane (a niby SQL to język &lt;a href="http://pl.wikipedia.org/wiki/J%C4%99zyk_deklaratywny"&gt;deklaratywny&lt;/a&gt;).&lt;br /&gt;Zaczęło mnie zastanawiać, co na to &lt;a href="http://hibernate.org"&gt;Hibernate&lt;/a&gt;. Czy jest na tyle mądry, że potrafi to samo zapytanie HQLowe zapisać na 2 zupełnie różne sposoby? Czy jego dialekty, ograniczają się jedynie do podmiany słów kluczowych i nazw typów, czy są mechanizmem dużo potężniejszym? Przekonajmy się.&lt;br /&gt;&lt;br /&gt;Na bazie aplikacji &lt;a href="http://www.hibernate.org/hib_files/jpwh-gettingstarted-070401.zip"&gt;Hibernate Getting Started - Hello World&lt;/a&gt; stworzyłem prosty projekt w środowisku Eclipsie. Skasowałem pliki &lt;span class="pre"&gt;Message.java&lt;/span&gt; oraz &lt;span class="pre"&gt;Message.hbm.xml&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Stworzyłem za to klasę &lt;span class="pre"&gt;Person&lt;/span&gt;:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class Person {&lt;br /&gt;    private Long id;&lt;br /&gt;    private String name;&lt;br /&gt;    private int salary;&lt;br /&gt;    &lt;br /&gt;    public Person() {&lt;br /&gt;     &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public Person(String text, int salary) {&lt;br /&gt;        this.name = text;&lt;br /&gt;        this.salary = salary;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Long getId() {&lt;br /&gt;        return id;&lt;br /&gt;    }&lt;br /&gt;    private void setId(Long id) {&lt;br /&gt;        this.id = id;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getName() {&lt;br /&gt;        return name;&lt;br /&gt;    }&lt;br /&gt;    public void setName(String text) {&lt;br /&gt;        this.name = text;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int getSalary() {&lt;br /&gt; return salary;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setSalary(int salary) {&lt;br /&gt;     this.salary = salary;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;oraz plik &lt;span class="pre"&gt;Person.hbm.xml&lt;/span&gt; odzwierciedlający zawartość klasy &lt;span class="pre"&gt;Person&lt;/span&gt; w bazie danych:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE hibernate-mapping PUBLIC&lt;br /&gt;    "-//Hibernate/Hibernate Mapping DTD//EN"&lt;br /&gt;    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-mapping&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;class name="hello.Person" table="PEOPLE"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;id name="id" column="PERSON_ID"&amp;gt;&lt;br /&gt;   &amp;lt;generator class="native"&amp;gt;&lt;br /&gt;   &amp;lt;/generator&amp;gt;&lt;br /&gt;  &amp;lt;/id&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="name" column="NAME" type="string" /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="salary" column="SALARY" type="integer" /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;/class&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/hibernate-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Skonfigurowałem w pliku &lt;span class="pre"&gt;hibernate.cfg.xml&lt;/span&gt; połączenie z bazą danych MySQL:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='utf-8'?&amp;gt; &amp;lt;!DOCTYPE hibernate-configuration&lt;br /&gt;        PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"&lt;br /&gt;        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt; &amp;lt;session-factory&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.driver_class"&amp;gt;com.mysql.jdbc.Driver&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.url"&amp;gt;jdbc:mysql://localhost:3306/test&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.MySQL5InnoDBDialect&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.username"&amp;gt;test&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.password"&amp;gt;test&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.min_size"&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.max_size"&amp;gt;20&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.timeout"&amp;gt;300&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.max_statements"&amp;gt;50&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.idle_test_period"&amp;gt;3000&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- SQL to stdout logging --&amp;gt;&lt;br /&gt;  &amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.hbm2ddl.auto"&amp;gt;update&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;mapping resource="hello/Person.hbm.xml" /&amp;gt;&lt;br /&gt; &amp;lt;/session-factory&amp;gt;&lt;br /&gt;&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Dzięki parametrowi&lt;br /&gt;&lt;span class="pre"&gt;&amp;lt;property name="hibernate.hbm2ddl.auto"&amp;gt;update&amp;lt;/property&amp;gt;&lt;/span&gt;&lt;br /&gt;schemat bazy danych zostanie dostosowany do aplikacji (zostaną utworzone lub zmodyfikowane odpowiednie tabele) przy jej starcie. &lt;br /&gt;Natomiast parametr &lt;br /&gt;&lt;span class="pre"&gt;&amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;&lt;/span&gt;&lt;br /&gt;pozwala wyświetla w konsoli zapytań SQL, które wykonuje Hibernate.&lt;br /&gt;&lt;br /&gt;Parametr&lt;br /&gt;&lt;span class="pre"&gt;&amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.MySQL5InnoDBDialect&amp;lt;/property&amp;gt;&lt;/span&gt;&lt;br /&gt;określa tzw. dialekt Hibernate, który odpowiada za tłumaczenie zapytań Hibernate na zapytania SQLowe zrozumiałe dla konkretnego systemu zarządzania bazami danych.&lt;br /&gt;&lt;br /&gt;Do tego zmieniłem zawartość metody &lt;span class="pre"&gt;main()&lt;/span&gt; klasy &lt;span class="pre"&gt;HelloWorld&lt;/span&gt;:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;    public static void main(String[] args) {&lt;br /&gt;        Session session = HibernateUtil.getSessionFactory().openSession();&lt;br /&gt;        Collection&lt;Person&gt; people = session.createCriteria(Person.class).list();&lt;br /&gt;        if (people.size() &lt; 5) {&lt;br /&gt;            Transaction tx = session.beginTransaction();&lt;br /&gt;            &lt;br /&gt;            Person p1 = new Person("Adam", 100);&lt;br /&gt;            Person p2 = new Person("Marek", 200);&lt;br /&gt;            Person p3 = new Person("Adrian", 150);&lt;br /&gt;            Person p4 = new Person("Konrad", 180);&lt;br /&gt;            Person p5 = new Person("Romek", 120);&lt;br /&gt;            &lt;br /&gt;            session.persist(p1);&lt;br /&gt;            session.persist(p2);&lt;br /&gt;            session.persist(p3);&lt;br /&gt;            session.persist(p4);&lt;br /&gt;            session.persist(p5);&lt;br /&gt;            &lt;br /&gt;            tx.commit();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        Query query = session.createQuery("FROM Person p ORDER BY p.salary").setMaxResults(3);&lt;br /&gt;        List&lt;Person&gt; list = query.list();&lt;br /&gt;        for (Person person : list) {&lt;br /&gt;   System.out.println(person.getName() + " " + person.getSalary());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;        session.close();&lt;br /&gt;        HibernateUtil.shutdown();&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Na początek prostsze zadanie - zapytanie do bazy MySQL. Odpalenie aplikacji kończy się spodziewanym wynikiem:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Hibernate: select person0_.PERSON_ID as PERSON_ID0_, person0_.NAME as NAME0_,&lt;br /&gt;    person0_.SALARY as SALARY0_ from PEOPLE person0_ order by person0_.SALARY limit ?&lt;br /&gt;Adam 100&lt;br /&gt;Romek 120&lt;br /&gt;Adrian 150&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Czas więc na uruchomienie aplikacji z bazą Oracle. Na początku, trzeba zmienić odrobinę plik &lt;span clas="pre"&gt;Person.hbm.xml&lt;/span&gt; tak, aby unikalny identyfikator osoby generowany był z sekwencji:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;id name="id" column="PERSON_ID"&amp;gt;&lt;br /&gt;   &amp;lt;generator class="sequence"&amp;gt;&lt;br /&gt;    &amp;lt;param name="sequence"&amp;gt;people_seq&amp;lt;/param&amp;gt;&lt;br /&gt;   &amp;lt;/generator&amp;gt;&lt;br /&gt;  &amp;lt;/id&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;oraz plik &lt;span clas="pre"&gt;hibernate.cfg.xml&lt;/span&gt;, konfigurując połączenie z bazą Oracle:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='utf-8'?&amp;gt; &amp;lt;!DOCTYPE hibernate-configuration&lt;br /&gt;        PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"&lt;br /&gt;        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;hibernate-configuration&amp;gt;&lt;br /&gt; &amp;lt;session-factory&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.driver_class"&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.url"&amp;gt;jdbc:oracle:thin:@127.0.0.1:1521/xe&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="dialect"&amp;gt;org.hibernate.dialect.OracleDialect&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.username"&amp;gt;test&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.connection.password"&amp;gt;test&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.min_size"&amp;gt;5&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.max_size"&amp;gt;20&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.timeout"&amp;gt;300&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.max_statements"&amp;gt;50&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;property name="hibernate.c3p0.idle_test_period"&amp;gt;3000&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!-- SQL to stdout logging --&amp;gt;&lt;br /&gt;  &amp;lt;property name="show_sql"&amp;gt;true&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;property name="hibernate.hbm2ddl.auto"&amp;gt;update&amp;lt;/property&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;mapping resource="hello/Person.hbm.xml" /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;/session-factory&amp;gt;&lt;br /&gt;&amp;lt;/hibernate-configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Uruchamiam aplikację i ...&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Hibernate: select * from&lt;br /&gt;    ( select person0_.PERSON_ID as PERSON_ID0_, person0_.NAME as NAME0_,&lt;br /&gt;     person0_.SALARY as SALARY0_ from PEOPLE person0_ order by person0_.SALARY )&lt;br /&gt;where rownum &lt;= ?&lt;br /&gt;Adam 100&lt;br /&gt;Romek 120&lt;br /&gt;Adrian 150&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Czyli bez niespodzianki. Dialekty Hibernate są więc dość potężnym mechanizmem. Pozwalają nie tylko na zmianę pojedynczych słów kluczowych, ale także konstrukcji całych zapytań. Trudno się zresztą dziwić. Hibernate to już bardzo dopracowany produkt.&lt;br /&gt;&lt;br /&gt;Niech no mi się teraz nawinie ktoś na rozmowie rekrutacyjnej, ze znajomością Oracle PL/SQLa i Hibernate...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-6505444468874974990?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/vadzj7HWS3s/moc-dialektw-hibernate.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SPdZ_nj-B3I/AAAAAAAAAIo/blaPKX7gNok/s72-c/osoby.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/10/moc-dialektw-hibernate.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-3994810094547001786</guid><pubDate>Sun, 21 Sep 2008 21:32:00 +0000</pubDate><atom:updated>2008-09-21T16:23:54.451-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Exception</category><title>Mój ulubiony Exception - java.lang.ArrayIndexOutOfBoundsException</title><description>a wszytko zaczęło się od popełnienia przeze mnie aplikacji. JSF, Facelets, Spring, JPA. Nic specjalnego... Poza tym, że na owej aplikacji od czasu do czasu (co kilka dni) wyskakiwał wyjątek &lt;span class="pre"&gt;java.lang.ArrayIndexOutOfBoundsException&lt;/span&gt;, a dokładniej:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;09:17:54,784 ERROR [ajp-0.0.0.0-8009-11] (LifecycleDecorator.java:75) - javax.faces.FacesException: java.lang.ArrayIndexOutOfBoundsException: 1&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:306)&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)&lt;br /&gt; at pl.matt.common.LifecycleDecorator.render(LifecycleDecorator.java:71)&lt;br /&gt; at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at pl.matt.common.filter.ProcessingTimeFilter.doFilter(ProcessingTimeFilter.java:29)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)&lt;br /&gt; at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)&lt;br /&gt; at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)&lt;br /&gt; at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)&lt;br /&gt; at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)&lt;br /&gt; at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)&lt;br /&gt; at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)&lt;br /&gt; at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)&lt;br /&gt; at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)&lt;br /&gt; at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437)&lt;br /&gt; at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:381)&lt;br /&gt; at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)&lt;br /&gt; at java.lang.Thread.run(Thread.java:619)&lt;br /&gt;Caused by: java.lang.ArrayIndexOutOfBoundsException: 1&lt;br /&gt; at com.sun.faces.renderkit.RenderKitUtils.buildTypeArrayFromString(RenderKitUtils.java:719)&lt;br /&gt; at com.sun.faces.renderkit.RenderKitUtils.determineContentType(RenderKitUtils.java:572)&lt;br /&gt; at com.sun.faces.renderkit.RenderKitImpl.createResponseWriter(RenderKitImpl.java:219)&lt;br /&gt; at com.sun.facelets.FaceletViewHandler.createResponseWriter(FaceletViewHandler.java:380)&lt;br /&gt; at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:550)&lt;br /&gt; at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)&lt;br /&gt; ... 24 more&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hmm... O co chodzi? Co ciekawe, błąd występował zawsze, gdy na stronę wchodziła przeglądarka &lt;span class="pre"&gt;Yanga WorldSearch Bot v1.1/beta (http://www.yanga.co.uk/)&lt;/span&gt;. Robi się coraz bardziej interesująco, prawda? Przy wystąpieniu błędu, miałem też ustawione logowanie nagłówków HTTP. Oto one:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;user-agent: Yanga WorldSearch Bot v1.1/beta (http://www.yanga.co.uk/)&lt;br /&gt;accept: text/html;q=1.0, text/plain;q=1.0, text/;q=0.5, */*;q=0.1&lt;br /&gt;accept-charset: utf-8;q=1.0, windows-1251;q=0.8, cp1251;q=0.8, koi8-r;q=0.8, *;q=0.5&lt;br /&gt;accept-encoding: gzip;q=1.0, deflate;q=1.0, identity;q=0.5, *;q=0&lt;br /&gt;content-length: 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Niby nic specjalnego (no poza przeglądarką) ale sytuacja dziwna. Aplikacja odpalana jest na JBossie 4.2.1.GA, gdzie implementacją JSFów jest implementacja referencyjna SUNa w wersji 1.2.04-p02. Pobrałem &lt;a href="https://javaserverfaces.dev.java.net/files/documents/1866/58376/jsf-1_2_04-p02-src.zip"&gt;źródła&lt;/a&gt;, aby podejrzeć 719 linię klasy RenderKitUtils&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private final static String CONTENT_TYPE_SUBTYPE_DELIMITER = "/";&lt;br /&gt;&lt;br /&gt;//...&lt;br /&gt;&lt;br /&gt;            // now split type and subtype&lt;br /&gt;            if (typeSubType.indexOf(CONTENT_TYPE_SUBTYPE_DELIMITER) &gt;= 0) {               &lt;br /&gt;                String[] typeSubTypeParts = Util.split(typeSubType.toString(), CONTENT_TYPE_SUBTYPE_DELIMITER);&lt;br /&gt;                type = typeSubTypeParts[0].trim();&lt;br /&gt;                subtype = typeSubTypeParts[1].trim();&lt;br /&gt;            } else {&lt;br /&gt;                type = typeSubType.toString();&lt;br /&gt;                subtype = "";&lt;br /&gt;            }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;linia 719 to&lt;br /&gt;&lt;span class="pre"&gt;subtype = typeSubTypeParts[1].trim();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Klasa parsuje zatem jeden z nagłówków HTTP gdzie spodziewa się dwóch napisów rozdzielonych &amp;quot;/&amp;quot;. Od razu moją uwagę zwrócił nagłówek:&lt;br /&gt;&lt;span class="pre"&gt;accept: text/html;q=1.0, text/plain;q=1.0, text/;q=0.5, */*;q=0.1&lt;/span&gt; a dokładniej jego część: &lt;span class="pre"&gt;text/;&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Trop był, trzeba było go jeszcze sprawdzić. Zainstalowałem zatem w FireFoxie wtyczkę &lt;a href="http://modifyheaders.mozdev.org/"&gt;Modify Headers&lt;/a&gt; która umożliwia... zmodyfikowanie nagłówków HTTP. Skonfigurowałem ją tak, aby zastępowała nagłówek &lt;span class="pre"&gt;accept&lt;/span&gt; wartością &lt;span class="pre"&gt;text/html;q=1.0, text/plain;q=1.0, text/;q=0.5, */*;q=0.1&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_62lNJlh-10g/SNbOoWKzLyI/AAAAAAAAAHU/Rjktg7uacew/s1600-h/0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_62lNJlh-10g/SNbOoWKzLyI/AAAAAAAAAHU/Rjktg7uacew/s320/0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5248609608287858466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;uruchomiłem aplikację, wszedłem na nią Firefoksem i...&lt;br /&gt;bingo. Aplikacja się wywala. Zaglądam w logi:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;00:03:13,862 ERROR [LifecycleDecorator] javax.faces.FacesException: java.lang.ArrayIndexOutOfBoundsException: 1&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:306)&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:144)&lt;br /&gt; at pl.matt.common.LifecycleDecorator.render(LifecycleDecorator.java:71)&lt;br /&gt; at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at pl.matt.common.filter.ProcessingTimeFilter.doFilter(ProcessingTimeFilter.java:29)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)&lt;br /&gt; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)&lt;br /&gt; at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)&lt;br /&gt; at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)&lt;br /&gt; at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)&lt;br /&gt; at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)&lt;br /&gt; at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)&lt;br /&gt; at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)&lt;br /&gt; at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)&lt;br /&gt; at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)&lt;br /&gt; at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)&lt;br /&gt; at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437)&lt;br /&gt; at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:381)&lt;br /&gt; at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)&lt;br /&gt; at java.lang.Thread.run(Thread.java:619)&lt;br /&gt;Caused by: java.lang.ArrayIndexOutOfBoundsException: 1&lt;br /&gt; at com.sun.faces.renderkit.RenderKitUtils.buildTypeArrayFromString(RenderKitUtils.java:719)&lt;br /&gt; at com.sun.faces.renderkit.RenderKitUtils.determineContentType(RenderKitUtils.java:572)&lt;br /&gt; at com.sun.faces.renderkit.RenderKitImpl.createResponseWriter(RenderKitImpl.java:219)&lt;br /&gt; at com.sun.facelets.FaceletViewHandler.createResponseWriter(FaceletViewHandler.java:380)&lt;br /&gt; at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:550)&lt;br /&gt; at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:106)&lt;br /&gt; at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)&lt;br /&gt; ... 24 more&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Jest mój ulubiony Exception.&lt;br /&gt;&lt;br /&gt;Tak jak w tenisie stołowym serwis to pół punktu, tak w programowaniu powtórzenie błędu to połowa jego poprawienia. Teraz tylko... no właśnie...&lt;br /&gt;&lt;br /&gt;odpaliłem aplikację w trybie odpluskiwania (debug). &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/SNbOorgdk2I/AAAAAAAAAHc/TnyaRfOM9Ck/s1600-h/1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_62lNJlh-10g/SNbOorgdk2I/AAAAAAAAAHc/TnyaRfOM9Ck/s320/1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5248609614015861602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Analizując stos wywołań natrafiłem na 203. linię klasy RenderKitImpl:&lt;br /&gt;&lt;span class="pre"&gt;String[] typeArray = context.getExternalContext().getRequestHeaderValuesMap().get("Accept");&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;O co chodzi? Przydała się wiedza z zakresu... serwletów! Na obiekcie &lt;span class="pre"&gt;HttpServletRequest&lt;/span&gt; wywołana jest metoda &lt;span class="pre"&gt;getHeaders()&lt;/span&gt;, która zwraca obiekt klasy &lt;span class="pre"&gt;Enumeration&lt;/span&gt; reprezentujący nagłówki HTTP o zadanej nazwie, w tym przypadku &lt;span class="pre"&gt;"Accept"&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Jak teraz podmienić nagłówek w obiekcie &lt;span class="pre"&gt;HttpServletRequest&lt;/span&gt;? Nie da się...&lt;br /&gt;Da się natomiast, przefiltrować żądanie HTTP, podmieniając obiekt je reprezentujący na obiekt innej klasy (oczywiście implementującej interfejs &lt;span class="pre"&gt;HttpServletRequest&lt;/span&gt;). Brzmi skomplikowanie? Chyba nie jest tak źle.&lt;br /&gt;&lt;br /&gt;Zatem po kolei: &lt;br /&gt;&lt;br /&gt;tworzę klasę filtra:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class ModifyRequestHeaderFilter implements Filter {&lt;br /&gt;&lt;br /&gt; public void init(FilterConfig filterConfig) throws ServletException {&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws java.io.IOException,&lt;br /&gt;   ServletException {&lt;br /&gt;  if (req instanceof HttpServletRequest) {&lt;br /&gt;   HttpServletRequest request = (HttpServletRequest) req;&lt;br /&gt;   req = new HttpServletRequestWrapper(request);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  chain.doFilter(req, res);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void destroy() {&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;metoda &lt;br /&gt;&lt;span class="pre"&gt;chain.doFilter(req, res);&lt;/span&gt;&lt;br /&gt;przekazuje żądanie do dalszego przetworzenia, ale wcześniej, żądanie jest opakowywane:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   HttpServletRequest request = (HttpServletRequest) req;&lt;br /&gt;   req = new HttpServletRequestWrapper(request);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;w obiekt mojej klasy, która przeciąża metodę getHeaders() klasy &lt;span class="pre"&gt;HttpServletRequest&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Klasa &lt;span class="pre"&gt;HttpServletRequestWrapper&lt;/span&gt; rozszerza klasę &lt;span class="pre"&gt;javax.servlet.http.HttpServletRequestWrapper&lt;/span&gt;, która w zasazdie tylko opakowuje żądanie HTTP. Delegując wywołania wszystkich metod do opakowanego obiektu, właśnie po to, żeby można było przeciążyć wybrane z nich. To przy okazji świetny przykład wzorca &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;dekorator&lt;/a&gt; .Tworzę zatem swoją klasę &lt;span class="pre"&gt;HttpServletRequestWrapper&lt;/span&gt; która przy żądniu nagłówków o nazwie &lt;span class="pre"&gt;"Accept"&lt;/span&gt;, podmienia w ich treści &lt;span class="pre"&gt;"text/;"&lt;/span&gt; na &lt;span class="pre"&gt;"text/*;"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper {&lt;br /&gt;&lt;br /&gt; private String substitutedHeaderName = "Accept";&lt;br /&gt; private String toReplace = "text/;";&lt;br /&gt; private String replacement = "text/*;";&lt;br /&gt;&lt;br /&gt; public HttpServletRequestWrapper(HttpServletRequest request) {&lt;br /&gt;  super(request);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @SuppressWarnings( { "unchecked" })&lt;br /&gt; @Override&lt;br /&gt; public Enumeration getHeaders(String name) {&lt;br /&gt;  if (substitutedHeaderName.equals(name)) {&lt;br /&gt;   Enumeration&lt;String&gt; headers = super.getHeaders(name);&lt;br /&gt;   List&lt;String&gt; out = new ArrayList&lt;String&gt;();&lt;br /&gt;   while (headers.hasMoreElements()) {&lt;br /&gt;    String header = (String) headers.nextElement();&lt;br /&gt;    if (header.contains(toReplace)) {&lt;br /&gt;     header = header.replaceAll(toReplace, replacement);&lt;br /&gt;    }&lt;br /&gt;    out.add(header);&lt;br /&gt;   }&lt;br /&gt;   return new IteratorEnumeration(out.iterator());&lt;br /&gt;  }&lt;br /&gt;  return super.getHeaders(name);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Trzeba jeszcze zarejestrować całe rozwiązanie w deskryptorze wdrożenia - pliku &lt;span class="pre"&gt;web.xml&lt;/span&gt;. Filtr konfiguruję tak, aby obsługiwał wszystkie żądania odwołujące się do stron JSF.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;filter&amp;gt;&lt;br /&gt; &amp;lt;filter-name&amp;gt;ModifyRequestHeaderFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt; &amp;lt;filter-class&amp;gt;pl.matt.common.filter.ModifyRequestHeaderFilter&amp;lt;/filter-class&amp;gt;&lt;br /&gt;&amp;lt;/filter&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;filter-mapping&amp;gt;&lt;br /&gt; &amp;lt;filter-name&amp;gt;ModifyRequestHeaderFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt; &amp;lt;url-pattern&amp;gt;*.jsf&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/filter-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Restart aplikacji i... działa. Serwlety wiecznie żywe. Mateusz wiecznie zadowolony.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-3994810094547001786?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/8aRjXv597dI/mj-ulubiony-exception.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_62lNJlh-10g/SNbOoWKzLyI/AAAAAAAAAHU/Rjktg7uacew/s72-c/0.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/09/mj-ulubiony-exception.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-7703805458092011885</guid><pubDate>Thu, 04 Sep 2008 18:29:00 +0000</pubDate><atom:updated>2008-09-04T16:58:39.862-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jboss Tools</category><category domain="http://www.blogger.com/atom/ns#">JSF</category><category domain="http://www.blogger.com/atom/ns#">Eclipse</category><title>JBoss Tools - nowa jakość w tworzeniu aplikacji opartych o JSF</title><description>Całkiem niedawno, Piotrek Buczek, jeden z moich zafascynowanych Seamem kolegów pokazał mi kilka sztuczek związanych z tą technologią. Oprócz sztuczek, bardzo zresztą widowiskowych uwagę moją przykuło środowisko na jakim pracował. Był to Eclipse 3.3 z wtyczką &lt;a href="http://www.jboss.org/tools/"&gt;JBoss Tools&lt;/a&gt;. Wsparcie dla Seama - bardzo pierwsza liga, jak to mawia pan &lt;a href="http://pl.youtube.com/watch?v=ynfT9qzmWzE"&gt;Kazimierz&lt;/a&gt;. Jak się ma wsparcie dla samych JSFów, zaraz zobaczymy. Zdradzę tylko, że wcale nie gorzej...&lt;br /&gt;&lt;br /&gt;Odkąd dostałem olbrzymią emkę za udział w konkursie &lt;a href="http://www.eclipse.org/ganymede/aroundtheworld.php"&gt;Ganymede Around the World Contest&lt;/a&gt; nie przystoi mi używać innej wersji Eclipse. Na nim zatem zainstaluję wtyczkę &lt;a href="http://www.jboss.org/tools/"&gt;JBoss Tools&lt;/a&gt;. Z Ganymede działa tylko rozwojowa wersja wtyczki (JBossTools 3.0.0.Alpha1) więc tą właśnie zainstaluję, ale po kolei...&lt;br /&gt;&lt;br /&gt;Wtyczkę można pobrać ze strony projektu &lt;a href="http://www.jboss.org/tools/"&gt;JBoss Tools&lt;/a&gt; lub zainstalować wykorzystując Eclipsowego zarządcę wtyczek. Wybieram to drugie rozwiązanie. Otwieram menu&lt;br /&gt;&lt;span class="pre"&gt;Help / Software Updates...&lt;/span&gt;&lt;br /&gt;i wybieram zakładkę&lt;br /&gt;&lt;span class="pre"&gt;Avaliable Software&lt;/span&gt;.&lt;br /&gt;Dodaję nową stronę o adresie:&lt;br /&gt;&lt;span class="pre"&gt;http://download.jboss.org/jbosstools/updates/development&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SMBxwUe6tOI/AAAAAAAAAFM/cZh9CFWtqS0/s1600-h/0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SMBxwUe6tOI/AAAAAAAAAFM/cZh9CFWtqS0/s320/0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315041205302498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Rozwijam nowo utworzony węzeł drzewka, zaznaczam &lt;br /&gt;&lt;span class="pre"&gt;JBossTools Development Release 3.0.0.Alpha1&lt;/span&gt;&lt;br /&gt;i klikam magiczny przycisk&lt;br /&gt;&lt;span class="pre"&gt;Install&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMBxwUpPbNI/AAAAAAAAAFU/u-h0U9OBN0k/s1600-h/1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMBxwUpPbNI/AAAAAAAAAFU/u-h0U9OBN0k/s320/1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315041248603346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Eclipse warczy, ściąga, restartuje się... i gotowe. Wypada jeszcze tylko skonfigurować w Eclipse JBossa. Odpalam zatem menu&lt;br /&gt;&lt;span class="pre"&gt;Window / Preferencess&lt;/span&gt;. i tam wybieram pozycję&lt;br /&gt;&lt;span class="pre"&gt;Server / Runtime Environments&lt;/span&gt; następnie klikam&lt;br /&gt;&lt;span class="pre"&gt;Add...&lt;/span&gt; i rozwijam gałąź &lt;span class="pre"&gt;JBoss, a division of Red Hat&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMBxwosWnSI/AAAAAAAAAFc/gVH5OkiTXmg/s1600-h/2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMBxwosWnSI/AAAAAAAAAFc/gVH5OkiTXmg/s320/2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315046630366498" /&gt;&lt;/a&gt;&lt;br /&gt;Kilka razy klikam &lt;span class="pre"&gt;Next&lt;/span&gt; wskazuję położenie na dysku JBossa i gotowe.&lt;br /&gt;&lt;br /&gt;Czas przyjrzeć się lepiej możliwościom wtyczki.Tworzę nowy projekt JSF (&lt;span class="pre"&gt;File / New... / Project... / JSF Project)&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SMBxwhftlTI/AAAAAAAAAFk/fDyrv1WFHD0/s1600-h/3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SMBxwhftlTI/AAAAAAAAAFk/fDyrv1WFHD0/s320/3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315044698297650" /&gt;&lt;/a&gt;&lt;br /&gt;Na następnej zakładce wybieram wersję JSF 1.2 z Faceletami oraz szablon &lt;span class="pre"&gt;FaceletsKickStartWithoutLibs&lt;/span&gt;, jako, że biblioteki mam w JBossie.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/SMBxw2ie7mI/AAAAAAAAAFs/5AEQ4fosJZk/s1600-h/4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_62lNJlh-10g/SMBxw2ie7mI/AAAAAAAAAFs/5AEQ4fosJZk/s320/4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315050347064930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zobaczmy co oferuje wtyczka. Otwieram plik &lt;span class="pre"&gt;WebContent/pages/greeting.xhtml&lt;/span&gt;. Pierwsze zaskoczenie - oprócz kodu pliku xhtml, mam zgrabny podgląd.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMBynkrS4NI/AAAAAAAAAF0/EymK1lCMltM/s1600-h/5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMBynkrS4NI/AAAAAAAAAF0/EymK1lCMltM/s320/5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315990444990674" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Klikam dowolne miejsce na podglądzie, podświetla mi się odpowiednie miejsce w kodzie.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SMBynh2pndI/AAAAAAAAAF8/-NQhq_gBKK0/s1600-h/6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SMBynh2pndI/AAAAAAAAAF8/-NQhq_gBKK0/s320/6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315989687311826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ładnie...&lt;br /&gt;Dodaję nowy tag, zmiany na bieżąco widzę w oknie podglądu.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMByn_6ZABI/AAAAAAAAAGE/hdU7BPhJHe4/s1600-h/7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMByn_6ZABI/AAAAAAAAAGE/hdU7BPhJHe4/s320/7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315997756063762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Jak dla mnie, rewelacja...&lt;br /&gt;Czas na zabawy z klawiszem &lt;span class="pre"&gt;CTRL&lt;/span&gt;. Przyciskam go, najeżdżam myszą na pole &lt;span class="pre"&gt;name&lt;/span&gt; wyrażenia &lt;span class="pre"&gt;#{person.name}&lt;/span&gt;. Klikam..,. i już widzę metodę &lt;span class="pre"&gt;getName()&lt;/span&gt; klasy &lt;span class="pre"&gt;Person&lt;/span&gt;, która w pliku &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt; skonfigurowana jest jako ziarno zarządzane JSF.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SMByn8OcszI/AAAAAAAAAGM/y7PBNDI4ivk/s1600-h/8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SMByn8OcszI/AAAAAAAAAGM/y7PBNDI4ivk/s320/8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242315996766450482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Klikam w słówko &lt;span class="pre"&gt;greeting&lt;/span&gt;  wyrażenia &lt;span class="pre"&gt;#{msg.greeting}&lt;/span&gt;. No i bomba, jestem już przy edycji pliku &lt;span class="pre"&gt;messages.properties&lt;/span&gt; i jego właściwości &lt;span class="pre"&gt;greeting&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMByoNq4-AI/AAAAAAAAAGU/eDRyLfBakmg/s1600-h/9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMByoNq4-AI/AAAAAAAAAGU/eDRyLfBakmg/s320/9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316001449146370" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Plik oczywiście jest skonfigurowany odpowiednio w &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt;.&lt;br /&gt;Przejdźmy zatem do tego pliku. Już pierwszy rzut oka, pozwala nam się zorientować, że mamy możliwość graficznej edycji nawigacji w aplikacji JSF.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMBzeV2_lxI/AAAAAAAAAGc/PhyH6z9tR_g/s1600-h/10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMBzeV2_lxI/AAAAAAAAAGc/PhyH6z9tR_g/s320/10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316931360331538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Sympatycznie. Tu niestety mały minus... Wtyczka automatycznie formatuje zawartość xmlową pliku &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt;, więc nie bardzo można mieć kontrolę nad wcięciami i kolejnością tagów w pliku. Przynajmniej ja nie potrafię tego osiągnąć.&lt;br /&gt;&lt;br /&gt;Wrócę jeszcze na moment do pliku &lt;span class="pre"&gt;WebContent/pages/greeting.xhtml&lt;/span&gt;. Oprócz nawigacji z klawiszem &lt;span class="pre"&gt;CTRL&lt;/span&gt;. Wtyczka JBoss Tools oferuje całkiem niezłe podpowiadanie. Zarówno tagów (wystarczy wpisać &lt;span class="pre"&gt;&amp;lt;f:&lt;/span&gt; i nacisnąć &lt;span class="pre"&gt;CTRL+spację&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SMBzeksdD9I/AAAAAAAAAGk/RMNfhAFkZU4/s1600-h/11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SMBzeksdD9I/AAAAAAAAAGk/RMNfhAFkZU4/s320/11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316935342657490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;jak i właściwości ziaren zarządzanych&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/SMBze6AW9vI/AAAAAAAAAGs/IlcvEXUBT1o/s1600-h/12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_62lNJlh-10g/SMBze6AW9vI/AAAAAAAAAGs/IlcvEXUBT1o/s320/12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316941063288562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;oraz wpisów w pliku messages.properties.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMBzfMMo7_I/AAAAAAAAAG0/yJKbpuyja38/s1600-h/13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMBzfMMo7_I/AAAAAAAAAG0/yJKbpuyja38/s320/13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316945946636274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mało? Zobaczmy, co jeszcze oferuje JBoss Tools. Odpalam projekt (na zakładce &lt;span class="pre"&gt;JBoss Server View&lt;/span&gt; klikam &lt;span class="pre"&gt;Start the server&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_62lNJlh-10g/SMBzfbl50LI/AAAAAAAAAG8/ONgWm5E0ttc/s1600-h/14.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_62lNJlh-10g/SMBzfbl50LI/AAAAAAAAAG8/ONgWm5E0ttc/s320/14.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242316950079131826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Serwer startuje...&lt;br /&gt;Wchodzę na stronę&lt;br /&gt;&lt;span class="pre"&gt;http://localhost:8080/jsfProject/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;otwieram w Eclipsie plik&lt;br /&gt;&lt;span class="pre"&gt;WebContent/pages/inputname.xhtml&lt;/span&gt;. Zauważyliście, że wykorzystywana jest tu, trochę zapomniana funkcja Faceletów, która umożliwia takie konstruowanie stron JSF, aby były one poprawnie wyświetlane w przeglądarce WWW bez uruchamiania ich na serwerze aplikacji?&lt;br /&gt;Zmieniam tytuł &lt;span class="pre"&gt;Facelets Hello Application&lt;/span&gt; na &lt;span class="pre"&gt;Witaj!&lt;/span&gt;. Zapisuję stronę. Przeładowuję ją w przeglądarce... i gotowe, zmiany od razu są widoczne.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_62lNJlh-10g/SMB0OZXAArI/AAAAAAAAAHE/7XzIo6WlMiI/s1600-h/15.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_62lNJlh-10g/SMB0OZXAArI/AAAAAAAAAHE/7XzIo6WlMiI/s320/15.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242317756933604018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Niestety zmiany w kodzie źródłowym, w plikach &lt;span class="pre"&gt;messages*.properties&lt;/span&gt; lub konfiguracja w &lt;span class="pre"&gt;faces-config.xml&lt;/span&gt; wymagają już restartu serwera.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_62lNJlh-10g/SMB0Otji1MI/AAAAAAAAAHM/OxRUwzAmZAg/s1600-h/22.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_62lNJlh-10g/SMB0Otji1MI/AAAAAAAAAHM/OxRUwzAmZAg/s320/22.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5242317762354926786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To zapewne tylko niektóre możliwości wtyczki. Jak dla mnie, są one rewelacyjne. Coś czuję, że JBoss Tools dołączy do mojego zestawu ulubionych wtyczek środowiska Eclipse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-7703805458092011885?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/BGTUl70gUDk/jboss-tools-nowa-jako-w-tworzeniu.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SMBxwUe6tOI/AAAAAAAAAFM/cZh9CFWtqS0/s72-c/0.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/09/jboss-tools-nowa-jako-w-tworzeniu.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-1863340552370343550</guid><pubDate>Sun, 31 Aug 2008 15:07:00 +0000</pubDate><atom:updated>2008-08-31T09:09:27.451-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Eclipse Ganymede</category><title>koszulka Eclipse, bug naprawiony</title><description>Stało się...&lt;br /&gt;&lt;a href="http://www.eclipse.org"&gt;Eclipse 3.4.0&lt;/a&gt; ujrzał światło dzienne, a &lt;a href="http://www.eclipse.org/ganymede/aroundtheworld.php"&gt;Ganymede Around the World Contest&lt;/a&gt; dobiegł końca. Wziąłem udział w tym konkursie, co na szczęście nie umknęło uwadze organizatorów, o czym przekonałem się odbierając przesyłkę:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_62lNJlh-10g/SLrBnDz1zgI/AAAAAAAAAEc/cbfH6WFnOdY/s1600-h/0.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_62lNJlh-10g/SLrBnDz1zgI/AAAAAAAAAEc/cbfH6WFnOdY/s320/0.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5240713993180794370" /&gt;&lt;/a&gt;&lt;br /&gt;Niby emka, ale jakaś duża. Przynajmniej nie zrobiona w Chinach a w Kanadzie.&lt;br /&gt;&lt;br /&gt;Jakby tego było mało, zgłoszony przeze mnie &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=238463"&gt;błąd&lt;/a&gt; został już naprawiony. Dołączony zostanie prawdopodobnie do wersji 3.4.1 środowiska.&lt;br /&gt;Poprawiony błąd i koszulka. Chyba warto brać udział w konkursach spod stajni Eclipse.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-1863340552370343550?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/soBTSyamEj0/koszulka-eclipse-bug-naprawiony.html</link><author>noreply@blogger.com (MZ)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_62lNJlh-10g/SLrBnDz1zgI/AAAAAAAAAEc/cbfH6WFnOdY/s72-c/0.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/08/koszulka-eclipse-bug-naprawiony.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6443533180962722149.post-1356919092323856470</guid><pubDate>Wed, 13 Aug 2008 18:53:00 +0000</pubDate><atom:updated>2008-08-14T07:57:15.645-07:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">J2SE</category><title>testy java</title><description>Zawsze mnie zastanawiało, skąd się biorą podchwytliwe pytania dotyczące programowania w Javie. Czy wymyślają je programiści, na zasadzie "sztuka dla sztuki", czy pochodzą one z prawdziwych projektów. Moja zagadka pochodzi z życia.&lt;br /&gt;&lt;br /&gt;Co będzie wynikiem wywołania funkcji:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  BigDecimal arg1 = new BigDecimal("10");&lt;br /&gt;  BigDecimal arg2 = new BigDecimal("3");&lt;br /&gt;  System.out.println(arg1.divide(arg2).toPlainString());&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;a) na konsole zostanie wypisane: 3,333333333&lt;br /&gt;b) na konsole zostanie wypisane: 3,33&lt;br /&gt;c) na konsole zostanie wypisane: 3&lt;br /&gt;d) zostanie rzucony wyjątek w linii &lt;span class="pre"&gt;System.out.println(arg1.divide(arg2).toPlainString());&lt;/span&gt;&lt;br /&gt;e) na konsole zostanie wypisane: null&lt;br /&gt;&lt;br /&gt;no i odpowiedź:&lt;br /&gt;&lt;span class="pre"&gt;Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.&lt;/span&gt;&lt;br /&gt;następnym razem dzieląc obiekty klasy BigDecimal będę uważał.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6443533180962722149-1356919092323856470?l=na-jawie.blogspot.com'/&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/NaJawie/~3/rjB4IQXqc6w/testy-java.html</link><author>noreply@blogger.com (MZ)</author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://na-jawie.blogspot.com/2008/08/testy-java.html</feedburner:origLink></item></channel></rss>
