<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog Technologiczny ATENA &#187; JBoss</title>
	<atom:link href="http://blog.atena.pl/category/jboss/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.atena.pl</link>
	<description>JavaEE, AJAX, xHTML, RIA, JBoss</description>
	<lastBuildDate>Fri, 20 Jan 2012 11:18:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>JBoss + LDAP</title>
		<link>http://blog.atena.pl/jboss-ldap</link>
		<comments>http://blog.atena.pl/jboss-ldap#comments</comments>
		<pubDate>Thu, 06 Oct 2011 12:25:09 +0000</pubDate>
		<dc:creator>Michał Łaguna</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaEE]]></category>
		<category><![CDATA[autentykacja]]></category>
		<category><![CDATA[autoryzacja]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[uwierzytelnianie]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1535</guid>
		<description><![CDATA[Jak skonfigurować w JBossie uwierzytelnianie i autoryzację opartą o LDAP ? Na początek przykładowa aplikacja Na potrzeby testów stwórzmy sobie prościutką aplikację i umieśćmy ją na JBossie. Najprościej będzie użyć do tego celu mechanizmu archetypów Mavena: mvn archetype:generate wybierzmy webapp-jee5 wybierzmy wersję 1.0 wskażmy groupId – np. pl.atena wskażmy artifactId – np. ldap-integration wskażmy version [...]]]></description>
			<content:encoded><![CDATA[<p>Jak skonfigurować w JBossie uwierzytelnianie i autoryzację opartą o LDAP ?</p>
<p><span id="more-1535"></span></p>
<h2>Na początek przykładowa aplikacja</h2>
<p>Na potrzeby testów stwórzmy sobie prościutką aplikację i umieśćmy ją na JBossie.</p>
<p>Najprościej będzie użyć do tego celu mechanizmu archetypów Mavena:</p>
<pre><strong>mvn archetype:generate</strong>
wybierzmy webapp-jee5
wybierzmy wersję 1.0
wskażmy groupId – np. pl.atena
wskażmy artifactId – np. ldap-integration
wskażmy version – np. 1.0-SNAPSHOT
wskażmy pakiet – np. pl.atena.ldap</pre>
<p>Po zatwierdzeniu powinniśmy mieć gotowy do deployu projekt.</p>
<p>Wystarczy go zbudować</p>
<pre><strong>mvn clean package</strong></pre>
<p>i skopiować do katalogu <strong>JBOSS/server/default/deploy</strong></p>
<p>Po uruchomieniu serwera i wejściu na stronę <a href="http://localhost:8080/ldap-integration">http://localhost:8080/ldap-integration</a> powinniśmy zobaczyć „Hello World”.</p>
<h2>Konfiguracja modułu uwierzytelniania w JBossie</h2>
<p>Kolejnym krokiem będzie konfiguracja uwierzytelniania w JBossie. W tym celu edytujemy plik <strong>JBOSS/Server/default/login-config.xml</strong> i dodajemy w nim nową politykę bezpieczeństwa, którą nazwiemy ldap:</p>
<pre>&lt;application-policy name="ldap"&gt;
  &lt;authentication&gt;
    &lt;login-module code="<strong>org.jboss.security.auth.spi.LdapExtLoginModule</strong>" flag="required" &gt;
      &lt;module-option&gt;<strong>ldap://serwerLdap:389</strong>&lt;/module-option&gt;
      &lt;module-option&gt;<strong>ATENA\ldapUser</strong>&lt;/module-option&gt;
      &lt;module-option&gt;<strong>password</strong>&lt;/module-option&gt;

      &lt;module-option name="baseCtxDN"&gt;<strong>CN=Users,DC=companyName,DC=com</strong>&lt;/module-option&gt;
      &lt;module-option name="baseFilter"&gt;<strong>(sAMAccountName={0})</strong>&lt;/module-option&gt;

      &lt;module-option&gt;<strong>OU=Groups,DC=companyName,DC=com</strong>&lt;/module-option&gt;
      &lt;module-option name="matchOnUserDN"&gt;<strong>true</strong>&lt;/module-option&gt;
      &lt;module-option name="uidAttributeID"&gt;<strong>member</strong>&lt;/module-option&gt;
      &lt;module-option name="roleFilter"&gt;<strong>(member={1})</strong>&lt;/module-option&gt;
      &lt;module-option name="roleAttributeID"&gt;<strong>CN</strong>&lt;/module-option&gt;

      &lt;module-option name="roleRecursion"&gt;<strong>2</strong>&lt;/module-option&gt;
      &lt;module-option name="searchScope"&gt;<strong>SUBTREE_SCOPE</strong>&lt;/module-option&gt;

      &lt;module-option name="allowEmptyPasswords"&gt;<strong>false</strong>&lt;/module-option&gt;
    &lt;/login-module&gt;
  &lt;/authentication&gt;
&lt;/application-policy&gt;</pre>
<p><strong>Wyjaśnienie najważniejszych parametrów:</strong></p>
<ul>
<li>login-module      – wskazanie modułu uwierzytelniania – dla samego uwierzytelniania możemy      użyć LdapLoginModule; jeśli chcemy użyć również autoryzacji opartej o LDAP      musimy użyć LdapExtLoginModule</li>
<li>java.naming.provider.url      – namiary na kontroler domeny</li>
<li>bindDN      – nazwa użytkownika z uprawnieniami do wykonywania zapytań w LDAPie</li>
<li>bindCredential – hasło      użytkownika</li>
<li>baseCtxDN – ścieżka do      wyszukiwania użytkownika</li>
<li>baseFilter      – filtr służący do wyszukania uwierzytelnianego użytkownika</li>
<li>rolesCtxDN – ścieżka do      wyszukiwania roli</li>
<li>roleFilter      – filtr służący do wyszukania roli użytkownika</li>
<li>roleAttributeID      – wskazanie na miejsce w ścieżce gdzie będzie nazwa roli</li>
<li>roleRecursion      – głębokość wyszukiwania roli</li>
<li>searchScope      – zasięg wyszukiwania (OBJECT_SCOPE, ONELEVEL_SCOPE, SUBTREE_SCOPE)</li>
<li>allowEmptyPasswords      – flaga wskazująca, czy puste hasła powinny być przekazywane do serwera      LDAPa (niektóre serwery LDAP traktują puste hasło jako zalogowanie      anonimowe)</li>
</ul>
<p><strong>Pełna lista parametrów dla modułu LdapExtLoginModeule dostępna jest pod adresem: </strong></p>
<p><a href="http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.2/html/Server_Configuration_Guide/Using_JBoss_Login_Modules-LdapExtLoginModule.html" target="_blank">http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.2/html/Server_Configuration_Guide/Using_JBoss_Login_Modules-LdapExtLoginModule.html</a></p>
<h2>Podpięcie uwierzytelniania do aplikacji</h2>
<p>Ostatnim krokiem jest podpięcie dodanej polityki do naszej aplikacji i zabezpieczenie dostępu do pewnych zasobów w aplikacji. W tym celu dodajemy w katalogu src/main/webapp/WEB-INF/ plik <strong>jboss-web.xml</strong> o następującej treści:</p>
<pre>&lt;jboss-web&gt;
  &lt;security-domain&gt;<strong>java:/jaas/ldap</strong>&lt;/security-domain&gt;
&lt;/jboss-web&gt;</pre>
<p>Następnie zabezpieczamy dostęp do aplikacji w pliku <strong>web.xml</strong>:</p>
<pre>&lt;web-app&gt;
  &lt;display-name&gt;<strong>Archetype Created Web Application</strong>&lt;/display-name&gt;
  &lt;security-constraint&gt;
    &lt;web-resource-collection&gt;
      &lt;web-resource-name&gt;<strong>LDAP Restricted Zone</strong>&lt;/web-resource-name&gt;
      &lt;url-pattern&gt;<strong>/*</strong>&lt;/url-pattern&gt;
    &lt;/web-resource-collection&gt;
    &lt;auth-constraint&gt;
      &lt;role-name&gt;<strong>administrator</strong>&lt;/role-name&gt;
    &lt;/auth-constraint&gt;
    &lt;/security-constraint&gt;
    &lt;login-config&gt;
      &lt;auth-method&gt;<strong>BASIC</strong>&lt;/auth-method&gt;
      &lt;realm-name&gt;<strong>LDAP Restricted Zone</strong>&lt;/realm-name&gt;
    &lt;/login-config&gt;
    &lt;security-role&gt;
      &lt;role-name&gt;<strong>administrator</strong>&lt;/role-name&gt;
    &lt;/security-role&gt;
&lt;/web-app&gt;</pre>
<p>Gdy ponownie wejdziemy na stronę naszej aplikacji (<a href="http://localhost:8080/ldap-integration">http://localhost:8080/ldap-integration</a>) powinniśmy zostać zapytani o login i hasło użytkownika. Po podaniu domenowego loginu i hasła powinniśmy ponownie zobaczyć nasze ‘Hello World’ – pod warunkiem, że jesteśmy w LDAPie przypisani do grupy <em>administrator</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/jboss-ldap/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PRAKTYCZNY ENVERS</title>
		<link>http://blog.atena.pl/praktyczny-envers</link>
		<comments>http://blog.atena.pl/praktyczny-envers#comments</comments>
		<pubDate>Fri, 20 Aug 2010 07:00:10 +0000</pubDate>
		<dc:creator>Mateusz Mrozewski</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaEE]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=1028</guid>
		<description><![CDATA[Envers jest dodatkiem do Hibernate’a pozwalającym na automatyczne zapisywanie historii zmian encji (audytu). Envers używa pojęcia rewizji – co oznacza, że każda zmiana dowolnej (audytowalnej) encji tworzy nową rewizję. Nowy rekord jest zapisany do tabeli, a na podstawie starego zostaje utworzona rewizja i zapisana do dodatkowej tabeli wraz z poprzednimi wartościami. Konfiguracja W ramach podstawowej [...]]]></description>
			<content:encoded><![CDATA[<p>Envers jest dodatkiem do Hibernate’a pozwalającym na automatyczne zapisywanie historii zmian encji (audytu). Envers używa pojęcia rewizji – co oznacza, że każda zmiana dowolnej (audytowalnej) encji tworzy nową rewizję. Nowy rekord jest zapisany do tabeli, a na podstawie starego zostaje utworzona rewizja i zapisana do dodatkowej tabeli wraz z poprzednimi wartościami.</p>
<p><span id="more-1028"></span></p>
<p><strong>Konfiguracja</strong></p>
<p>W ramach podstawowej niezbędnej konfiguracji należy dodać następujące właściwości do pliku persistence.xml lub hibernate.cfg.xml:</p>
<p style="text-align: left">&lt;property name=&#8221;hibernate.ejb.event.post-insert&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-update&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-delete&#8221; value=&#8221;org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.pre-collection-update&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.pre-collection-remove&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;<br />
&lt;property name=&#8221;hibernate.ejb.event.post-collection-recreate&#8221; value=&#8221;org.hibernate.envers.event.AuditEventListener&#8221; /&gt;</p>
<p>Konfigurujemy w ten sposób listenery , które sprawdzają, czy zmieniły się jakieś audytowalne encje i czy należy zachować historię zmian tych encji.</p>
<p>Kolejnym krokiem jest już oznaczenie encji adnotacją @Audited. Jeśli adnotację umieścimy na poziomie klasy, wszystkie pola będą wersjonowane. Możemy również adnotację umieścić na poziomie pól klasy, aby wersjonować tylko wybrane.</p>
<p><strong>Przykład użycia</strong></p>
<p>Po umieszczeniu konfiguracji opisanej w kroku wyżej użycie Envers’a sprowadza się do dodania odpowiednich adnotacji.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Entity<br />
@Audited<br />
public class Item {<br />
&nbsp; &nbsp; @Id<br />
&nbsp; &nbsp; private int id;<br />
<br />
&nbsp; &nbsp; private String name;<br />
<br />
&nbsp; &nbsp; public int getId() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return id;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setId(int id) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.id = id;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public String getName() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return name;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setName(String name) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.name = name;<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>I to tak naprawdę wszystko z rzeczy specyficznych dla Envers. Użycie encji w innym zakresie jest tak standardowe, jak w przypadku JPA lub Hibernate i w zasadzie niczym się od nich nie różni.</p>
<p><strong>Przechowywanie rewizji</strong></p>
<p>Dla każdej adnotowanej encji zostanie utworzona dodatkowa tabela przechowująca audyt. Dla naszej encji z podanego przykładu powstanie podstawowa tabela:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE ITEM<br />
(<br />
ID decimal(10) PRIMARY KEY NOT NULL,<br />
NAME varchar2(1020)<br />
);</div></td></tr></tbody></table></div>
<p>Oraz dodatkowa tabela do przechowywania audytu:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE ITEM_AUD<br />
(<br />
ID decimal(10) NOT NULL,<br />
REV decimal(10) NOT NULL,<br />
REVTYPE decimal(3),<br />
NAME varchar2(1020),<br />
CONSTRAINT SYS_C006187 PRIMARY KEY (ID,REV)<br />
);</div></td></tr></tbody></table></div>
<p>Dodatkowo doszły nam następujące pola:</p>
<ul>
<li>REV – oznacza numer rewizji;</li>
<li>REVTYPE – typ zmiany; możliwe wartości: 0 – wstawienie rekordu, 1 – modyfikacja rekordu, 2 – usunięcie rekordu.</li>
</ul>
<p>Najnowszy rekord w tabeli audytu będzie miał wartości o jedną wersję wstecz względem wartości w aktualnej tabeli. Jeśli natomiast rekord zostanie usunięty, nie znajdziemy go już w tabeli podstawowej, a najświeższy wpis będzie miał wartości ustawione na &lt;null&gt; i typ rewizji 2.</p>
<p>Numery rewizji są wspólne dla wszystkich encji. Oznacza to, że jeśli najpierw zmienimy encję A, otrzyma ona rewizję 1, dopiero potem zmienimy encję B, która otrzyma rewizję 2 (oczywiście obie będą posiadały oddzielne tabele audytu).</p>
<p><strong>Encja rewizji i zapis dodatkowych danych</strong></p>
<p>Oprócz zapisywania historii zmian danej encji możemy dla każdej rewizji zapisać dodatkowe informacje. Służy do tego encja rewizji – jest to standardowa encja z dodatkową adnotacją oraz dodatkowymi polami, jakie chcemy zapisać. Przykładowo:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@Entity<br />
@RevisionEntity(MyRevisionListener.class)<br />
public class MyRevisionEntity extends DefaultRevisionEntity {<br />
&nbsp; &nbsp; private static final long serialVersionUID = -78999006241889798L;<br />
&nbsp; &nbsp; private String username;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public String getUsername() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; return username;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setUsername(String username) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.username = username;<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>Klasa DefaultRevisionEntity jest dostarczana wraz z Envers i deklaruje dwa podstawowe pola: id oraz timestamp. Do tego możemy dołożyć dodatkowe informacje, które chcemy zapisać, np. nazwę użytkownika. Wykonuje się to w listenerze wskazanym przez adnotację @RevisionEntity:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class MyRevisionListener implements RevisionListener {<br />
<br />
&nbsp; &nbsp; public void newRevision(Object revisionEntity) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; MyRevisionEntity entity = (MyRevisionEntity) revisionEntity;<br />
&nbsp; &nbsp; &nbsp; &nbsp; entity.setUsername(&quot;NAZWA UŻYTKOWNIKA&quot;);<br />
&nbsp; &nbsp; }<br />
<br />
}</div></td></tr></tbody></table></div>
<p>Dla przykładowej encji rewizji zostanie utworzona następująca tabela:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE MYREVISIONENTITY<br />
(<br />
ID decimal(10) PRIMARY KEY NOT NULL,<br />
TIMESTAMP decimal(19) NOT NULL,<br />
USERNAME varchar2(1020)<br />
);</div></td></tr></tbody></table></div>
<p>Teraz przy utworzeniu nowej rewizji dowolnej audytowanej encji zostanie utworzony nowy wpis w tej tabeli z danymi uzupełnionymi według naszego listenera.</p>
<p><strong>Odpytywanie o rewizje</strong></p>
<p>Envers dostarcza klasy użytkowe pozwalające na odpytywanie o stan rewizji poszczególnych encji. Klasa AuditReaderFactory pozwala nam na pobranie instancji AuditReader w zależności od tego, czy operujemy na EntityManager z JPA czy też na Session z Hibernate.</p>
<p>AuditReader pozwala na budowanie zapytań implementujących interfejs AuditReader. Służy on do budowania zapytań w sposób podobny jak w przypadku Hibernate Criteria. Pytać możemy na dwa sposoby:</p>
<ul>
<li>o encję w konkretnej rewizji,</li>
<li>o rewizje, w których encje się zmieniły.</li>
</ul>
<p>Przykład zapytania o konkretną rewizję:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">int revision = 1;<br />
AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(Item.class, revision);<br />
<br />
List items = query.addOrder(AuditEntity.property(&quot;name&quot;).desc())<br />
&nbsp; &nbsp; .setFirstResult(4)<br />
&nbsp; &nbsp; .setMaxResults(2)<br />
&nbsp; &nbsp; .getResultList();</div></td></tr></tbody></table></div>
<p>Przykład zapytania o rewizje, w których zmieniała się encja:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">int revision = 1;<br />
Number revision = (Number) getAuditReader().createQuery()<br />
&nbsp; &nbsp; .forRevisionsOfEntity(Item.class, false, true)<br />
&nbsp; &nbsp; .setProjection(AuditEntity.revisionNumber().min())<br />
&nbsp; &nbsp; .add(AuditEntity.id().eq(entityId))<br />
&nbsp; &nbsp; .getSingleResult();</div></td></tr></tbody></table></div>
<p><strong>Wnioski</strong></p>
<p>Jak widać, Envers pozwala na łatwe wdrożenie historii zmian bez specjalnego nakładu pracy i praktycznie transparentnie dla istniejącego modelu. Warto też wspomnieć, że Envers stał się już częścią dystrybucji Hibernate’a (od wersji 3.5), co dodatkowo świadczy o jego użyteczności i jakości.</p>
<p><strong>Źródła</strong></p>
<p>Strona główna projektu: <a href="http://jboss.org/envers">http://jboss.org/envers</a><br />
Dokumentacja: <a href="http://docs.jboss.org/envers/docs/index.html">http://docs.jboss.org/envers/docs/index.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/praktyczny-envers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JSR-303 &#8211; przepis na fasolkę. Bardzo dobrą poniekąd. Cz. 1</title>
		<link>http://blog.atena.pl/jsr-303-przepis-na-fasolke-bardzo-dobra-poniekad-cz-1</link>
		<comments>http://blog.atena.pl/jsr-303-przepis-na-fasolke-bardzo-dobra-poniekad-cz-1#comments</comments>
		<pubDate>Thu, 11 Feb 2010 09:21:27 +0000</pubDate>
		<dc:creator>Daniel Ramotowski</dc:creator>
				<category><![CDATA[JBoss]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaEE]]></category>

		<guid isPermaLink="false">http://blog.atena.pl/?p=858</guid>
		<description><![CDATA[Finalna wersja specyfikacji JSR-303: Bean Validation ukazała się światu pod koniec ubiegłego roku (2009). Jest to kolejny przysmak a’la carte z renomowanej kuchni Gavin’a King’a i spółki, który doczekał się formalnej specyfikacji. Zatem – delektujmy się przez chwilę… Dla osób niewtajemniczonych wyjaśniam, że mam na myśli produkt hibernate-validator, który jest protoplastą specyfikacji. Wraz z nią [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Finalna wersja specyfikacji JSR-303: Bean Validation ukazała się światu pod koniec ubiegłego roku (2009). Jest to kolejny przysmak a’la carte z renomowanej kuchni Gavin’a King’a i spółki, który doczekał się formalnej specyfikacji. Zatem – delektujmy się przez chwilę…</strong><br />
<span id="more-858"></span><br />
Dla osób niewtajemniczonych wyjaśniam, że mam na myśli produkt hibernate-validator, który jest protoplastą specyfikacji.<br />
Wraz z nią otrzymaliśmy jej implementację referencyjną w postaci produktu hibernate-validator w wersji 4.<br />
Świadomy tego, że bezapelacyjnie każdego ta historia urzekła przejdę do konkretów.<br />
Dlaczego w ogóle o tym piszę? istnieje co najmniej kilka powodów:</p>
<ol>
<li>Jest to nowy standard w ramach Javy.</li>
<li>Będzie wchodził w skład JEE 6.</li>
<li>Bardzo łatwo się go używa &#8211; również na platformie SAP NetWeaver. <img src='http://blog.atena.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li>Posiada nowe rozbudowane API oraz nowe możliwości rozszerzeń (np. tzw. &#8222;composite constraints&#8221;).</li>
<li>W sposób przezroczysty integruje się z już posiadanym kodem.</li>
</ol>
<p>Ponieważ jest to artykuł subiektywny, nie zamierzam w nim wymieniać wszystkich właściwości oraz różnic w specyfikacji JSR 303 w stosunku do starego hibernate-validator&#8217;a. Ze szczegółami można zawsze zapoznać się pobierając specyfikację ze stron <a href="http://jcp.org/en/jsr/detail?id=303">Java Community Process</a>.</p>
<p>Moim zdaniem bardzo istotna jest rozbudowa specyfikacji o możliwość definiowania mechanizmów walidacji za pomocą deskryptorów XML. Być może niektórzy czytelnicy posądzą mnie tutaj o herezję, ponieważ dziesiątki deskryptorów dostępnych w JEE to swoiste &#8222;małe piekiełko&#8221;. W przypadku walidatora jest to bardzo dobry pomysł o czym świadczą silne argumenty:</p>
<ol>
<li>Deskryptory pozwalają na zastosowanie walidacji w beanach dostarczanych w postaci bibliotek,</li>
<li>Definicje w deskryptorach uniezależniają walidowane komponenty od  API walidatora oraz własnych walidatorów w formie rozszerzeń.</li>
</ol>
<p>Poniżej przedstawiam przykład kodu z zastosowaniem adnotacji oraz odpowiednika z zastosowaniem deskryptora xml.</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Person.java</span><br />
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test.beans</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.constraints.NotNull</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.Size</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.constraints.Past</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Date</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.Valid</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Person <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// wymuszenie wartości różnej niż null</span><br />
&nbsp; &nbsp; @NotNull<span style="color: #009900;">&#40;</span>message<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Imię nie może być puste&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// wymuszenie wartości różnej niż null</span><br />
&nbsp; &nbsp; @NotNull<span style="color: #009900;">&#40;</span>message<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Nazwisko nie może być puste&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> surname<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// wymuszamy datę przeszłą w stosunku do czasu systemowego</span><br />
&nbsp; &nbsp; @Past<span style="color: #009900;">&#40;</span>message<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Należy podać datę przeszłą&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Adate+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Date</span></a> birthDate<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// oczekiwanie, że w kolekcji będzie co najmniej jeden element</span><br />
&nbsp; &nbsp; @Size<span style="color: #009900;">&#40;</span>min<span style="color: #339933;">=</span><span style="color: #cc66cc;">1</span>,message<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Należy podać co najmniej jeden adres&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; @Valid <span style="color: #666666; font-style: italic;">// wskazanie aby implementacja wykonała również walidację adresów</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> List<span style="color: #339933;">&lt;</span>Address<span style="color: #339933;">&gt;</span> adrList<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #339933;">----------------------------------------------------------</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp;Address.java</span><br />
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test.beans</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.constraints.NotNull</span><span style="color: #339933;">;</span><br />
<br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Address <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// wymuszenie wartości różnej niż null</span><br />
&nbsp; &nbsp; @NotNull<span style="color: #009900;">&#40;</span>message<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;Miasto nie może być puste&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> city<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Stan analogiczny do powyższego kodu możemy uzyskać za pomocą następujących definicji w deskryptorze xml:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #808080; font-style: italic;">&lt;!-- sample-constraints.xml --&gt;</span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint-mappings</span> </span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://jboss.org/xml/ns/javax/validation/mapping&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp;<span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;default-package<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test.beans<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/default-package<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Person&quot;</span> <span style="color: #000066;">ignore-annotations</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;name&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint</span> <span style="color: #000066;">annotation</span>=<span style="color: #ff0000;">&quot;javax.validation.constraints.NotNull&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Imię nie może być puste<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/field<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;surname&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint</span> <span style="color: #000066;">annotation</span>=<span style="color: #ff0000;">&quot;javax.validation.constraints.NotNull&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Nazwisko nie może być puste<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/field<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;birthDate&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint</span> <span style="color: #000066;">annotation</span>=<span style="color: #ff0000;">&quot;javax.validation.constraints.Past&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Należy podać datę przeszłą<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/field<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;adrList&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint</span> <span style="color: #000066;">annotation</span>=<span style="color: #ff0000;">&quot;javax.validation.constraints.Size&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Należy podać co najmniej jeden adres<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;element</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;min&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/element<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;valid</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/field<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;Address&quot;</span> <span style="color: #000066;">ignore-annotations</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;field</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;city&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint</span> <span style="color: #000066;">annotation</span>=<span style="color: #ff0000;">&quot;javax.validation.constraints.NotNull&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Miasto nie może być puste<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/field<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint-mappings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>Nie jest trudno wywnioskować, że wszystkie ograniczenia zdefiniowane w kodzie źródłowym mają swoje odpowiedniki w deskryptorze. Aby powyższe przykłady uruchomić, konieczne jest jeszcze skonfigurowanie całego &#8222;silnika&#8221; walidacji.<br />
Konfigurację realizuje się przez zamieszczenie w katalogu META-INF pliku o nazwie validation.xml, który jest deskryptorem konfiguracji JSR-303.<br />
Oto przykład pliku:</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;validation-config</span> </span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://jboss.org/xml/ns/javax/validation/configuration&quot;</span></span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span><br />
<span style="color: #009900;"> &nbsp;<span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;default-provider<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.hibernate.validator.HibernateValidator<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/default-provider<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constraint-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>META-INF/sample-constraints.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constraint-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/validation-config<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></td></tr></tbody></table></div>
<p>W powyższym pliku określono następujące właściwości silnika:</p>
<ol>
<li><strong>Default-provider</strong> wskazuje dostawcę implementacji JSR-303, którym jest oczywiście hibernate validator</li>
<li><strong>Constraint-mapping</strong> wskazuje na dodatkowy deskryptor xml z definicją ograniczeń, można zdefiniować wiele plików z definicją ograniczeń</li>
</ol>
<p>Na deser pozostał mi jeszcze prościutki przykład uruchomienia walidacji w kodzie z zastosowaniem poprzednich przykładów.<br />
Oto on:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// ValidationTest.java</span><br />
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">test.beans</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.ConstraintViolation</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.Validation</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.validation.ValidatorFactory</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ValidationTest <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> argv<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ValidationTest vt <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ValidationTest<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Person p <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Person<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; p.<span style="color: #006633;">name</span><span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;John&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; t.<span style="color: #006633;">validateBean</span><span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> validateBean<span style="color: #009900;">&#40;</span>Person p<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ValidatorFactory vf <span style="color: #339933;">=</span> Validation.<span style="color: #006633;">buildDefaultValidatorFactory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Set<span style="color: #339933;">&lt;</span>ConstraintViolation<span style="color: #339933;">&gt;</span> violationSet <span style="color: #339933;">=</span> vf.<span style="color: #006633;">getValidator</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">validate</span><span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span>ConstraintViolation cv <span style="color: #339933;">:</span> violationSet <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>cv.<span style="color: #006633;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Smacznej walidacji <img src='http://blog.atena.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.atena.pl/jsr-303-przepis-na-fasolke-bardzo-dobra-poniekad-cz-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

