<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8583476407209452685</id><updated>2012-02-14T14:53:36.127+01:00</updated><category term='metody prywatne'/><category term='postgresql'/><category term='jdbc'/><category term='Integer'/><category term='testowanie'/><category term='form:checkboxes'/><category term='pula'/><category term='kurs'/><category term='Date'/><category term='Mysql'/><category term='red hat'/><category term='Hibernate'/><category term='komunikat'/><category term='pivot'/><category term='pola prywatne'/><category term='ESI'/><category term='Shared Libraries'/><category term='db2'/><category term='comparator'/><category term='DataSource'/><category term='hiberante validator'/><category term='prywatne atrybuty'/><category term='pool'/><category term='eskejpowanie'/><category term='no matching editors or conversion strategy found'/><category term='seam-gen'/><category term='L1 cache'/><category term='Too many open files'/><category term='treeset'/><category term='crosstab'/><category term='walidacja'/><category term='WebSphere Integration Developer'/><category term='partial mocking'/><category term='hashCode'/><category term='Websphere Application Server'/><category term='eclipse'/><category term='Spring'/><category term='WAS'/><category term='internacjonalizacja'/><category term='CakePHP'/><category term='IBM'/><category term='h:selectManyCheckbox'/><category term='pragmatyzm'/><category term='backslash'/><category term='logika'/><category term='jsr 303'/><category term='java'/><category term='adnotacje'/><category term='not a valid reference'/><category term='seam'/><category term='tutorial'/><category term='WebSphere Process Server'/><category term='WID'/><category term='częściowe mockowanie'/><category term='eclipse.ini'/><category term='PHP'/><category term='jvm terminated exit code=-1'/><category term='silent mode'/><category term='cudzysłów'/><category term='przykłady'/><category term='instalacja'/><category term='wps'/><category term='replaceAll'/><category term='intuicja'/><category term='velocity'/><category term='equals'/><category term='PowerMock'/><category term='examples'/><category term='mechanizm refleksji'/><category term='problem'/><title type='text'>Andrzej Ludwikowski - technologie webowe.</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5819850624392674952</id><published>2012-02-03T15:14:00.000+01:00</published><updated>2012-02-03T15:14:20.686+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='walidacja'/><category scheme='http://www.blogger.com/atom/ns#' term='adnotacje'/><title type='text'>Przekazywanie adnotacji do adnotacji.</title><content type='html'>Adnotacje mają pewne swoje ograniczenia. Pierwsze z nich to fakt, że danej adnotacji do danego targetu możemy użyć tylko raz.&lt;br /&gt;&lt;br /&gt;Bazując na przykładzie z &lt;a href="http://aludwikowski.blogspot.com/2012/02/hibernate-validator-jsr-303-mechanizm.html"&gt;poprzedniego posta&lt;/a&gt;, jeśli w klasie Entity, mamy 2 pary pól do identycznej walidacji, np:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class Entity {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private Date from;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private Date to;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private Date activeFrom;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private Date activeTo;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To użycie tej samej adnotacji walidującej dwa razy jest niedozwolone.&lt;br /&gt;&lt;pre class="java" name="code"&gt;@CheckDates(dateFrom="from", dateTo="to")&lt;br /&gt;@CheckDates(dateFrom="activeFrom", dateTo="activeTo")&lt;br /&gt;public class Entity {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date from;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date to;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date activeFrom;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date activeTo;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Rozwiązaniem tego problemu jest wykorzystanie kolejnego ograniczenia adnotacji, mówięcego, że parametrem adnotacji może być tylko typ prymitywny, String, Class, enum, inna adnotacja, lub tablica 1-wymiarowa tablica wymienionych wcześniej klas.&lt;br /&gt;&lt;br /&gt;Implementacja czegoś takiego mogłba by być następująca:&lt;br /&gt;&lt;pre class="java" name="code"&gt;@Target({ TYPE })&lt;br /&gt;@Retention(RUNTIME)&lt;br /&gt;@Constraint(validatedBy = MultiCheckDatesValidator.class)&lt;br /&gt;public @interface MultiCheckDates {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String message() default "{pl.costam.MultiCheckDates}";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Class&amp;lt;?&amp;gt;[] groups() default {};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Class&amp;lt;? extends Payload&amp;gt;[] payload() default {};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CheckDates[] value();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I sam walidator, który tak de facto w pętli wywołuje walidator z poprzedniego posta (musimy jedynie dopisać konstruktor):&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class MultiCheckDatesValidator implements ConstraintValidator&amp;lt;MultiCheckDates, Object&amp;gt; {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private CheckDates[] checkDates;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void initialize(MultiCheckDates constraintAnnotation) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; checkDates = constraintAnnotation.value();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean isValid(Object object, ConstraintValidatorContext context) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; boolean isValid = true;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for (CheckDates checkDate : checkDates) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;* tworzymy i wywołujemy walidator dla pojedyńczej pary from-to&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;*/&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!new CheckDatesValidator(checkDate).isValid(object, context)) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; isValid = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return isValid;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I samo wywołanie:&lt;br /&gt;&lt;pre class="java" name="code"&gt;@MultiCheckDates({&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @CheckDates(dateFrom = "from", dateTo = "to"),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; @CheckDates(dateFrom = "activeFrom", dateTo = "activeTo") })&lt;br /&gt;public class Entity {&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Za piękne może to i nie jest, ale warto mieć świadomość limitów wykorzystania adnotacji. Prawdopodobnie lepszym rozwiązaniem byłoby stworzenie osobnej klasy DateRange, jak zasugerował to &lt;cite class="user"&gt;&lt;a href="http://www.blogger.com/profile/00672953404604806278" rel="nofollow"&gt;Michał Gruca&lt;/a&gt;&lt;/cite&gt;&lt;span class="icon user"&gt;&lt;/span&gt;&lt;span class="datetime secondary-text"&gt;&lt;/span&gt; w swoim &lt;a href="http://aludwikowski.blogspot.com/2012/02/hibernate-validator-jsr-303-mechanizm.html?showComment=1328270275469#c2825079617264770090"&gt;komentarzu&lt;/a&gt;.&lt;br /&gt;Choć czasami zastajemy kod taki a nie inny i refaktor bywa bardzo bolesny.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5819850624392674952?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5819850624392674952/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2012/02/przekazywanie-adnotacji-do-adnotacji.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5819850624392674952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5819850624392674952'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2012/02/przekazywanie-adnotacji-do-adnotacji.html' title='Przekazywanie adnotacji do adnotacji.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5637296161050096127</id><published>2012-02-03T12:08:00.000+01:00</published><updated>2012-02-03T12:08:29.201+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hiberante validator'/><category scheme='http://www.blogger.com/atom/ns#' term='mechanizm refleksji'/><category scheme='http://www.blogger.com/atom/ns#' term='walidacja'/><category scheme='http://www.blogger.com/atom/ns#' term='jsr 303'/><title type='text'>Hibernate Validator (JSR 303) + mechanizm refleksji = walidacja absolutna</title><content type='html'>Przygarnięcie przez JavaEE projektu &lt;a href="http://www.hibernate.org/subprojects/validator.html"&gt;Hibernate Validator&lt;/a&gt; pod numerem &lt;a href="http://jcp.org/en/jsr/detail?id=303"&gt;JSR 303&lt;/a&gt; było wg. mnie kolejnym dobrym krokiem w standaryzacji dobry rozwiązań z projektów opensourcowych.&lt;br /&gt;&lt;br /&gt;Jednak po jakimś czasie używania (jakże przyjemnego) standardowych walidatorów, doszedłem do wniosku, że to za mało. Napisanie &lt;a href="http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html"&gt;kilku własnych&lt;/a&gt;, które swoją drogą również tworzy się bardzo prosto, tylko na chwilę zaspokoiło moje potrzeby. Dopiero połączenie JSR 303 i mechanizmu refleksji w javie, daje maksymalne możliwości wykorzystania tego standardu.&lt;br /&gt;&lt;br /&gt;Załóżmy, że mamy klasę która posiada dwie daty: od i do.&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class Entity {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date from;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date to;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Chcielibyśmy sprawdzić czy podane daty są po kolei, tj 'from' &amp;lt;= 'to'. Możemy napisać własny walidator dla klasy Entity, ale w projekcie takich klas z datami możemy mieć mnóstwo i dla każdej z nich należałoby stworzyć oddzielny walidator. Dzięki refleksją w javie możemy zrobić jeden uniwersalny, który jako parametry przyjmowałby 2 wartości, nazwa pola 'from', nazwa pola 'to'.&lt;br /&gt;&lt;pre class="java" name="code"&gt;@Target({ TYPE })&lt;br /&gt;@Retention(RUNTIME)&lt;br /&gt;@Constraint(validatedBy = CheckDatesValidator.class)&lt;br /&gt;public @interface CheckDates {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String message() default "{pl.costam.CheckDates}";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Class&amp;lt;?&amp;gt;[] groups() default {};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Class&amp;lt;? extends Payload&amp;gt;[] payload() default {};&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String dateFrom();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; String dateTo();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I sam walidator:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class CheckDatesValidator implements ConstraintValidator&amp;lt;CheckDates, Object&amp;gt; {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String dateFromFieldName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String dateToFieldName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private String message;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void initialize(CheckDates checkDates) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; dateFromFieldName = checkDates.dateFrom();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; dateToFieldName = checkDates.dateTo();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; message = checkDates.message();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean isValid(Object object, ConstraintValidatorContext context) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; boolean result = validateDates(object);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!result) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //jeśli walidacja nie powiodła sie to tworzymy własny constraint - wskazujemy dla którego pola wystąpił błąd&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; context.disableDefaultConstraintViolation();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; context.buildConstraintViolationWithTemplate(message)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .addNode(dateToFieldName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .addConstraintViolation();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return result;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private boolean validateDates(Object object) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Date dateFrom = field(dateFromFieldName).ofType(Date.class).in(object).get();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Date dateTo = field(dateToFieldName).ofType(Date.class).in(object).get();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // sprawdzenie dat&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return checkDatesInterval(dateFrom, dateTo);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; e.printStackTrace();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Poprzez refleksję można odwołać sie do pola używając właściwie "czystej" javy, ale wygląda to średnio w kodzie i lepiej użyć jakiegoś gotowego rozwiązania. Ja osobiście polecam biliotekę: &lt;a href="http://docs.codehaus.org/display/FEST/Accessing+Fields"&gt;FEST&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Zastowanie adnotacji jest następujące:&lt;br /&gt;&lt;pre class="java" name="code"&gt;@CheckDates(dateFrom="from", dateTo="to")&lt;br /&gt;public class Entity {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date from;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Date to;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5637296161050096127?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5637296161050096127/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2012/02/hibernate-validator-jsr-303-mechanizm.html#comment-form' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5637296161050096127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5637296161050096127'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2012/02/hibernate-validator-jsr-303-mechanizm.html' title='Hibernate Validator (JSR 303) + mechanizm refleksji = walidacja absolutna'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-3508150619717448798</id><published>2011-11-09T12:46:00.000+01:00</published><updated>2011-11-09T12:46:34.623+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='L1 cache'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate L1 cache a cachowanie zapytań.</title><content type='html'>Niby wszyscy wiedzą jak działa działa L1 cache w Hibernate. W ramach jednej sesji hibernata, jeśli wczytamy sobie jakiś obiekt za pomocą np. funkcji .get(), to każde kolejne wywołanie tej funkcji nie odpytuje już bezpośrednio bazy danych, tylko zwraca ten obiekt właśnie z sesji. Pytanie, czy jesteśmy świadomi wszystkich konsekwencji takiego podejścia?&lt;br /&gt;&lt;br /&gt;Proponuje zagadkę.&lt;br /&gt;W bazie jest 2 użytkowników z tego samego miasta: Andrzej i Wojtek. Metoda getAllUsersFromCity() tworzy odpowiedni obiekt Criteria i zwraca listę użytkowników z danego miasta. Przyjmijmy, że kod funkcji testCache() wykonywany jest w ramach jednej sesji hibernata:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;public void testCache(){&lt;br /&gt;&amp;nbsp; &amp;nbsp; printUsers();&lt;br /&gt;&amp;nbsp; &amp;nbsp; //w tym momecie ktoś inny edytuje jednego z użytkowników,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //w zupełnie innej sesji lub bezpośrednio na bazie,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //zmienia nazwe z Andrzej na Bartek&lt;br /&gt;&amp;nbsp; &amp;nbsp; printUsers();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void printUsers(){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;User&amp;gt; users = dao.getAllUsersFromCity("city");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach(User user : users){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.out.println(user.getName());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Co zostanie wyświetlone na ekranie?&lt;br /&gt;a)AndrzejWojtekAndrzejWojtek&lt;br /&gt;b)AndrzejWojtekBartekWojtek&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-3508150619717448798?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/3508150619717448798/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/11/hibernate-l1-cache-cachowanie-zapytan.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3508150619717448798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3508150619717448798'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/11/hibernate-l1-cache-cachowanie-zapytan.html' title='Hibernate L1 cache a cachowanie zapytań.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5851373811296032943</id><published>2011-08-31T15:28:00.000+02:00</published><updated>2011-08-31T15:28:31.308+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='velocity'/><category scheme='http://www.blogger.com/atom/ns#' term='not a valid reference'/><title type='text'>Velocity - "is not a valid reference".</title><content type='html'>Jeśli masz problem z odwołaniem się w Velocity do metody jakiegoś obiektu, np.&lt;br /&gt;&lt;blockquote&gt;$someObject.getSomeField()&lt;/blockquote&gt;i dostajesz komunikat:&lt;br /&gt;&lt;blockquote&gt;... is not a valid reference&lt;/blockquote&gt;To warto sprawdzić czy klasa obiektu someObject jest &lt;b style="color: red;"&gt;publiczna&lt;/b&gt;, w przeciwnym razie otrzymasz wspomniany wyżej komunikat.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5851373811296032943?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5851373811296032943/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/08/velocity-is-not-valid-reference.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5851373811296032943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5851373811296032943'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/08/velocity-is-not-valid-reference.html' title='Velocity - &quot;is not a valid reference&quot;.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-2244118112428637151</id><published>2011-06-28T15:09:00.000+02:00</published><updated>2011-06-28T15:09:13.953+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='intuicja'/><category scheme='http://www.blogger.com/atom/ns#' term='pragmatyzm'/><category scheme='http://www.blogger.com/atom/ns#' term='logika'/><title type='text'>Logika + intuicja = inteligencja ?</title><content type='html'>Rzadko mi się to zdarza, ale czasem trzeba usiąść i przewartościować to i owo w swoim życiu. Bez obaw, nie będzie to tekst o uczuciach, związkach i innych takich:) Będzie o sposobie myślenia, przyswajania wiedzy i to niekoniecznie w stricte programistycznym kontekście.&lt;br /&gt;&lt;br /&gt;Czy zdarzyło Ci się kiedyś, że poświeciłeś 2/3 dni na jakiś problem, zadanie - bez większych rezultatów, a nagle (czasami nawet kilka dni później), nie wiadomo skąd - oświecenie - Twój mózg dostarcza rozwiązanie, praktycznie na talerzu. Ja miałem tak przy całkach, czasami potrafiłem zmarnować cały dzień na 1 całkę, żeby rano obudzić się i ją po prostu ładnie rozpisać. Jeśli chcesz wiedzieć skąd się to bierze, to koniecznie musisz przeczytać:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://www.blogger.com/goog_1736012938" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/-IZFHzGtBacw/TgmY8bQBDDI/AAAAAAAAAD8/2CvhX4-MG90/s200/pragmatic.jpeg" width="166" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://pragprog.com/titles/ahptl/pragmatic-thinking-and-learning"&gt;Pragmatic Thinking and Learning: Refactor Your Wetware&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;Tutył tcorhę nie ceikawy, ale jśeli ztsawnaaisz się delazcgo potarsfiz pzreyczatć ten tkest bez wikęzsyh porblmóew, to opdoeiwdź na m.in. to pyatine zanjzdisez w tej kąsicże. &lt;br /&gt;&lt;br /&gt;Co do przewartościowania, to musiałem zmienić swój pogląd dotyczący wszelkich aktywności o naturze bardziej "artystycznej", które uważałem, do tej pory, za nieprzydatne i zbędne (przynajmniej dla mnie). Myślałem, że &lt;b&gt;logika&lt;/b&gt; jest głównym silnikiem mojego mózgu. Co nie mija się mocno z prawdą, aczkolwiek każdy z nas ma &lt;b&gt;drugi silnik&lt;/b&gt; - zupełnie nielogiczny i bardzo abstrakcyjny. &lt;b&gt;Intuicja&lt;/b&gt;, instynkt (tak nazywany jest ten silnik) wydają się nie do końca potrzebne w przypadku np. programowania, ale tak de facto dopiero one pozwalają w pełni rozwinąć skrzydła (właściwie czymkolwiek byśmy się nie zajmowali). To właśnie silnik nr 2 pozwala obudzić się z rozwiązaną całką przed oczyma. Jego możliwości są praktycznie nieskończone jak i bardzo nieprzewidywalne. Ważne jest aby dbać i rozwijać oba silniki. Jak sugeruje autor książki, właśnie aktywności wywodzące się z szeroko rozumianej sztuki, rozwijają ten drugi silnik. Wątpię żebym nagle zaczął pisać wiersze, ale dostrzegam sens np. plastyki (i innych podobnych przedmiotów) w szkole, które (pomijając to, że były moim zdaniem po prostu źle prowadzone) mogą przydać się w ogólnym rozwoju.&lt;br /&gt;&lt;br /&gt;Tak samo krytycznie nastawiony byłem do różnego rodzaju "niestandardowych" sposobów nauczania. Nie twierdze, że nagle wszystkie nabierają dla mnie sensu, ale cześć technik, ma swoje naukowe uzasadnienie i muszę przyznać, że chciałbym kilka z nich wypróbować. Mam nadzieję, że wystarczająco zaciekawiłem, aczkolwiek ciężko streścić książkę, która sama w sobie jest streszczeniem wielu prac i badań naukowych.&lt;br /&gt;&lt;br /&gt;Dla tych bardziej leniwych, polecam wykład, który w dużej mierze pokrywa się z tą książką:&lt;br /&gt;&lt;a href="http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas"&gt;http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wyjściowym źródłem informacji dla mnie był m.in. blog:&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2011/06/trawienie-confitury.html"&gt;http://art-of-software.blogspot.com/2011/06/trawienie-confitury.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html"&gt;http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-2244118112428637151?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/2244118112428637151/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/06/logika-intuicja-inteligencja.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2244118112428637151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2244118112428637151'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/06/logika-intuicja-inteligencja.html' title='Logika + intuicja = inteligencja ?'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-IZFHzGtBacw/TgmY8bQBDDI/AAAAAAAAAD8/2CvhX4-MG90/s72-c/pragmatic.jpeg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1238827311862023297</id><published>2011-06-21T15:04:00.001+02:00</published><updated>2011-06-21T15:06:22.458+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='testowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='częściowe mockowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='partial mocking'/><title type='text'>Partial mock - stosować, czy nie?</title><content type='html'>Na samym początku chcę zaznaczyć, że prawdopodobnie ten post &lt;b&gt;nie  będzie &lt;/b&gt;udzielał jednoznacznej odpowiedzi, jego celem (przynajmniej na  chwilę obecną) jest zebranie wszystkich za i przeciw stosowaniu  częściowego mockowania.&lt;br /&gt;&lt;br /&gt;Zakładam, że ewentualnemu  czytelnikowi sama idea mockowania jest znana. &lt;b&gt;Partial mock&lt;/b&gt; danego  obiektu to taka hybryda prawdziwego obiektu i mocka, innymi słowy część  metod danego obiektu może być zmockowana, a cześć działać normalnie.  Więcej o tym:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/powermock/wiki/MockPartial"&gt;PowerMock&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;a href="http://mockito.googlecode.com/svn/branches/1.5/javadoc/org/mockito/Mockito.html"&gt;Mockito&lt;/a&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;Co to daje? Przede wszystkim&lt;b&gt; ułatwia testowanie&lt;/b&gt;, czy raczej samo napisanie testu. Wyobraźmy sobie sytuację, w której dana klasa ma jedną publiczną metodę, która korzysta z 20 innych prywatnych, pozagnieżdżanych między sobą. Załóżmy, że te 20 metod tworzy spójną całość i wydzielanie ich do osobnych klas byłoby bezsensowne. Napisanie testu dla takiej publicznej metody jest zajęciem dość karkołomnym. Taki test, który np. sprawdzałby czy metoda 17 robi coś tam poprawnie, zawiera w sobie całą masę mocków i innych obiektów, które umożliwiają taki przepływ w kodzie klasy, aby dojść do tej metody 17 i ją przetestować. Zrozumienie takiego testu dla człowieka, który go nie pisał jest dramatem.&lt;br /&gt;&lt;br /&gt;Czy nie lepiej napisać oddzielny test dla metody 17? A potem odpowiednio sprawdzić, czy metoda ta jest wywoływana w innej metodzie, właśnie za pomocą partial mockingu? Jak dla mnie takie podejście jest o wiele przejrzystsze.&lt;br /&gt;&lt;br /&gt;Konserwatywni w dziedzinie testowania, na pewno już się gotują, że piszę o testowaniu metod prywatnych, ale powiedzmy, że zmieniam im dostęp na pakietowy:). Tak, czy inaczej na pewno nie pochwalą partial mocków, bo to podejście śmierdzi, jest "niekoszerne".&lt;br /&gt;&lt;br /&gt;Ogólnie zgadzam się z nimi w jednej kwestii, na pewno konieczność zastosowanie partial mockingu do testów, jest bardzo wyraźnym sygnałem, że z naszym kodem jest coś nie tak i prawdopodobnie lepszym wyjściem będzie jego &lt;b&gt;refaktoring&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Jednakże istnieją sytuacje (jak chociażby legacy code), gdzie partial mock jest nie dość, że wygodnym, to czytelnym rozwiązaniem. &lt;br /&gt;&lt;br /&gt;Oczywiście nie jestem w dziedzinie testów aż takim ekspertem jakbym chciał, dlatego jeśli istnieją inne przesłanki za lub przeciw partial mockom, to proszę o komentarze.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Artykuły o partial mocking:&lt;/u&gt;&lt;br /&gt;&lt;a href="http://nathan.crause.name/entries/programming/partial-mocking-stubbing-and-why-it-s-not-evil"&gt;http://nathan.crause.name/entries/programming/partial-mocking-stubbing-and-why-it-s-not-evil&lt;/a&gt;&lt;br /&gt;&lt;a href="http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring/"&gt;http://monkeyisland.pl/2009/01/13/subclass-and-override-vs-partial-mocking-vs-refactoring/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/3806977/partial-mocking-as-code-smell"&gt;http://stackoverflow.com/questions/3806977/partial-mocking-as-code-smell&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1238827311862023297?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1238827311862023297/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/06/partial-mock-stosowac-czy-nie.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1238827311862023297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1238827311862023297'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/06/partial-mock-stosowac-czy-nie.html' title='Partial mock - stosować, czy nie?'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-535834573929747047</id><published>2011-04-18T14:54:00.000+02:00</published><updated>2011-04-18T14:54:38.054+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Date'/><title type='text'>Zagadka java Date()</title><content type='html'>Jaki będzie wynik poniższego kodu:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;System.out.println(new Date().getTime() &lt; new Date().getTime());&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-535834573929747047?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/535834573929747047/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/04/zagadka-java-date.html#comment-form' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/535834573929747047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/535834573929747047'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/04/zagadka-java-date.html' title='Zagadka java Date()'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-6328485794460772251</id><published>2011-04-08T07:56:00.004+02:00</published><updated>2011-04-12T12:07:16.555+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hashCode'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='equals'/><title type='text'>Equals, hashCode i Hibernate</title><content type='html'>Ok, to był dość długi wstęp (&lt;a href="http://aludwikowski.blogspot.com/2011/02/metody-equlas-i-hashcode-w-javie.html"&gt;1&lt;/a&gt;, &lt;a href="http://aludwikowski.blogspot.com/2011/03/metoda-hashcode-w-javie.html"&gt;2&lt;/a&gt;, &lt;a href="http://aludwikowski.blogspot.com/2011/03/testowanie-equals-i-hashcode.html"&gt;3&lt;/a&gt;), może czasami jak dla dzieci, ale przynajmniej wszystko jest w 1 miejscu, a składa się na meritum problemu, czyli jak powinno się implementować metody equals() i hashCode() &lt;b&gt;w połączeniu z Hibernatem&lt;/b&gt;. Mówiąc jeszcze bardziej precyzyjnie, czy możną używać pola reprezentującego klucz główny tabeli w tych metodach. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Najpierw trochę literatury:&lt;br /&gt;&lt;a href="http://community.jboss.org/wiki/EqualsandHashCode"&gt;http://community.jboss.org/wiki/EqualsandHashCode&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="https://forum.hibernate.org/viewtopic.php?t=928172"&gt;https://forum.hibernate.org/viewtopic.php?t=928172&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=2"&gt;http://onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=2&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Wnioski z tego, z czym się do tej pory zapoznałem, są takie, że Hibernate mówi: nie używajcie ID, ale jak już musicie, to przynajmniej upewnijcie się, że obiekty (które będą porównywane) są w tej samej sesji! &lt;u&gt;Dlatego proponuję otwartą dyskusję na ten temat.&lt;/u&gt; Obecnie przyjąłem sobie następujący schemat pisania equals() i hashCode(). W equals() biorę pod uwagę tylko id jeśli oba obiekty mają ustawione id (w moim przypadku różne od 0). W przeciwnym wypadku porównuję odpowiednie pola. W hashCode() nie wykorzystuje id, ponieważ może dojść do sytuacji, w której 2 obiekty takie same, będą miały różne hashe.&lt;br /&gt;&lt;pre class="java" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object object) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (this == object) return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if ( !(object instanceof Entity) ) return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Entity entity = (Entity) object;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (id != 0 &amp;amp;&amp;amp; entity.getId()!=0){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return id == entity.getId();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new EqualsBuilder().append(field, entity.getField())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ...//i inne pola&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .isEquals();&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-6328485794460772251?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/6328485794460772251/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/04/equals-hashcode-i-hibernate.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6328485794460772251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6328485794460772251'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/04/equals-hashcode-i-hibernate.html' title='Equals, hashCode i Hibernate'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-503632433244445810</id><published>2011-03-28T09:13:00.000+02:00</published><updated>2011-03-28T09:13:49.708+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='testowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='hashCode'/><category scheme='http://www.blogger.com/atom/ns#' term='equals'/><title type='text'>Testowanie equals i hashCode</title><content type='html'>Zgodnie z obecną modą na wszechobecne testy jednostkowe wypadałoby jakoś testować nasze implementacje equals() i hashCode(), żeby się przy tym zbytnio nie narobić proponuję następujące rozwiązanie: klasa abstrakcycja, która sprawdza podstawowe warunki konktraktu dla equals() i hashCode() na podstawie 3 dostarczonych przez klasę dziedziczącą obiektów, które powinnym być identyczne wg. equals (ale maksymalnie od siebie różne) oraz jednego, który jest różny od pozastałych wg. equals. &lt;b&gt;Pełny kod źródłowy&lt;/b&gt; wraz z klasą abstrakcyjną można pobrać korzystając &lt;a href="http://www.aludwik.webd.pl/AbstractEqualsTest.rar"&gt;z tego linku.&lt;/a&gt; Zastosowanie najlepiej widać na przykładzie:&lt;br /&gt;&lt;br /&gt;Klasa testowana:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class Entity {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int field1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int field2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int notSignificantField;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int hashCode() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object object) {&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Entity(int field1, int field2, int notSignificantField) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.field1 = field1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.field2 = field2;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.notSignificantField = notSignificantField;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Klasa testująca:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class EntityTest extends AbstractEqualsTest&amp;lt;Entity&amp;gt; {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Entity objectThatShouldBeEqualA() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new Entity(1, 2, 33);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Entity objectThatShouldBeEqualB() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new Entity(1, 2, 44);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Entity objectThatShouldBeEqualC() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new Entity(1, 2, 55);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Entity objectThatShouldNotBeEqual() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new Entity(1, 1, 33);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-503632433244445810?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/503632433244445810/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/testowanie-equals-i-hashcode.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/503632433244445810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/503632433244445810'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/testowanie-equals-i-hashcode.html' title='Testowanie equals i hashCode'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-3727735546581421697</id><published>2011-03-03T14:42:00.000+01:00</published><updated>2011-03-03T14:42:33.481+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hashCode'/><title type='text'>Metoda hashCode w javie</title><content type='html'>Nudów ciąg dalszy, czyli kilka słów o metodzie hashCode(), która &lt;b&gt;powinna być zawsze nadpisana, jeśli nadpisaliśmy metodą equals().&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;1. Kontrakt dla metody hashCode().&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Metoda musi spełniać następujące warunki:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; W czasie działania aplikacji metoda zawsze zwraca tą samą wartość int, dla tego samego obiektu.&lt;/li&gt;&lt;li&gt;Jeśli dwa obiekty &lt;b&gt;są&lt;/b&gt; &lt;b&gt;równe &lt;/b&gt;wg. metody equals() to wartości zwracane przez hashCode() dla tych obiektów &lt;b&gt;muszą&lt;/b&gt; być takie same.&lt;/li&gt;&lt;li&gt;Jeśli dwa obiekty &lt;b&gt;nie są&lt;/b&gt; &lt;b&gt;równe&lt;/b&gt; wg. metody equals() to wartości zwracane przez hashCode() dla tych obiektów &lt;b&gt;nie muszą&lt;/b&gt; być takie same. Aczkolwiek zaleca się taką implementację hashCode(), żeby dla różnych obiektów zwracała różne wartości hash, co wpływa pozytywnie na szybkość operacji na hashowalnych kolekcjach.&lt;/li&gt;&lt;/ul&gt;Chyba największą trudnością przy implementacji hashCode jest wybór odpowiednich pól, na bazie których, będzie liczony hash. Jak ktoś lubi może stosować różne kombinację podczas obliczania hash'a (cała masa tego w necie), ale chyba lepiej i wygodniej skorzystać z gotowych rozwiązań (Commons, Guava):&lt;br /&gt;&lt;pre class="java" name="code"&gt;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int hashCode() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return new HashCodeBuilder().append(someField)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .append(someField2)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .toHashCode();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-3727735546581421697?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/3727735546581421697/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/metoda-hashcode-w-javie.html#comment-form' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3727735546581421697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3727735546581421697'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/metoda-hashcode-w-javie.html' title='Metoda hashCode w javie'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1488356152516515929</id><published>2011-03-02T10:47:00.001+01:00</published><updated>2011-03-02T17:21:13.039+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='comparator'/><category scheme='http://www.blogger.com/atom/ns#' term='treeset'/><title type='text'>Zagadka</title><content type='html'>Jak ten młody leszcz dałem się ostatnio nabrać na TreeSet w Javie. Oto zagadka:&lt;br /&gt;chciałem sobie posortować liście na podstawie ich koloru, użyłem TreeSet'a, jaki będzie wynik funkcji shouldTestTreeSet(), jaka będzie kolejność liści?&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;class Leaf{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int color;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;int size;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Leaf(int color, int size) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;this.color = color;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;this.size = size;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public boolean equals(Object obj) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if (obj == this) return true;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if (!(obj instanceof Leaf)) return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Leaf leaf = (Leaf) obj;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return new EqualsBuilder().append(this.color, leaf.color)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;.append(this.size, leaf.size).isEquals();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int hashCode() {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return new HashCodeBuilder().append(color).append(size).toHashCode();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String toString() {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return String.valueOf(color + " " +size);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class LeafComparator implements Comparator&amp;lt;Leaf&amp;gt;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public int compare(Leaf o1, Leaf o2) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return Ints.compare(o1.color, o2.color);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class TreeSetTest {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public void shouldTestTreeSet() {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Leaf leaf = new Leaf(1,1);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Leaf leaf2 = new Leaf(1,2);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Leaf leaf3 = new Leaf(1,3);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Set&amp;lt;Leaf&amp;gt; tree = new TreeSet&amp;lt;Leaf&amp;gt;(new LeafComparator());&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;tree.add(leaf3);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;tree.add(leaf);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;tree.add(leaf2);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;System.out.println(tree);&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1488356152516515929?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1488356152516515929/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/zagadka.html#comment-form' title='Komentarze (8)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1488356152516515929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1488356152516515929'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/03/zagadka.html' title='Zagadka'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1273836480459496937</id><published>2011-02-24T14:02:00.014+01:00</published><updated>2011-02-28T11:54:19.593+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='hashCode'/><category scheme='http://www.blogger.com/atom/ns#' term='equals'/><title type='text'>Metody equlas i hashCode w Javie.</title><content type='html'>Niestety, aby dojść do meritum problemu, muszę część rzeczy powielić po raz kolejny, żeby nie szukać tego po innych stronach. Dopiero kolejny post będzie dotyczył konkretnie problemu equals i hashCode w kontekście użycia z Hibernatem.&lt;br /&gt;&lt;br /&gt;Czyli, na początek, standardowo - jak powinno się zaimplementować metodę equals i hashCode.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;1. Sygnatura metody.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Niby wszyscy wiedzą, że metoda eguals powinna zawsze wyglądać tak:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public boolean equals(Object other)&lt;br /&gt;&lt;/pre&gt;ale warto wspomnieć dlaczego np. nie można zastosować (dla obiektu Entity) czegoś takiego:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public boolean equals(Entity entity)&lt;br /&gt;&lt;/pre&gt;problemy pojawiają się, np. przy użyciu kolekcji:&lt;br /&gt;&lt;pre class="java" name="code"&gt;Entity entity = new Entity(1);&lt;br /&gt;Entity entity2 = new Entity(2);&lt;br /&gt;System.out.println(entity.equals(entity2)); //zwraca true&lt;br /&gt;&lt;br /&gt;Set&amp;lt;Entity&amp;gt; encje = new HashSet&amp;lt;Entity&amp;gt;();&lt;br /&gt;encje.add(entity);&lt;br /&gt;System.out.println(encje.contains(entity2)); //zwraca false&lt;br /&gt;&lt;/pre&gt;ostatnia linijka zwraca false, ponieważ źle nadpisaliśmy metodę equals() z klasy Object, która jako parametr przyjmuje Object. Dlatego nasza metoda to jedynie przeładowanie metody equals, a nie jej nadpisanie.&lt;br /&gt;&lt;br /&gt;Reasumując, prawidłowa metoda equals ma sygnaturę:&lt;br /&gt;&lt;pre class="java" name="code"&gt;@Override&lt;br /&gt;public boolean equals(Object other)&lt;br /&gt;&lt;/pre&gt;i koniec kropka!!!!! Strażnikiem poprawności sygnatury jest adnotacja oczywiście @Override, jeśli kompilator nie warczy, że jest źle użyta, to z naszą sygnaturą jest wszystko OK (o ile nie dziedziczymy z jakiejś innej klasy...).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;2. Kontrakt dla metody equals().&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Metoda musi spełniać następujące warunki:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt; zwrotność&lt;/b&gt;, czyli x.equals(x) == true&lt;/li&gt;&lt;li&gt;&lt;b&gt; symetryczność&lt;/b&gt;, czyli x.equals(y) == true, wtedy i tylko wtedy gdy y.equals(x) == true&lt;/li&gt;&lt;li&gt;&lt;b&gt; przechodniość&lt;/b&gt;, czyli jeśli x.equals(y)==true i y.equals(z)==true, wtedy x.equals(z)==true&lt;/li&gt;&lt;li&gt;&lt;b&gt;konsekwentność&lt;/b&gt;, czyli wielokrotne powtórzenie x.equals(y) zwraca zawsze tą wartość dla niezmienionych obiektów x i y.&lt;/li&gt;&lt;li&gt;dla wartości null (np. x.equals(&lt;b&gt;null&lt;/b&gt;)) metoda zawsze powinna zwracać &lt;b&gt;false&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;Największą trudność w implementacji sprawia punkt 3., dlatego warto się mu przyjrzeć dokładniej. Rozważmy następujące klasy:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class Point {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private final int x;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private final int y;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Point(int x, int y) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.x = x;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.y = y;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object o) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(o instanceof Point))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Point p = (Point) o;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return p.x == x &amp;amp;&amp;amp; p.y == y;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //...&lt;br /&gt;}&lt;br /&gt;public class ColorPoint extends Point {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Color color;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public ColorPoint(int x, int y, Color color) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; super(x, y);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; this.color = color;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&lt;br /&gt;//łamie symetryczność&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object o) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(o instanceof ColorPoint))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ColorPoint cp = (ColorPoint) o;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return super.equals(o) &amp;amp;&amp;amp; cp.color == color;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Na pierwszy rzut oka wszystko jest ok, aczkolwiek złamany jest punkt drugi kontraktu, tj. &lt;b&gt;symetryczność&lt;/b&gt;:&lt;br /&gt;&lt;pre class="java" name="code"&gt;Point p = new Point(1, 2);&lt;br /&gt;ColorPoint cp = new ColorPoint(1, 2, Color.RED);&lt;br /&gt;&lt;br /&gt;p.equals(cp); //true&lt;br /&gt;cp.equals(p); //false&lt;br /&gt;&lt;/pre&gt;możemy oczywiście poprawić metodę tak aby symetryczność została zachowana:&lt;br /&gt;&lt;pre class="java" name="code"&gt;&amp;nbsp; &amp;nbsp; //łamie przechodniość &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object o) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(o instanceof Point))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // If o is a normal Point, do a color-blind comparison&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(o instanceof ColorPoint))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return o.equals(this);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // o is a ColorPoint; do a full comparison&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ColorPoint cp = (ColorPoint) o;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return super.equals(o) &amp;amp;&amp;amp; cp.color == color;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&lt;/pre&gt;niestety, w tym przypadku łamana jest &lt;b&gt;przechodniość&lt;/b&gt;:&lt;br /&gt;&lt;pre class="java" name="code"&gt;ColorPoint p1 = new ColorPoint(1, 2, Color.RED); &lt;br /&gt;Point p2 = new Point(1, 2); &lt;br /&gt;ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);&lt;br /&gt;&lt;br /&gt;p1.equals(p2) //true&lt;br /&gt;p2.equals(p3) //true&lt;br /&gt;p1.equals(p3) //false&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;Niestety powyższy problem nie ma jednego dobrego rozwiązania. Taka jest natura obiektowo zorientowanego programowania. Mało tego nawet niektóre obiekty języka Java mają ten problem, np equals() z klasy &lt;a href="http://download.oracle.com/javase/1.5.0/docs/api/java/sql/Timestamp.html#equals%28java.lang.Object%29"&gt;Timestamp&lt;/a&gt; (która jest podklasą Date) łamie symetryczność.&lt;br /&gt;&lt;br /&gt;Można to obejść np. zamiast dziedziczenia Point dodać prywatne pole typu Point do klasy ColorPoint, wtedy:&lt;br /&gt;&lt;pre class="java" name="code"&gt;class ColorPoint {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Point point;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Color color;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean equals(Object o) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (!(o instanceof ColorPoint))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ColorPoint cp = (ColorPoint) o;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return cp.point.equals(point) &amp;amp;&amp;amp; cp.color.equals(color);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;3. Przykład jak zaimplementować equals().&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;@Override&lt;br /&gt;public boolean equals(Object object) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (this == object) return true; //załatwia punkt 1. kontraktu&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( !(object instanceof Entity) ) return false; //dodatkowo załatwia punkt 5 kontraktu&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Entity entity = (Entity) object;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //dla porównania konkretnych warto posłużyć się już gotowym builderem z biblioteki commons&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new EqualsBuilder().append(field1, entity.getField1())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .append(field2, entity.getField2())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; .isEquals();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;ważnym jest aby dla buildera wybrać tylko te pola, mają znaczenie przy porównaniu!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;4. Jeśli nadpisujesz equals(), to zawsze nadpisuj hashCode()&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ale o tym w następnym poście.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1273836480459496937?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1273836480459496937/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/02/metody-equlas-i-hashcode-w-javie.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1273836480459496937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1273836480459496937'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/02/metody-equlas-i-hashcode-w-javie.html' title='Metody equlas i hashCode w Javie.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-222568149308044423</id><published>2011-02-17T21:56:00.001+01:00</published><updated>2011-02-23T11:40:32.983+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CakePHP'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='internacjonalizacja'/><title type='text'>Internacjonalizcja w CakePHP</title><content type='html'>Niestety świat się nie kręci wokół javy i czasem trzeba wrócić do starego poczciwego php'a. Szukałem dość długo jak powinna wyglądać poprawna (w kontekście kodu jak i SEO) internacjonalizacja w CakePHP i generalnie w każdym tutorialu czegoś brakowało, coś nie do końca działało, dlatego postarałem się jakoś zebrać tą wiedzę i usystematyzować. Żeby zrozumieć co się dzieje w tutku, trzeba mieć podstawową wiedzę z Caka (wersja 1.2.9), oraz przeczytać rozdział o i18n i l10n z manuala. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Na początek radze zapoznać się ze sposobami internacjonalizacji aplikacji, które są dość dobrze opisane &lt;a href="http://h3h.net/technology/designing-urls-for-multilingual-websites"&gt;tu&lt;/a&gt;. Niestety nie stać mnie na różne domeny dla różnych języków (podejście (1)), dlatego wybrałem opcje (2), czyli zróżnicowanie linków pod kątem języków. Generalnie jako piaskownice i poligon doświadczalny postanowiłem zinternacjonalizować swoją bidną &lt;a href="http://www.ludwikowski.info/"&gt;stronę domową&lt;/a&gt;. Plus będzie tego taki, że wszystkie przykłady będą miały pokrycie na działającym przykładzie.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; Przyjmuję następującą strukturę linków:&lt;br /&gt;&lt;br /&gt;http://www.ludwikowski.info/ - ładuje domyślną stronę w języku polskim&lt;br /&gt;&lt;br /&gt;http://www.ludwikowski.info&lt;b&gt;/pol&lt;/b&gt; - również ładuje domyślną stronę w języku polskim&lt;br /&gt;http://www.ludwikowski.info&lt;b&gt;/eng&lt;/b&gt; - ładuje domyślną stronę w języku angielskim&lt;br /&gt;&lt;br /&gt;http://www.ludwikowski.info&lt;b&gt;/pol/&lt;/b&gt;pages/display/projects - ładuje wybraną stronę w język polskim &lt;br /&gt;http://www.ludwikowski.info&lt;b&gt;/eng/&lt;/b&gt;pages/display/projects - ładuje wybraną stronę w języku  angielskim&lt;br /&gt;&lt;br /&gt;i teraz pytanie z dziedziny SEO, co z linkami typu:&lt;br /&gt;http://www.ludwikowski.info&lt;b&gt;/&lt;/b&gt;pages/display/projects - niby można to obsługiwać domyślnie po polsku, ale nie wiem czy jest sens, dlatego postanowiłem po pierwsze nie generować takich linków, po drugie ich nie obsługiwać. Aczkolwiek, jeśli ktoś ma na ten temat inne zdanie to zapraszam do dyskusji, generalnie zasady SEO są dla mnie czasami dość rozmyte.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. &lt;/b&gt;Wszędzie tam gdzie treść ma być poddana internacjonalizacji używamy funkcji &lt;a href="http://book.cakephp.org/view/3/The-Manual#%21/view/162/Internationalizing-Your-Application"&gt;__()&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4&lt;/b&gt;. Potrzebujemy plików .po, w których będą przechowywane przetłumaczone frazy. Możemy je stworzyć ręcznie, albo użyć jednego z poleceń cakekowych z poziomu konsoli, a konkretnie: &lt;b&gt;cake i18n extract&lt;/b&gt;. Polecenie to generuje nam plik .pot będący szablonem na podstawie którego tworzymy już konkretne pliki .po. Czyli w moim przypadku, fragmenty plików .po wyglądają następująco.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;app/locale/eng/LC_MESSAGES/default.po&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;#: \views\elements\rightMenu.ctp:5&lt;br /&gt;msgid "Mój blog"&lt;br /&gt;msgstr "My blog"&lt;br /&gt;&lt;br /&gt;#: \views\elements\topMenu.ctp:3&lt;br /&gt;msgid "O mnie"&lt;br /&gt;msgstr "About me"&lt;/blockquote&gt;&lt;br /&gt;&lt;b&gt;app/locale/pol/LC_MESSAGES/default.po&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;#: \views\elements\rightMenu.ctp:5&lt;br /&gt;msgid "Mój blog"&lt;br /&gt;msgstr "Mój blog"&lt;br /&gt;&lt;br /&gt;#: \views\elements\topMenu.ctp:3&lt;br /&gt;msgid "O mnie"&lt;br /&gt;msgstr "O mnie"&lt;b&gt; &lt;/b&gt;&lt;/blockquote&gt;jeśli zasada tworzenie plików .po nie jest nam znana odsyłam do literatury w necie.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. &lt;/b&gt;Teraz trzeba dostosować aplikację, żeby w miarę wygodnie można było tworzyć linki oraz ich używać. Po pierwsze zasady routingu. W app/config/routes.php umieszczamy (koniecznie&lt;b&gt; przed &lt;/b&gt;standardowymi definicjami routtingu!):&lt;br /&gt;&lt;pre class="php" name="code"&gt;//mapowanie na stronę główną po angielsku&lt;br /&gt;Router::connect('/eng', array('language' =&amp;gt;'eng', 'controller' =&amp;gt; 'pages', 'action' =&amp;gt; 'display', 'home'));&lt;br /&gt; &lt;br /&gt;//mapowanie na stronę główną po polsku&lt;br /&gt;Router::connect('/pol', array('language' =&amp;gt;'pol', 'controller' =&amp;gt; 'pages', 'action' =&amp;gt; 'display', 'home'));&lt;br /&gt; &lt;br /&gt;//pobiera language z np. array('controller'=&amp;gt; 'contacts', 'action' =&amp;gt; 'sendEmail', 'language' =&amp;gt; 'pol') i umiesza go na początku url'a&lt;br /&gt;Router::connect('/:language/:controller/:action/*', array(), array('language' =&amp;gt; '[a-z]{3}'));&lt;br /&gt;&lt;/pre&gt;Jak dokładnie działa routowanie w cake'u odsyłam do manuala.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.&lt;/b&gt; Należy jakoś zautomatyzować tworzenie linków, żebyśmy nie musieli za każdym razem ręcznie odczytywać (czy to z sesji, czy to z cookie) jaki jest wybrany język i umieszczać go w linku. Dlatego tworzymy &lt;b&gt;app/app_handler &lt;/b&gt;i nadpisujemy metodę tworzącą url'e:&lt;br /&gt;&lt;pre class="php" name="code"&gt;class AppHelper extends Helper {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function url($url = null, $full = false) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!isset($url['language'])){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //sprawdzamy czy jest w coookie&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (isset($_COOKIE['lang'])){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $language=$_COOKIE['lang'];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //sprawdzamy czy jest w sesji&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (isset($_SESSION['Config']['language'])){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $language=$_SESSION['Config']['language'];&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //jeśli nie ma to domyślnie ustawiamy język polski&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $language='pol';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //dodajemy do urla język&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $url['language'] = $language;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return parent::url($url, $full);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Dzięki takiemu zabiegowi możemy tworzyć linki dokładnie tak samo jak to było do tej pory:&lt;br /&gt;&lt;pre class="php" name="code"&gt;echo $html-&amp;gt;link(__('Kontakt', true), array('controller'=&amp;gt;'pages', 'action'=&amp;gt;'display', 'contact'));&lt;br /&gt;&lt;/pre&gt;Język w postaci parametru 'language', będzie dodawany automatycznie.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7.&lt;/b&gt; Przechodzimy do dostosowania kontrolera, który będzie przełączał język (na podstawie url'a) jeśli różni się on od obecnie ustawionego. Tworzymy w tym celu odpowiedni komponent &lt;b&gt;app/controllers/components/language.php&lt;/b&gt;: &lt;br /&gt;&lt;pre class="php" name="code"&gt;class LanguageComponent extends Object {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $name = 'Language';&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $components = array('Cookie', 'Session');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //pobiera język z sesji, lub z cookie, lub domyślny = 'pol' jeśli nie był do tej pory ustawiony język &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function getLanguage(){&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if ($this-&amp;gt;Session-&amp;gt;read('Config.language')){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;Session-&amp;gt;read('Config.language');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else if ($this-&amp;gt;Cookie-&amp;gt;check('lang')){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;Cookie-&amp;gt;read('lang');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return 'pol';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ustawia wybrany język, dodatkowo inicjalizuje parametr w sesji jeśli wygasła &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function setLanguage($language&amp;nbsp; = 'pol'){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($this-&amp;gt;Cookie-&amp;gt;read('lang') &amp;amp;&amp;amp; !$this-&amp;gt;Session-&amp;gt;check('Config.language')) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;Session-&amp;gt;write('Config.language', $this-&amp;gt;Cookie-&amp;gt;read('lang'));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; else if ($language !=&amp;nbsp; $this-&amp;gt;Session-&amp;gt;read('Config.language')) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;Session-&amp;gt;write('Config.language', $language);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;Cookie-&amp;gt;write('lang', $language, false, '20 days');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //zmienia $url np.&amp;nbsp; /eng/controller/action/... na /$lang/controller/action/... &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function prepareUrl($url, $lang){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return "/".$lang.substr($url, 4, strlen($url));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;w &lt;b&gt;app/app_controller.php&lt;/b&gt;:&lt;br /&gt;&lt;pre class="php" name="code"&gt;class AppController extends Controller {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $components = array('Session', 'Cookie', 'Visit', 'Language');&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function beforeFilter() {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;set('visitors', $this-&amp;gt;Visit-&amp;gt;visitCookieUpdate());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;Language-&amp;gt;setLanguage($this-&amp;gt;_getLanguageFromParams());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function _getLanguageFromParams(){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (isset($this-&amp;gt;params['language'])){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;params['language'];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return 'pol';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;8.&lt;/b&gt; Ok, ogólny kontroler załatwiony, przydałby się jeszcze jakiś, który będzie wymuszał zmianę języka i przenosił na aktualnie oglądaną stronę &lt;b&gt;app/controllers/languages_controller.php&lt;/b&gt;:&lt;br /&gt;&lt;pre class="php" name="code"&gt;class LanguagesController extends AppController{&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $uses = array();&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $components = array('Language');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function change(){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;redirect($this-&amp;gt;Language-&amp;gt;prepareUrl($this-&amp;gt;referer(), $this-&amp;gt;Language-&amp;gt;getLanguage()));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;kontroler jest tak prosty, ponieważ wszystko robi za nas app_controller, język wymuszamy poprzez odpowiedni link. Tak de facto do zadań tego kontrolera należy jedynie przekierowanie na tą samą stronę. Możliwe, że można to jakoś sprawniej załatwić, ale nic mi nie przyszło do głowy, jak ktoś ma pomysł to pisać.&lt;br /&gt;&lt;pre class="php" name="code"&gt;echo $html-&amp;gt;link('Polski', array('language' =&amp;gt; 'pol', 'controller' =&amp;gt; 'languages', 'action' =&amp;gt; 'change');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;9. &lt;/b&gt;Praktycznie to by było na tyle, aczkolwiek żeby mieć już pełny pogląd na sprawy internacjonalizacji, pozostaje ostatni aspekt. Funckja __(), powinna być jedynie zastosowana do krótkich wiadomości. W przypadku potrzeby przetłumaczenia np. całej zawartości paragrafu, należy użyć techniki podmiany widoków, która została opisana w oficjalnym &lt;a href="http://book.cakephp.org/view/3/The-Manual#%21/view/162/Internationalizing-Your-Application"&gt;manualu&lt;/a&gt;. Niestety pages_controller rządzi się trochę swoimi prawami i oddzielnie dla niego trzeba dorobić jedną rzecz. Ogólnie zastanawiam się, czy nie szybciej byłoby napisać swój własny pages_controller. Moje rozwiązania, które 'łata' pages_controller nie uważam, za zbyt finezyjne, dlatego jak ktoś ma inny pomysł jak to zrobić to z chęcią przeczytam propozycje.&lt;br /&gt;&lt;br /&gt;Dorabiamy kolejny komponent &lt;b&gt;pages_i18n&lt;/b&gt;:&lt;br /&gt;&lt;pre class="php" name="code"&gt;class PagesI18nComponent extends Object {&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $name = 'PagesI18n';&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var $components = array('Language');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function viewName($viewName){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (file_exists(VIEWS.'pages'.DS.$this-&amp;gt;Language-&amp;gt;getLanguage().DS.$viewName.'.ctp')){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $this-&amp;gt;Language-&amp;gt;getLanguage().DS.$viewName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }else{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return $viewName;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;w pages_controller wywołujemy podmianę nazwy widoku:&lt;br /&gt;&lt;pre class="php" name="code"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if (isset($path[0])){&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $path[0] = $this-&amp;gt;PagesI18n-&amp;gt;viewName($path[0]);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;set(compact('page', 'subpage', 'title'));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; $this-&amp;gt;render(join('/', $path));&lt;br /&gt;&lt;/pre&gt;a widoki umieszczamy odpowiednio:&lt;b&gt; views/pages/pol/home.ctp&lt;/b&gt;, &lt;b&gt;views/pages/eng/home.ctp&lt;/b&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-222568149308044423?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/222568149308044423/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/02/internacjonalizcja-w-cakephp.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/222568149308044423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/222568149308044423'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/02/internacjonalizcja-w-cakephp.html' title='Internacjonalizcja w CakePHP'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-4614243311612688308</id><published>2011-01-26T13:56:00.002+01:00</published><updated>2011-01-26T13:57:45.145+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='backslash'/><category scheme='http://www.blogger.com/atom/ns#' term='replaceAll'/><category scheme='http://www.blogger.com/atom/ns#' term='eskejpowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='cudzysłów'/><title type='text'>Jak zamenić " na \" w java za pomocą String.replaceAll()</title><content type='html'>Z kategorii tak dziwne, że aż śmieszne. Otóż zamiana " w String'u w Javie na \" może przysporzyć pewnych trudności.&lt;br /&gt;&lt;br /&gt;Używając oferowanej przez String'a funckji: replaceAll(), zapisujemy:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;String s = "Adam Mickewicz \"Pan Tadeusz\" ";&lt;br /&gt;s = s.replaceAll("\"", "\\\"");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;efekt - żaden. Taka operacja nic z naszym String'iem nie zrobi. Należy pamiętać, że pierwszy argument funkcji replaceAll, to wyrażenie regularne. Dlatego znak '\', musi być dodatkowo wyeskejpowany dla regexp'a, czyli dopiero:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;s = s.replaceAll("\\\"", "\\\\\"");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;robi to o co nam chodziło. Zapis iście komiczny, ale co zrobisz...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-4614243311612688308?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/4614243311612688308/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/01/jak-zamenic-na-w-java-za-pomoca.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4614243311612688308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4614243311612688308'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/01/jak-zamenic-na-w-java-za-pomoca.html' title='Jak zamenić &quot; na \&quot; w java za pomocą String.replaceAll()'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-476182452195141810</id><published>2011-01-21T11:24:00.000+01:00</published><updated>2011-01-21T11:24:53.634+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pivot'/><category scheme='http://www.blogger.com/atom/ns#' term='crosstab'/><category scheme='http://www.blogger.com/atom/ns#' term='postgresql'/><title type='text'>Zamiana wierszy na kolumny w tabeli - crosstab (postgresql).</title><content type='html'>Jakiś czas temu musiałem, zrobić dość nieprzyjemną operacje na tabeli, tzn. zamienić wiersze tak aby tworzyły one kolumny. Czyli coś takiego:&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;x&lt;/td&gt;&lt;td&gt;&amp;nbsp;f01&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;x&lt;/td&gt;&lt;td&gt;&amp;nbsp;f02&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;x&lt;/td&gt;&lt;td&gt;&amp;nbsp;f03&lt;/td&gt;&lt;td&gt;&amp;nbsp;c&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;y&lt;/td&gt;&lt;td&gt;&amp;nbsp;f01&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;y&lt;/td&gt;&lt;td&gt;&amp;nbsp;f02&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;f01&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;f02&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;f03&lt;/td&gt;&lt;td&gt;&amp;nbsp;c&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;br /&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;f04&lt;/td&gt;&lt;td&gt;&amp;nbsp;d&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;f05&lt;/td&gt;&lt;td&gt;&amp;nbsp;e&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;miało zamienić się w coś takiego:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;id&lt;/td&gt;&lt;td&gt;&amp;nbsp;f01&lt;/td&gt;&lt;td&gt;&amp;nbsp;f02&lt;/td&gt;&lt;td&gt;&amp;nbsp;f03&lt;/td&gt;&lt;td&gt;&amp;nbsp;f04&lt;/td&gt;&lt;td&gt;&amp;nbsp;f05&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;x&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;td&gt;&amp;nbsp;c&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;y&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;nbsp;z&lt;/td&gt;&lt;td&gt;&amp;nbsp;a&lt;/td&gt;&lt;td&gt;&amp;nbsp;b&lt;/td&gt;&lt;td&gt;&amp;nbsp;c&lt;/td&gt;&lt;td&gt;&amp;nbsp;d&lt;/td&gt;&lt;td&gt;&amp;nbsp;e&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;Generalnie rzecz niby prosta, ale dość nienaturalna dla tabel w bazce . W realnym przykładzie miałem tak de facto 20 kolumn, co wiązało by się z wykonaniem 20 JOIN-ów, na tabelach, które posiadać będą olbrzymią ilość danych.&lt;br /&gt;&lt;br /&gt;W postgresie na szczęście znalazłem funkcję: &lt;a href="http://www.postgresql.org/docs/8.3/interactive/tablefunc.html"&gt;crosstab&lt;/a&gt;, która &lt;span id="search" style="visibility: visible;"&gt;umożliwia &lt;em&gt;szybkie (?)&lt;/em&gt; wykonanie zapytania krzyżowego (typu PIVOT) &lt;/span&gt;i pięknie realizuje to, o co mi chodzi.&lt;br /&gt;&lt;br /&gt;Zastanawiam się tylko jak jest ona zaimplementowana, i jaka jest jej wydajność, czy poradzi sobie z zakładaną dość dużą ilością danych? Ktoś coś wie na ten temat?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-476182452195141810?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/476182452195141810/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2011/01/zamiana-wierszy-na-kolumny-w-tabeli.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/476182452195141810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/476182452195141810'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2011/01/zamiana-wierszy-na-kolumny-w-tabeli.html' title='Zamiana wierszy na kolumny w tabeli - crosstab (postgresql).'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-3920368163349231484</id><published>2010-10-12T11:52:00.000+02:00</published><updated>2010-10-12T11:52:58.724+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='testowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='PowerMock'/><category scheme='http://www.blogger.com/atom/ns#' term='pola prywatne'/><category scheme='http://www.blogger.com/atom/ns#' term='metody prywatne'/><title type='text'>PowerMock i przetestujesz wszystko...</title><content type='html'>Poprzednie dwa posty pokazywały jak można testować metody i pola prywatne klasy. Zapis nie za piękny, czytelność słaba, ogólnie takie rozwiązanie takie se. Na szczęście istnieje bardzo przyjemne narzędzie umożliwiające wyżej wymienione zagadnienia i wiele, wiele innych.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/powermock/"&gt;PowerMock&lt;/a&gt; to framework rozszerzający biblioteki takie jak: &lt;a href="http://easymock.org/"&gt;EasyMock&lt;/a&gt; i &lt;a href="http://mockito.org/"&gt;Mockito&lt;/a&gt;. Odsyłam do oficjalnej strony w celu zapoznania się na co konkretnie pozwala PowerMock. Ja używam go wraz z Mockito i nie miałem do tej pory żadnych problemów. Poniżej prosty przykład użycia.&lt;br /&gt;&lt;br /&gt;Klasa do testów:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class SomeClass {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Integer privateField;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private boolean privateMethod(String s, int i){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Klasa testująca:&lt;br /&gt;&lt;pre class="java" name="code"&gt;import static org.powermock.reflect.Whitebox.getField;&lt;br /&gt;import static org.powermock.reflect.Whitebox.invokeMethod;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.Field;&lt;br /&gt;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import org.junit.runner.RunWith;&lt;br /&gt;import org.powermock.modules.junit4.PowerMockRunner;&lt;br /&gt;&lt;br /&gt;@RunWith(PowerMockRunner.class)&lt;br /&gt;public class SomeClassTest {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void shouldTestPrivateMethod() throws Exception {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //given&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SomeClass someClass = new SomeClass();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //when&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; boolean test = invokeMethod(someClass,"privateMethod", "Test", 1);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void shouldTestPrivateField() throws IllegalArgumentException, IllegalAccessException {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //given&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; SomeClass someClass = new SomeClass();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //when&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Field field = getField(SomeClass.class, "privateField");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Integer testInteger = (Integer) field.get(someClass);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;WhiteBox oferuje jak wspomniałem o wiele więcej i warto się z tą funkcjonalnością zaznajomić.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-3920368163349231484?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/3920368163349231484/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/10/powermock-i-przetestujesz-wszystko.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3920368163349231484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3920368163349231484'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/10/powermock-i-przetestujesz-wszystko.html' title='PowerMock i przetestujesz wszystko...'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-187422752003492137</id><published>2010-09-30T12:03:00.001+02:00</published><updated>2011-01-26T13:57:12.650+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='mechanizm refleksji'/><category scheme='http://www.blogger.com/atom/ns#' term='prywatne atrybuty'/><title type='text'>Mechanizm refleksji - dostęp do prywatnych atrybutów.</title><content type='html'>Oczywiście mechanizm refleksji, umożliwia dostęp nie tylko do metod prywatnych, ale również prywatnych atrybutów klasy. Krótki kodzik poniżej, gdyby ktoś potrzebował dostać się do takiego prywatnego pola.&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;private Integer getPrivateField(SomeClass someClass) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Field field = SomeClass.class.getDeclaredField("privateInteger");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; field.setAccessible(true);&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (Integer) field.get(someClass);&amp;nbsp;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class SomeClass{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Integer privateInteger;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-187422752003492137?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/187422752003492137/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/mechanizm-refleksji-dostep-do.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/187422752003492137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/187422752003492137'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/mechanizm-refleksji-dostep-do.html' title='Mechanizm refleksji - dostęp do prywatnych atrybutów.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1311175562424784608</id><published>2010-09-17T15:18:00.000+02:00</published><updated>2010-09-17T15:18:58.610+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='testowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='mechanizm refleksji'/><category scheme='http://www.blogger.com/atom/ns#' term='metody prywatne'/><title type='text'>Testowanie metod prywatnych w javie</title><content type='html'>Pomijając dysputy o tym, czy w ogóle można, czy też nie można testować metod prywatnych. Zamieszczam przykład jak to zrobić jeśli, ktoś będzie w sytuacji, że po prostu musi to zrobić. &lt;br /&gt;&lt;br /&gt;Mamy przykładowo klasę do stestowania:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class SomeClass{&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;private Boolean someMethod(String s, Integer i){&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&amp;nbsp;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Podczas testów używam mechanizmu &lt;a href="http://pl.wikipedia.org/wiki/Mechanizm_refleksji"&gt;refleksji&lt;/a&gt; i schematu given/when/then, o którym więcej można posłuchać &lt;a href="http://www.dailymotion.pl/video/xb1lm3_wrocyaw-jug-9-mockito-i-tdd_tech"&gt;tutaj&lt;/a&gt;. Przykładowa klasa testująca metodę prywatną z klasy SomeClass może być następująca:&lt;br /&gt;&lt;pre class="java" name="code"&gt;import static org.fest.assertions.Assertions.assertThat;&lt;br /&gt;import static org.fest.assertions.Fail.fail;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.InvocationTargetException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;&lt;br /&gt;import org.junit.Before;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;&lt;br /&gt;public class SomeClassTest {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SomeClass someClass;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Before&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void init() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;someClass = new SomeClass();&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void shouldDoSomethingGood() {&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;//given&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;//sekcja przygotowująca&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;//when&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;Boolean result=null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;try {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;result = invokePrivateMethodSomeMethod("test",10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;catch (Exception e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;e.printStackTrace();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fail("Nie oczekujemy wyjątku");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;//then&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;assertThat(result).isTrue();&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Boolean invokePrivateMethodSomeMethod(String s, Integer i) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;Class[] args =&amp;nbsp; {String.class, Integer.class}; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;//niestety musimy wpisać nazwę metody jako string - niezbyt dobre rozwiązanie w przypadku późniejszego refaktoringu&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;Method method = SystemUtils.class.getDeclaredMethod("someMethod", args);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;method.setAccessible(true);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;Object[] argObjects = {s,i};&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;return (Boolean) method.invoke(someClass, argObjects);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1311175562424784608?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1311175562424784608/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/testowanie-metod-prywatnych-w-javie.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1311175562424784608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1311175562424784608'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/testowanie-metod-prywatnych-w-javie.html' title='Testowanie metod prywatnych w javie'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-4792766358670983242</id><published>2010-09-10T12:46:00.002+02:00</published><updated>2010-09-10T12:49:20.990+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='h:selectManyCheckbox'/><category scheme='http://www.blogger.com/atom/ns#' term='no matching editors or conversion strategy found'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='form:checkboxes'/><title type='text'>Spring form:checkboxes a JSF h:selectManyCheckbox</title><content type='html'>Krótka notka dla wszystkich, którzy przesiedli się z JSF'a na Spring'a (wersja 2.5.6) i przyszło im użyć tagu &lt;b&gt;form:checkboxes&lt;/b&gt;. Idea obu tagów jest taka sama, czyli jak "przyjemnie" obsłużyć na formularzu wiele checkboxów.&lt;br /&gt;&lt;br /&gt;Załóżmy, że mamy encje Employee i Language, które są w relacji wiele-do-wielu.&lt;br /&gt;Aby wyświetlić na formularzu wszystkie checkboxy (języki) z zaznaczonymi tymi, które dany pracownik zna. W JSF używamy: &lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;h:selectmanycheckbox id="id" value="#{languages}"&gt;&lt;br /&gt;  &lt;f:selectitems value="#{allLanguages}"&gt;&lt;/f:selectitems&gt;&lt;br /&gt;&lt;/h:selectmanycheckbox&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To samo w Spring'u wygląda następująco&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;form:checkboxes itemlabel="language" items="${allLanguages}" itemvalue="id" path="languages"&gt;&lt;/form:checkboxes&gt;&lt;/pre&gt;&lt;br /&gt;Pominę kwestie skąd i jak wstrzykiwane są &lt;b&gt;allLanguages&lt;/b&gt; i &lt;b&gt;languages.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Wszystko teoretycznie powinno działać, ale niestety nie jest tak różowo. Pojawia się następujący błąd:&lt;br /&gt;&lt;blockquote&gt;Failed to convert property value of type [java.lang.String] to required type [java.util.Set] for property languages; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [emp.entity.Language] for property languages[0]: no matching editors or conversion strategy found&lt;/blockquote&gt;Przyczyną błędu jest brak odpowiedniego PropertyEditor'a dla Language. Przykładowy editor dla klasy Language:&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class LanguageEditor extends PropertyEditorSupport {&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private LanguageManager languageManager;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public LanguageEditor(LanguageManager languageManager) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;super();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;this.languageManager = languageManager;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void setAsText(String text) throws IllegalArgumentException {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;setValue(languageManager.getLanguageById(Long.parseLong(text)));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getAsText() {&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;Language language = (Language) getValue();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;return language == null ? null :&amp;nbsp; Long.toString(language.getId());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;W moim przypadku metoda setAsText używa managera, który pobiera encje Language o danym id z bazy. Trzeba jeszcze tylko dodać tego editora w metodzie initBuilder w kontrolerze który odpowiada za obsługę formularzu:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class EmployeeEditController extends SimpleFormController{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; super.initBinder(request, binder);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; binder.registerCustomEditor(Language.class, new LanguageEditor(languageManager));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;nbsp; .... &lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I coś takiego rozwiązuje zgłaszany błąd.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-4792766358670983242?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/4792766358670983242/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/spring-formcheckboxes-jsf.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4792766358670983242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4792766358670983242'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/09/spring-formcheckboxes-jsf.html' title='Spring form:checkboxes a JSF h:selectManyCheckbox'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-6428237713458312069</id><published>2010-07-09T17:05:00.055+02:00</published><updated>2010-09-30T11:56:11.777+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pool'/><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='Integer'/><category scheme='http://www.blogger.com/atom/ns#' term='pula'/><title type='text'>Java Integer pool</title><content type='html'>Mam nadzieje, że nie jestem jednym z ostatnich, którzy się o tym dowiadują, ale kwestia tworzenia Integer'ów w Javie jest dość ciekawa. Prześledźmy kilka przykładów:&lt;br /&gt;&lt;pre class="java" name="code"&gt;//1.&lt;br /&gt;Integer i1 = 12345&lt;br /&gt;Integer i2 = 12345&lt;br /&gt;//(i1==i2) -&amp;gt; false&lt;br /&gt;&lt;br /&gt;//2.&lt;br /&gt;Integer i1 = 127&lt;br /&gt;Integer i2 = 127&lt;br /&gt;//(i1==i2) -&amp;gt; true&lt;br /&gt;&lt;br /&gt;//3.&lt;br /&gt;Integer i1 = new Integer(127)&lt;br /&gt;Integer i2 = new Integer(127)&lt;br /&gt;//(i1==i2) -&amp;gt; false&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A teraz komentarz:&lt;br /&gt;1. Takie przypisanie zmiennej prymitywnej w starszej wersji Javy było w ogóle nie możliwe. Teraz jednak rusza do akcji "opakowywacz" i z typu prymitywnego int robi Integer, dzięki temu obie instrukcje przypisania są poprawne. Porównanie &lt;b&gt;i1==i2&lt;/b&gt; odnosi się oczywiście do referencji. Referencje wskazują na osobne obiekty, dlatego porównanie zwraca wartość &lt;b&gt;false&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;2. Tu jest ciekawiej. Dlaczego odwołując się do tego co napisałem powyżej, w tym przypadku jest inaczej? Otóż Java, obiekty typu Integer (również Byte, Short, Long) o wartościach od &lt;b&gt;-128 do 127&lt;/b&gt;, przechowuje w specjalnej puli, gdzie obiekty te po prostu nie powtarzają się. Dlatego też referencje wskazują na ten sam obiekt w puli. &lt;br /&gt;&lt;br /&gt;3. W ostatnim przykładzie wymuszamy (przez &lt;b&gt;new&lt;/b&gt;) otworzenie 2 osobnych obiektów. Stąd wartość porównania wynosi znowu &lt;b&gt;false&lt;/b&gt; (niezależnie już od wartości).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-6428237713458312069?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/6428237713458312069/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/07/java-integer-pool.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6428237713458312069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6428237713458312069'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/07/java-integer-pool.html' title='Java Integer pool'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-6231151830494858626</id><published>2010-05-03T20:44:00.001+02:00</published><updated>2010-05-06T09:47:19.387+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Integration Developer'/><category scheme='http://www.blogger.com/atom/ns#' term='WID'/><title type='text'>Fix Pack 7.0.0.2 dla Business Process Management = WID działa na full wypas.</title><content type='html'>Mój wcześniejszy problem, czyli synchronizacji WID'a z WPS'a rozwiązany (!) przez update oprogramowania&amp;nbsp; do wersji 7.0.0.2., dzięki sugestii mojego mentora. &lt;br /&gt;&lt;br /&gt;Instalacja update trwa, żeby nie skłamać, jakoś pół dnia, oczywiście zależy to po części od naszego łącza, bo jest sporo do ściągnięcia. Tak czy inaczej warto było poczekać, bo teraz wszystko działa jak należy. Dodam tylko, że jeśli uruchomiliśmy Instalation Managera z poziomu roota, to po updacie należy wykonać ponownie polecenie:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;chown -R andrzej /home/andrzej/IBM&lt;/code&gt;&lt;/blockquote&gt;Byłem w stanie uruchomić przykładową aplikacje typu hello world. Taką w stylu Business Process, czyli webservis, który po przesłaniu tytułu, imienia i nazwiska, zwróci nam coś w stylu: "Hello mr andrzej ludwikowski". I tu znowu pochwała w stronę WID'a, który umożliwia przetestowanie naszej aplikacji używając IDE w bardzo przyjemny i przejrzysty sposób. Takie rozwiązania każdy lubi.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-6231151830494858626?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/6231151830494858626/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/05/fix-pack-7002-dla-business-process.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6231151830494858626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6231151830494858626'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/05/fix-pack-7002-dla-business-process.html' title='Fix Pack 7.0.0.2 dla Business Process Management = WID działa na full wypas.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5469927754631176115</id><published>2010-04-30T16:45:00.000+02:00</published><updated>2010-04-30T16:45:56.480+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Integration Developer'/><category scheme='http://www.blogger.com/atom/ns#' term='WID'/><title type='text'>WebSphere Integration Developer - pierwsze wrażenia.</title><content type='html'>Przez ostatni tydzień miałem przyjemność pobawić się trochę z narzędziem IBM, tj. WebSphere Integration Developer 7. Musze przyznać, że pierwsze wrażenie jest bardzo pozytywne i oby takie pozostało. W końcu narzędzie komercyjne, w którym wiemy za co płacimy. A za co płacimy? Za wygodę między innymi:)&lt;br /&gt;&lt;br /&gt;Dla osób, które nie wiedzą czym jest tak do końca WID, to w telegraficznym skrócie, to taki znany wszystkim Eclipse, ale obudowany sporą warstwą funkcjonalności i udogodnień dodanych przez IBM'a. Praca (no może to małe nadużycie, bo aż tyle w nim nie popracowałem) jest bardzo przyjemna, można stworzyć aplikację bazującą na web servisach praktycznie wyłącznie klikając myszką i nie pisząc żadnego kodu. Wszystko obudowane jest paletami z odpowiedniki kontrolkami, która potem może sobie odpowiednio dostosowywać aby zbudować interesująca nas funkcjonalność.&lt;br /&gt;&lt;br /&gt;Na pochwałę zasługuje również zbiór dołączonych do WID'a tutoriali i kursów, które napisane są bardzo przystępny sposób i albo tłumaczą ogólnie teorię związaną z procesami biznesowymi, albo pokazują co jak wyklikać aby jakaś przykładowa aplikacja nam zadziałała.&lt;br /&gt;&lt;br /&gt;Niestety muszę być obiektywny i dodać łyżkę przysłowiowego dziegciu, nie mogę do tej pory poprawnie zsynchronizować WID'a z WPS'em. Serwer startuje poprawnie (mogę wejść do konsoli admina) jednak jego status jest cały czas na "starting..." przez co nie mogę np. wypróbować testowania serwisów z poziomu WID'a. Mam nadzieję, że problem ten jednak da się jakoś rozwiązać.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5469927754631176115?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5469927754631176115/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/websphere-integration-developer.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5469927754631176115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5469927754631176115'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/websphere-integration-developer.html' title='WebSphere Integration Developer - pierwsze wrażenia.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-678074919332459209</id><published>2010-04-22T10:18:00.001+02:00</published><updated>2010-04-26T10:27:40.068+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='instalacja'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Integration Developer'/><category scheme='http://www.blogger.com/atom/ns#' term='WID'/><category scheme='http://www.blogger.com/atom/ns#' term='red hat'/><title type='text'>Instalacja WebSphere Integration Developer 7 na Red Hat 5</title><content type='html'>Instalacja WID'a nie była aż tak problematyczna, jak się nastawiłem, mając doświadczenia z WPS'em :) Nie mniej, nie obyło się bez problemów, które postaram się przedstawić i omówić w poniższej notce. Instalację przeprowadziłem na oddzielnej kopii Red Hata, (oprogramowanie VmWare pozwala na zainstalowanie wielu systemów operacyjnych), bałem się głównie, że mogę zepsuć całą moją dotychczasową pracę z WPS'em i tak pewnie by się stało, gdybym pracował na jednym systemie. Ale do rzeczy...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Najważniejsze&lt;/b&gt; jest odpowiednie przygotowanie systemu przed i po instalacji.&lt;br /&gt;1. Instalator WID będzie komunikował, że brakuje mu biblioteki &lt;b&gt;libstdc++.so.5&lt;/b&gt;, aby rozwiązać ten problem &lt;b&gt;nie&lt;/b&gt; wystarczy utworzyć linku symbolicznego z libstdc++.so.6 do libstdc.so.5, tak jak to uczyniłem na początku, co potem spowodowało błędy przy uruchamianiu WID'a takie jak:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre wrap=""&gt;"Caused by: java.lang.UnsatisfiedLinkError: &lt;br /&gt;/home/andrzej/IBM/SDPShared/plugins/com.ibm.cic.licensing.lum.linux_7.0.101.v20090605_0444/os/linux/x86/libi4clntjni.so &lt;br /&gt;&lt;br /&gt;(/usr/lib/libstdc++.so.5: version `CXXABI_1.2' not found (required by &lt;br /&gt;/home/andrzej/IBM/SDPShared/plugins/com.ibm.cic.licensing.lum.linux_7.0.101.v20090605_0444/os/linux/x86/libi4clntjni.so))"&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;1.1. Musimy zainstalować libstdc++, aby to zrobić najwygodniej należy najpierw zarejestrować swój system w RHN, używając komendy &lt;b&gt;"&lt;code&gt;rhn_register" &lt;/code&gt;&lt;/b&gt;&lt;code&gt;z poziomu root'a. Rejestracja będzie pytała o login i hasło do konta użytego m.in. do ściągnięcia systemu.&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;1.2. Następnie wybieramy &lt;b&gt;Appliaction&amp;gt;Add/Remove Software&lt;/b&gt;, wyszukujemy i instalujemy &lt;b&gt;compat-libstdc++-33-3.2.3-61&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;1.3. Warto upewnić się czy biblioteka fizycznie znajduje się w /usr/lib&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;b&gt; &lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;2. Przechodzimy do instalacji WID'a. Z poziomu root'a wykonujemy &lt;b&gt;umask 0022&lt;/b&gt;, a następnie uruchamiamy &lt;b&gt;./launchpad.sh&lt;/b&gt;. Podczas pracy z kreatorem instalacji zmieniłem jedynie katalog instalacji zamieniając &lt;b&gt;/opt/&lt;/b&gt; na &lt;b&gt;/home/andrzej/&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;2.1. Instalujemy kolejno WID'a, WAS'a, i środowisko testowe (czas ok. 1-1.5 godzin)&lt;b&gt; &lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;3. Po instalacji musimy zwiększyć liczbę uchwytów do plików. Korzystamy z oficjalnej instrukcji:&lt;a href="http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/index.jsp?topic=/com.ibm.wbit.help.inst.doc/topics/t_increase_handles.html"&gt;link&lt;/a&gt;. W punkcie 7 plik limits.conf znajdował się w moim przypadku w &lt;b&gt;/etc/security&lt;/b&gt;. Po wykonaniu instrukcji należy zrestartować system.&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;4. Ostatnim krokiem jest dodanie uprawnień dla zwykłego użytkownika do katalogu instalacji WID'a (w moim przypadku) &lt;b&gt;/home/andrzej/IBM&lt;/b&gt;, używając komendy&lt;b&gt;:&lt;/b&gt;&lt;/code&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;chown -R andrzej /home/andrzej/IBM&lt;/code&gt;&lt;/blockquote&gt;&lt;code&gt;5. Po uruchomieniu WID'a w moim przypadku nie została wczytana żadna domyślna perspektywa, nie wiem dlaczego, ale wystarczy ręcznie przełączyć na jakąś z perspektyw i już możemy pracować.&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-678074919332459209?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/678074919332459209/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacja-websphere-integration.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/678074919332459209'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/678074919332459209'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacja-websphere-integration.html' title='Instalacja WebSphere Integration Developer 7 na Red Hat 5'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-3915429375618888020</id><published>2010-04-14T10:27:00.001+02:00</published><updated>2010-04-14T10:32:00.591+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wps'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='WAS'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Websphere Application Server'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><title type='text'>Tutorial jak uruchomić projekt Seam (bazujący na JPA) w Websphere Application Server v 7</title><content type='html'>Moim głównym zadaniem było, uruchomienie projektu Seam, korzystającego z zewnętrznej bazy danych na WPS'ie, biorąc pod uwagę fakt, że WPS jest nakładką na WAS'a, oraz to że na początku nie mogłem uruchomić profilu WPS'owskiego, napisałem (łącznie z tym) 3 tutrialne potrzebne do uruchominia Seam'a na WAS'ie. Jednakże tutoriale te są w równym stopniu poprawne w przypadku uruchomienia Seam na WPS'ie, jedyna różnica jest taka, że konsola administratora WPS posiada trochę więcej opcji niż ta WAS'owska.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Co potrzebujemy?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;1. Seam w wersji &lt;b&gt;2.1.2.GA: &lt;a href="http://seamframework.org/Download"&gt;link&lt;/a&gt;&amp;nbsp; &lt;/b&gt;- jest to nowsza wersja Seam'a, w poprzednich tutorialach używałem wersji 2.0, jednakże różnice związane z tym tutorialem są tylko takie, że seam-gen zada o kilka pytań więcej, na które odpowiadamy domyślnymi odpowiedziami.&lt;br /&gt;2. Projekt wygenerowany przez seam-gen, na podstawie bazy danych, patrz: &lt;a href="http://aludwikowski.blogspot.com/2010/03/seam-gen-w-akcji.html"&gt;link&lt;/a&gt;&lt;br /&gt;3. Zapoznanie się oraz wykonanie wcześniejszego tutoriala dotyczącego brakujących bibliotek: &lt;a href="http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-shared-libraries-do.html"&gt;link&lt;/a&gt;&lt;br /&gt;4. Zapoznanie się oraz wykonanie wcześniejszego tutoriala dotyczącego utworzenia data source: &lt;a href="http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-baze-danych-mysql-do.html"&gt;link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;a href="http://seamframework.org/Download"&gt;&lt;/a&gt; &lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Uruchomienie projektu Seam na WAS'ie:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;1. Punktem wyjściowym jest projekt wygenerowany przez Seam-gen, najlepiej wcześniej sprawdzony na JBoss'ie. Projekt bazujący na &lt;b&gt;JPA&lt;/b&gt;, czyli typu &lt;b&gt;war&lt;/b&gt;.&lt;br /&gt;2. Edytujemy plik resources/META-INF/persistence-dev.xml:&lt;br /&gt;&amp;nbsp;- zmieniamy wartość między tagami &lt;b&gt;&amp;lt; jta-data-source&amp;gt;&lt;/b&gt; i wpisujemy tam nazwę JNDI data source, którego wcześniej utworzyliśmy w moim przypadku &lt;b&gt;jdbc/MySql_cms&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;&amp;lt; jta-data-source&amp;gt;jdbc/MySql_cms&amp;lt; /jta-data-source&amp;gt; &lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;&amp;nbsp;- dodajemy / edytujemy właściwości hibernate, tak aby otwrzymać:&lt;br /&gt;&lt;blockquote&gt;&amp;lt; properties&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; property name="hibernate.hbm2ddl.auto" value="update"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; property name="hibernate.show_sql" value="true"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; property name="hibernate.format_sql" value="true"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; !-- Only relevant if Seam is loading the persistence unit (Java SE bootstrap) --&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;&amp;lt; property name="hibernate.transaction.manager_lookup_class"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value="org.hibernate.transaction.WebSphereExtendedJTATransactionLookup"/&amp;gt;&lt;/b&gt;&lt;br /&gt;&amp;lt; /properties&amp;gt; &lt;/blockquote&gt;&lt;span style="color: red;"&gt;- &lt;/span&gt;&lt;b style="color: red;"&gt;UWAGA!!&lt;/b&gt;&lt;span style="color: red;"&gt; &lt;/span&gt;W kodzie powyżej są spacje w tagach XML, należy je usunąć, jeśli chcemy wkleić do pliku.&lt;br /&gt;3. Używając polecania &lt;b&gt;"ant archive" &lt;/b&gt;w katalogu &lt;b&gt;głównym&lt;/b&gt; projektu, kompilujemy projekt i tworzymy m.in. plik .war.&lt;br /&gt;4. Uruchamiamy WAS'a /WPS'a i przechodzimy do konsoli administratora, wybieramy Application&amp;gt;App Types&amp;gt; Websphere E A, oraz wybieramy Install.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8H_F51zG2I/AAAAAAAAACI/xaLoXOD86I0/s1600/Screenshot-2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="69" src="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8H_F51zG2I/AAAAAAAAACI/xaLoXOD86I0/s200/Screenshot-2.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5. W następnym oknie wybieramy plik .war który utworzyliśmy (znajduje się on w katalogu &lt;b&gt;dist&lt;/b&gt; naszego projektu). Klikamy next, w następnym oknie wybieramy &lt;b&gt;Fast path&lt;/b&gt; i dajemy również next.&lt;br /&gt;6. Kreator instalacji zostawiamy bez zmian, tylko w przedostatnim oknie dodajemy nazwę naszego projektu, klikany next, a następnie finish, na końcu zapisujemy zmiany na serwerze:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8H_OEszDhI/AAAAAAAAACQ/ioUxbN74Xos/s1600/Screenshot-3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="80" src="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8H_OEszDhI/AAAAAAAAACQ/ioUxbN74Xos/s200/Screenshot-3.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;7. Wybieramy nasz projekt z listy zainstalowanych projektów, wybieramy &lt;b&gt;"Manage modules"&lt;/b&gt;, następnie klikamy na nazwę naszego projektu z zmieniamy ustawienia class loadera na: "Classes loaded with local class loader first (parent last)"&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8H_WxnaijI/AAAAAAAAACY/aRNIAjLr1Qw/s1600/Screenshot-5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="126" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8H_WxnaijI/AAAAAAAAACY/aRNIAjLr1Qw/s200/Screenshot-5.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8H_geIWU9I/AAAAAAAAACg/-AOwII2lIY4/s1600/Screenshot-4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="89" src="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8H_geIWU9I/AAAAAAAAACg/-AOwII2lIY4/s200/Screenshot-4.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;8. Podobnie jak w punkcie 7. postępujemy po wyborze &lt;b&gt;"Class loading and update detection"&lt;/b&gt;. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8H_lbTtVxI/AAAAAAAAACo/w1QQUHkUHeU/s1600/Screenshot-6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="132" src="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8H_lbTtVxI/AAAAAAAAACo/w1QQUHkUHeU/s200/Screenshot-6.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;9. Dodajemy przygotowane wcześniej Shared libraries do naszego projektu. Wybieramy &lt;b&gt;"Shared library references"&lt;/b&gt;, następnie zaznaczamy nazwę naszej aplikacji i klikamy na &lt;b&gt;"Reference shared libraries"&lt;/b&gt;, dodajemy "Jboss_libs" do okna po prawej i dajemy OK.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8H_tppro2I/AAAAAAAAACw/ZEKZhuesD10/s1600/Screenshot-7.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="121" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8H_tppro2I/AAAAAAAAACw/ZEKZhuesD10/s200/Screenshot-7.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;10. Zapisujemy wszystkie zmiany na serwerze. Zaznaczamy nasz projekt na liście i klikamy na start.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8IARFdcf_I/AAAAAAAAAC4/fTaqnmS-LNw/s1600/Screenshot-8.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="93" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8IARFdcf_I/AAAAAAAAAC4/fTaqnmS-LNw/s200/Screenshot-8.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;11. Projekt powinien się poprawnie uruchomić i jest dostępny pod adresem:&lt;br /&gt;&lt;blockquote&gt;http://localhost:9080/websphere_war_test/index.html&lt;/blockquote&gt;Wymienione wcześniej 2 tutoriale, czyli &lt;a href="http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-shared-libraries-do.html"&gt;http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-shared-libraries-do.html&lt;/a&gt;, &lt;a href="http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-baze-danych-mysql-do.html"&gt;http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-baze-danych-mysql-do.html&lt;/a&gt;, razem z tym, tworzą tak na prawdę jeden tutorial, pokazujący jak od początku do końca uruchomić projekt wygenerowany przez seam-gen (używający JPA) na Websphere Application Server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-3915429375618888020?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/3915429375618888020/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-uruchomic-projekt-seam.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3915429375618888020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/3915429375618888020'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-uruchomic-projekt-seam.html' title='Tutorial jak uruchomić projekt Seam (bazujący na JPA) w Websphere Application Server v 7'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-EhdUDK1j_U/S8H_F51zG2I/AAAAAAAAACI/xaLoXOD86I0/s72-c/Screenshot-2.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-2220618673921365397</id><published>2010-04-13T09:02:00.000+02:00</published><updated>2010-04-13T09:02:15.174+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse.ini'/><category scheme='http://www.blogger.com/atom/ns#' term='problem'/><category scheme='http://www.blogger.com/atom/ns#' term='komunikat'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='jvm terminated exit code=-1'/><title type='text'>Eclipse problem z "jvm terminated exit code=-1"</title><content type='html'>W końcu znalazłem rozwiązanie dręczącego mnie od jakiegoś czasu problemu. Pracuje nad pewnym projektem w Eclipse od pół roku i wszystko działało sprawnie aż pewnego dnia przy uruchomieniu Eclipsa dostaję komunikat:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;jvm terminated exit code=-1&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8MMR6TT-9I/AAAAAAAAADA/GqAR22zAwug/s1600/Nowy-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8MMR6TT-9I/AAAAAAAAADA/GqAR22zAwug/s320/Nowy-1.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Rozwiązania podawane w internecie raz działały raz nie, przeinstalowałem nawet Jave, wszystko na nic, bo i tak po jakimś czasie dostawałem, ku mojej irytacji, ten komunikat. Okazało się, że wystarczyło zedytować plik &lt;b&gt;eclipse.ini&lt;/b&gt;, i zmniejszyć ilość pamięci dla launchera z 256 na 128:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;plugins/org.eclipse.equinox.launcher_1.0.200.v20090520.jar&lt;br /&gt;--launcher.library&lt;br /&gt;plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519&lt;br /&gt;-product&lt;br /&gt;org.eclipse.epp.package.jee.product&lt;br /&gt;--launcher.XXMaxPermSize&lt;br /&gt;128M&lt;br /&gt;-showsplash&lt;br /&gt;org.eclipse.platform&lt;br /&gt;--launcher.XXMaxPermSize&lt;br /&gt;128m&lt;br /&gt;-vmargs&lt;br /&gt;-Dosgi.requiredJavaVersion=1.5&lt;br /&gt;-Xms40m&lt;br /&gt;-Xmx512m&lt;/blockquote&gt;Nie wiem w sumie z czego to wynika, ponieważ tak jak mówiłem, przez pół roku wszystko działało cacy. Tak czy inaczej mam nadzieje, że to rozwiązanie pomoże na dobre.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-2220618673921365397?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/2220618673921365397/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/eclipse-problem-z-jvm-terminated-exit.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2220618673921365397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2220618673921365397'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/eclipse-problem-z-jvm-terminated-exit.html' title='Eclipse problem z &quot;jvm terminated exit code=-1&quot;'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-EhdUDK1j_U/S8MMR6TT-9I/AAAAAAAAADA/GqAR22zAwug/s72-c/Nowy-1.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-6704345609471688595</id><published>2010-04-12T12:37:00.006+02:00</published><updated>2010-05-27T13:31:03.955+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataSource'/><category scheme='http://www.blogger.com/atom/ns#' term='WAS'/><category scheme='http://www.blogger.com/atom/ns#' term='Mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Websphere Application Server'/><title type='text'>Tutorial jak dodać bazę danych Mysql do DataSource w Websphere Application Server v 7 ?</title><content type='html'>&amp;nbsp; Krótki tutorial jak dodać bazę danych MySql, do WAS'a. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Co potrzebujemy?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;1. Sterownik JDBC do MySql'a: &lt;a href="http://www.mysql.com/downloads/connector/j/"&gt;link&lt;/a&gt;.&lt;br /&gt;2. Zainstalowany serwer MySql z utworzoną bazą danych, ten punkt pozostawiam czytelnikowi.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Dodajemy sterownik do "JDBC providers&lt;/b&gt;".&lt;/span&gt;&lt;br /&gt;1. Uruchamiamy WAS'a, następnie przechodzimy do &lt;b&gt;Resources&amp;gt;JDBC&amp;gt;JDBC providers&lt;/b&gt; i wybieramy &lt;b&gt;New&lt;/b&gt;.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8HLbf-AbLI/AAAAAAAAABQ/5az6iYJbUVk/s1600/Screenshot-2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="111" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8HLbf-AbLI/AAAAAAAAABQ/5az6iYJbUVk/s200/Screenshot-2.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;2. Uzupełniamy odpowiednio formularz. W &lt;b&gt;"Implementation class name"&lt;/b&gt; powinniśmy wpisać:&lt;/div&gt;&lt;blockquote&gt;&amp;nbsp;com.mysql.jdbc.jdbc2.optional.&lt;i&gt;MysqlConnectionPoolDataSource&lt;/i&gt;&lt;/blockquote&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HLzdb_bdI/AAAAAAAAABY/YCV98K5byc4/s1600/Screenshot-3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" src="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HLzdb_bdI/AAAAAAAAABY/YCV98K5byc4/s200/Screenshot-3.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;3. W następnym oknie podajemy ścieżkę do sterownika JDBC, czyli w moim przypadku.&lt;/div&gt;&lt;blockquote&gt;&amp;nbsp;/home/andrzej/Desktop/tools/mysql-connector-java-5.1.12/mysql-connector-java-5.1.12-bin.jar&lt;/blockquote&gt;&lt;div style="text-align: left;"&gt;4. Kończymy pracę z kreatorem klikając &lt;b&gt;Finish&lt;/b&gt;, oraz zapisujemy zamiany w konfiguracji serwera.&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Dodajemy bazę danych do "Data Source".&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1. Mając dodany sterownik JDBC, możemy przystąpić do dodania bazy danych. Przechodzimy do  &lt;b&gt;Resources&amp;gt;Data source &lt;/b&gt;i klikamy New&lt;b&gt;.&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HMVNeAdFI/AAAAAAAAABg/m096sDLHrQ4/s1600/Screenshot-4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="113" src="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HMVNeAdFI/AAAAAAAAABg/m096sDLHrQ4/s200/Screenshot-4.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;2. Wypełniamy odpowiednio pola, w moim przypadku nazwa bazy danych to "cms", stąd takie końcówki, oczywiście możemy wypełnić te pola wedle uznania.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HMeEZo7JI/AAAAAAAAABo/EWkftsM4QVQ/s1600/Screenshot-6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="90" src="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8HMeEZo7JI/AAAAAAAAABo/EWkftsM4QVQ/s200/Screenshot-6.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;3. Wybieramy naszego dostawcę JDBC&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8HMndfwZNI/AAAAAAAAABw/cm_eh0oIaZ0/s1600/Screenshot-7.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="91" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8HMndfwZNI/AAAAAAAAABw/cm_eh0oIaZ0/s200/Screenshot-7.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;4. W następnym oknie wartość dla &lt;b&gt;"Data store helper class name"&lt;/b&gt; powinna być ustawiona na:&lt;/div&gt;&lt;blockquote&gt;com.ibm.websphere.rsadapter.ConnectJDBCDataStoreHelper&lt;/blockquote&gt;5. Następne okno pozastawiamy bez zmian, kończymy pracę z kreatorem i zapisujemy zmiany na serwerze.&lt;br /&gt;6. Klikamy na &lt;b&gt;"MySql_cms"&lt;/b&gt; na liście &lt;b&gt;"Data source"&lt;/b&gt;, następnie z podmenu &lt;b&gt;"Additional properties"&lt;/b&gt; po prawej stronie wybieramy &lt;b&gt;"Custom properties"&lt;/b&gt;. Musimy znaleźć i zedytować kilka zmiennych, tj.&lt;br /&gt;&lt;blockquote&gt;databaseName = cms?autoReconnect=true&lt;br /&gt;user = admin &lt;br /&gt;password = admin&lt;br /&gt;port = 3306&lt;br /&gt;serverName = localhost&lt;/blockquote&gt;&lt;div style="text-align: left;"&gt;Wszystkie wartości powinny być typu: java.lang.String. oraz dostosowane do odpowiedniej konfiguracji bazy danych. Jeśli port jest defaultowy to chyba można pominąć tą wartość.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8HM4QxSV1I/AAAAAAAAAB4/11TTP6ej_ys/s1600/Screenshot-8.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="128" src="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8HM4QxSV1I/AAAAAAAAAB4/11TTP6ej_ys/s200/Screenshot-8.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;7. Zapisujemy zmiany na serwerze i testujemy połączenie:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8HM_YHi_FI/AAAAAAAAACA/29LSFyWCudM/s1600/Screenshot-9.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="137" src="http://3.bp.blogspot.com/_-EhdUDK1j_U/S8HM_YHi_FI/AAAAAAAAACA/29LSFyWCudM/s200/Screenshot-9.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Jest to kolejny tutorial będący przygotowaniem do uruchomienia aplikacji Seam na WAS'ie&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-6704345609471688595?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/6704345609471688595/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-baze-danych-mysql-do.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6704345609471688595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/6704345609471688595'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-baze-danych-mysql-do.html' title='Tutorial jak dodać bazę danych Mysql do DataSource w Websphere Application Server v 7 ?'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-EhdUDK1j_U/S8HLbf-AbLI/AAAAAAAAABQ/5az6iYJbUVk/s72-c/Screenshot-2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-9181640291620963460</id><published>2010-04-12T09:39:00.011+02:00</published><updated>2010-04-12T13:57:48.528+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Shared Libraries'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='WAS'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='Websphere Application Server'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><title type='text'>Tutorial jak dodać "Shared Libraries" do Websphere Application Server v 7</title><content type='html'>Szybki tutorial jak dodać "Shared Libraries" do WAS'a, dodawane biblioteki będą potrzebne do uruchamiania aplikacji Seam'owskich na WAS'ie, używając JBoss'a nie musimy martwić się o te biblioteki, natomiast w WAS'ie musimy je ręcznie dodać do serwera, lub do samej aplikacji. Tutorial jest oczywiście uniwersalny i możemy dodać inne biblioteki, jednak moim głównym celem jest przystosowanie WAS'a do aplikacji Seam'owskich.&lt;br /&gt;&lt;br /&gt;Lista potrzebnych bibliotek, których wymaga projekt Seam używający &lt;b&gt;JPA&lt;/b&gt; (!):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;hibernate.jar&lt;/li&gt;&lt;li&gt; hibernate-annotations.jar&lt;/li&gt;&lt;li&gt; hibernate-commons-annotations.jar&lt;/li&gt;&lt;li&gt; hibernate-entitymanager.jar&lt;/li&gt;&lt;li&gt; hibernate-validator.jar&lt;/li&gt;&lt;li&gt; commons-collections.jar&lt;/li&gt;&lt;li&gt; jboss-common-core.jar &lt;/li&gt;&lt;li&gt; antlr.jar&lt;/li&gt;&lt;li&gt; cglib.jar&lt;/li&gt;&lt;li&gt; asm.jar&lt;/li&gt;&lt;li&gt; dom4j.jar&lt;/li&gt;&lt;li&gt; javassist.jar&lt;/li&gt;&lt;li&gt; concurrent.jar&lt;/li&gt;&lt;/ul&gt;1. Uruchamiamy WAS'a i przychodzimy do konsoli administratora.&lt;br /&gt;2. Wybieramy &lt;b&gt;Environment&amp;gt;Shared Libraries&lt;/b&gt;, oraz klikamy &lt;b&gt;New&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8F8I6B2aMI/AAAAAAAAAA4/PNq6GVkr_ro/s1600/Screenshot-2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="75" src="http://1.bp.blogspot.com/_-EhdUDK1j_U/S8F8I6B2aMI/AAAAAAAAAA4/PNq6GVkr_ro/s200/Screenshot-2.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;3. Wybieramy nazwę, oraz dodajemy ścieżki do poszczególnych .jar'ów, oddzielając je enterem. &lt;b&gt;UWAGA&lt;/b&gt; &lt;b&gt;nie&lt;/b&gt; możemy oddzielać bibliotek znakami "&lt;b&gt;;&lt;/b&gt;" lub "&lt;b&gt;:&lt;/b&gt;".&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8F9CpaCsCI/AAAAAAAAABA/Yr7TbagxDEQ/s1600/Screenshot-5.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="111" src="http://4.bp.blogspot.com/_-EhdUDK1j_U/S8F9CpaCsCI/AAAAAAAAABA/Yr7TbagxDEQ/s200/Screenshot-5.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;4. Zapisujemy zmiany w konfiguracji serwera.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8F9P5rfbjI/AAAAAAAAABI/_UD7_mrAsaY/s1600/Screenshot-6.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="105" src="http://2.bp.blogspot.com/_-EhdUDK1j_U/S8F9P5rfbjI/AAAAAAAAABI/_UD7_mrAsaY/s200/Screenshot-6.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;5. Gotowe ! Oczywiście aby korzystać z tych bibliotek musimy je jeszcze dodać do wdrażanej aplikacji, ale o tym za jakiś czas.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-9181640291620963460?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/9181640291620963460/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-shared-libraries-do.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/9181640291620963460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/9181640291620963460'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/tutorial-jak-dodac-shared-libraries-do.html' title='Tutorial jak dodać &quot;Shared Libraries&quot; do Websphere Application Server v 7'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-EhdUDK1j_U/S8F8I6B2aMI/AAAAAAAAAA4/PNq6GVkr_ro/s72-c/Screenshot-2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1485504908057214042</id><published>2010-04-11T15:56:00.000+02:00</published><updated>2010-04-11T15:56:25.232+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wps'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Process Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Too many open files'/><title type='text'>Przygotowanie profilu na Websphere Process Server</title><content type='html'>Wspomniane we wcześniejszym &lt;a href="http://aludwikowski.blogspot.com/2010/04/przygotowanie-do-deployowania-aplikacji.html"&gt;poście&lt;/a&gt; problemy, wynikały z zupełnie innych kwestii, niż w początąkowym założeniu, czyli problemamy z SQLem. Problem stanowił inny wyjątek, czyli:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre wrap=""&gt;[4/8/10 10:28:56:221 PDT] 00000000 ConnectionEve A J2CA0056I: The &lt;br /&gt;Connection Manager received a fatal connection error from the Resource &lt;br /&gt;Adapter for resource jdbc/WPSDB. The exception is: java.sql.SQLException: &lt;br /&gt;Meta-data for Container &lt;br /&gt;org.apache.derby.impl.store.raw.data.RAFContainer4@7f057f05 could not be &lt;br /&gt;accessed:java.sql.SQLException: Meta-data for Container &lt;br /&gt;org.apache.derby.impl.store.raw.data.RAFContainer4@7f057f05 could not be &lt;br /&gt;accessed:java.sql.SQLException: Java exception: &lt;br /&gt;'/home/andrzej/ibm/WebSphere/ProcServer/profiles/ProcSrv02/databases/WPRCSDB/seg0/c290.dat &lt;br /&gt;(Too many open files): &lt;br /&gt;java.io.FileNotFoundException'.:java.io.FileNotFoundException: &lt;br /&gt;/home/andrzej/ibm/WebSphere/ProcServer/profiles/ProcSrv02/databases/WPRCSDB/seg0/c290.dat &lt;br /&gt;(Too many open files)&lt;/pre&gt;&lt;/blockquote&gt;Rozwiązaniem tego problemu jest zwiększenie limitu otwieranych plików używając konta roota (polecenie ulimit -n 90000 w pliku /root/.bashrc), oraz uruchomienie serwera również z poziomu root'a. Rozwiązanie można znaleźć na blogu kolegi Rafała: &lt;a href="http://rwisniecki.blogspot.com/2010/04/problem-z-uruchomieniem-konsoli.html"&gt;link&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1485504908057214042?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1485504908057214042/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/przygotowanie-profilu-na-websphere.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1485504908057214042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1485504908057214042'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/przygotowanie-profilu-na-websphere.html' title='Przygotowanie profilu na Websphere Process Server'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-1456375936746995910</id><published>2010-04-09T12:31:00.000+02:00</published><updated>2010-04-09T13:03:37.306+02:00</updated><title type='text'>Przygotowanie do deployowania aplikacji seam na WPS/WAS</title><content type='html'>Przygotowania do uruchomienia przykładowych aplikacji Seam na Websphere Process Server, niestety nie odbyły się bez problemów. Po utworzeniu profilu (typu stand-alone) na WPS'ie serwer uruchamia się z błędami, takimi jak:&lt;br /&gt;&lt;blockquote&gt;[4/8/10 10:28:56:378 PDT] 00000000 WSRdbManagedC W   DSRA0180W: Exception detected during ManagedConnection.destroy().  The exception is: &lt;br /&gt;&lt;br /&gt;com.ibm.ws.exception.WsException: DSRA0080E: An exception was received by the Data Store Adapter. See original exception message: No current connection.. with SQL&lt;br /&gt;&lt;br /&gt;State : 08003 SQL Code : 40000&lt;br /&gt;    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)&lt;br /&gt;    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)&lt;br /&gt;    at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Unknown Source)&lt;/blockquote&gt;Przypuszczam, że skutkiem tych błędów są kolejne błędy przy uruchomieniu konsoli administratora. Niestety po przeszukaniu ton materiałów wypstrykałem się pomysłów jak naprawić ten błąd. Dodam, że pojawią się one już na świeżutkiem WPS-ie, gdzie nic nie było zmieniane i konfigurowane.&lt;br /&gt;&lt;br /&gt;Skoro WPS ma pod sobą WAS'a, postanowiłem używać profilu WAS'owskiego, na którym serwer uruchamia się bez najmniejszych problemów. Pierwszy próby deployowania aplikacji seam'owskich zakończyły się ni to sukcesem ni to porażką, ponieważ bazując na oficjalnej instrukji: &lt;a href="http://docs.jboss.org/seam/snapshot/en-US/html/websphere.html"&gt;link&lt;/a&gt;, udało mi się uruchomić aplikacje jpa, niestety przykład z jee5/booking nadal nie chce działać. Generalnie sama instrukcja mogła by być napisana w trochę bardziej obszerniejszy sposób, ponieważ wiele aspektów działania seam na was nadal pozostaje dla mnie czarną plamą, która zamierzam w miarę zmniejszać w następnym tygodniu.....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-1456375936746995910?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/1456375936746995910/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/przygotowanie-do-deployowania-aplikacji.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1456375936746995910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/1456375936746995910'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/przygotowanie-do-deployowania-aplikacji.html' title='Przygotowanie do deployowania aplikacji seam na WPS/WAS'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-2082436844348759860</id><published>2010-04-07T12:00:00.000+02:00</published><updated>2010-04-07T12:23:17.474+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wps'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='instalacja'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Process Server'/><category scheme='http://www.blogger.com/atom/ns#' term='silent mode'/><title type='text'>Instalacje IBM WPS na Red Hat - "silent mode"</title><content type='html'>Drugą opcją instalacji WPS'a jest instalacja w tzn. "silent mode". Czyli cała instalacja odbywa się po cichu, bez żadnych kreatorów, itd. Wystarczy, że zmodyfikujemy odpowiednio dwa pliki.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. &lt;/span&gt;&lt;span class="ph filepath"&gt;&lt;var style="font-weight: bold;" class="keyword varname"&gt;DVD_root&lt;/var&gt;&lt;span style="font-weight: bold;"&gt; or  &lt;/span&gt;&lt;var style="font-weight: bold;" class="keyword varname"&gt;extract_root&lt;/var&gt;&lt;span style="font-weight: bold;"&gt;/responsefiles/wbi/template_response.xml&lt;/span&gt;&lt;br /&gt;i&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. &lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;" class="ph filepath"&gt;&lt;var class="keyword varname"&gt;DVD_root&lt;/var&gt; or  &lt;var class="keyword varname"&gt;extract_root&lt;/var&gt;/responsefiles/wbi/run_templates&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="ph filepath"&gt;Jeśli zależy nam na standardowej instalacji, to&lt;/span&gt;&lt;span class="ph filepath"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;" class="ph filepath"&gt;&lt;span style="font-weight: bold;"&gt; &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="ph filepath"&gt;w moim przypadku zmieniłem wszystkie wystąpienia &lt;span style="font-weight: bold;"&gt;"/opt/"&lt;/span&gt; na &lt;span style="font-weight: bold;"&gt;"/home/andrzej/&lt;/span&gt;&lt;/span&gt;&lt;span class="ph filepath"&gt;&lt;span style="font-weight: bold;"&gt;"&lt;/span&gt; w obu plikach oczywiście. Dodatkowo jeśli zależy nam na utworzeniu defaultowego profilu, to należy odkomentować i uzupełnić odpowiedni linie z pliku &lt;/span&gt;&lt;span class="ph filepath"&gt;&lt;span style="font-weight: bold;"&gt;template_response.xml.&lt;br /&gt;&lt;/span&gt;&lt;profile installlocation="'/home/andrzej/ibm/WebSphere/ProcServer'" id="'IBM"&gt;&lt;br /&gt;&lt;/profile&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span class="ph filepath"&gt;&lt; installlocation="'/home/andrzej/ibm/WebSphere/ProcServer'" id="'IBM"&gt;&lt;br /&gt;&lt; data key="'eclipseLocation'" value="'/home/andrzej/ibm/WebSphere/ProcServer'/"&gt;&lt;br /&gt;&lt; data key="cic.selector.nl" value="en"&gt;&lt;br /&gt;&lt; data key="user.cic.imported,com.ibm.websphere.ND.70" value="WAS"&gt;&lt;br /&gt;&lt; data key="'user.bpm.admin.username'" value="'andrzej'/"&gt;&lt;br /&gt;&lt; data key="'user.bpm.admin.password'" value="'haslo'/"&gt;&lt;br /&gt;&lt; / profile &gt;&lt;/data&gt;&lt;/data&gt;&lt;/data&gt;&lt;/data&gt;&lt;/data&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span class="ph filepath"&gt;&lt;br /&gt;&lt;br /&gt;&lt;data key="'eclipseLocation'" value="'/home/andrzej/ibm/WebSphere/ProcServer'/"&gt;&lt;data key="cic.selector.nl" value="en"&gt;&lt;data key="user.cic.imported,com.ibm.websphere.ND.70" value="WAS"&gt;&lt;data key="'user.bpm.admin.username'" value="'andrzej'/"&gt;Uruchomienie instalacji odbywa się poprzez uruchomienie pliku: &lt;span style="font-weight: bold;"&gt;run_templates&lt;/span&gt;. Więcej na ten temat można przeczytać w oficjalnej dokumentacji: &lt;a href="http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/index.jsp?topic=/com.ibm.websphere.wps.doc/doc/tins_installing_silently.html"&gt;link&lt;/a&gt;.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;UWAGA!! &lt;/span&gt;Przygotowanie systemu powinno być identyczne jak to było opisane w poprzednim poście: &lt;a href="http://aludwikowski.blogspot.com/2010/04/instalacja-ibm-websphere-process-server.html"&gt;link&lt;/a&gt;.  Warto też uruchomić całą instalację, czyli plik run_templates, z poziomu root'a, żeby uniknąć problemów z przywilejami.&lt;br /&gt;&lt;/data&gt;&lt;/data&gt;&lt;/data&gt;&lt;/data&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-2082436844348759860?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/2082436844348759860/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacje-ibm-wps-na-red-hat-silent.html#comment-form' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2082436844348759860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/2082436844348759860'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacje-ibm-wps-na-red-hat-silent.html' title='Instalacje IBM WPS na Red Hat - &quot;silent mode&quot;'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5917617597712605250</id><published>2010-04-04T11:51:00.000+02:00</published><updated>2010-04-04T12:21:19.335+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wps'/><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='instalacja'/><category scheme='http://www.blogger.com/atom/ns#' term='WebSphere Process Server'/><category scheme='http://www.blogger.com/atom/ns#' term='red hat'/><title type='text'>Instalacja IBM WebSphere Process Server 7 na Red Hat Enterprise Linux 5</title><content type='html'>Kilka podpowiedzi jak zainstalować IBM WebSphere Process Server na Red Hat Enterprise Linux 5 dla takich linuxowych słabiaków jak ja.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;0. &lt;/span&gt;Nie wiem czy było to konieczne, raczej nie, ale jako rozgrzewkę polecam zainstalowanie sobie Java JDK (wraz z JRE), oraz podpięcie pod przeglądarkę internetową, JDK prędzej czy później i tak będzie nam potrzebne. Aby podpiąć JRE pod FF polecam istrukcję na stornie: &lt;a href="http://java.com/pl/download/help/5000010500.xml#100"&gt;link&lt;/a&gt;. &lt;span style="font-weight: bold;"&gt;UWAGA!&lt;/span&gt; W moim przypadku, przy tworzeniu linku, zamiast katalogu &lt;span class="bodytext"&gt;&lt;span class="bodytext"&gt;&lt;b&gt;ns7-gcc29&lt;/b&gt;, należało wybrać&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="bodytext"&gt;&lt;span class="bodytext"&gt;&lt;b&gt;ns7&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;. Jeśli nie posiadamy katalogu &lt;span style="font-weight: bold;"&gt;plugins&lt;/span&gt; w głównym katalogu FF, to należy go utworzyć ręcznie.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt; Przed przystąpieniem do instalacji WPS'a należy odpowiednio przygotować Red Hat'a. Postępujęmy wg. oficjalnej instrukcji: &lt;a href="http://publib.boulder.ibm.com/infocenter/wasinfo/fep/index.jsp?topic=/com.ibm.websphere.installation.nd.doc/info/ae/ae/tins_prepare.html"&gt;link&lt;/a&gt;. Uwagi do poszczególnym punktów:&lt;br /&gt;1. wybieramy &lt;span style="font-weight: bold;"&gt;umask 002&lt;/span&gt; - wybrałem instalacje na zwykłym koncie użytkownika.&lt;br /&gt;Większość instrukcji jest niekonieczna jeśli pracujemy na "świeżym" linuxie.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;UWAGA!&lt;/span&gt; W przypadku Red Hat'a musimy dodatkowo wyłączyć SELinux - jest to system ochronny systemu (nie wiem do końca jak działa więc nie będę się rozpisywał), który w pewnym momencie może zablokować nam instalację WPS'a.&lt;br /&gt;Aby wyłączyć SELinux, należy zedytować plik "&lt;span style="font-weight: bold;"&gt;/etc/selinux/config&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;# This file controls the state of SELinux on the system.&lt;br /&gt;# SELINUX= can take one of these three values:&lt;br /&gt;# enforcing - SELinux security policy is enforced.&lt;br /&gt;# permissive - SELinux prints warnings instead of enforcing.&lt;br /&gt;# disabled - No SELinux policy is loaded.&lt;br /&gt;SELINUX=enforcing&lt;br /&gt;# SELINUXTYPE= can take one of these two values:&lt;br /&gt;# targeted - Only targeted network daemons are protected.&lt;/blockquote&gt;wystarczy zmienić SELINUX=enforcing na SELINUX=permissive i zrestartować system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2.&lt;/span&gt; Z tak przygotowanym systemem instalacja przebiegła u mnie bez żadnych błędów i problemów. Bazowałem na oficjalnej instrukcji: &lt;a href="http://publib.boulder.ibm.com/infocenter/dmndhelp/v7r0mx/index.jsp?topic=/com.ibm.websphere.wps.doc/welcome_wps.html"&gt;link&lt;/a&gt;. Wybieramy opcje "&lt;span style="font-weight: bold;" class="ph uicontrol"&gt;Nonadministrative or nonroot installation&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt;" A dalej leci już z górki.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5917617597712605250?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5917617597712605250/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacja-ibm-websphere-process-server.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5917617597712605250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5917617597712605250'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/instalacja-ibm-websphere-process-server.html' title='Instalacja IBM WebSphere Process Server 7 na Red Hat Enterprise Linux 5'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-313475766024971203</id><published>2010-04-01T10:47:00.000+02:00</published><updated>2010-04-01T11:46:49.882+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='seam-gen'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><title type='text'>Seam + Eclipse tutorial.</title><content type='html'>Postanowiłem napisać ostatni tutorial z cyklu &lt;span style="font-weight: bold;"&gt;"początki z seamem&lt;/span&gt;", aby dopełnić poprzednie 2, czyli &lt;a href="http://aludwikowski.blogspot.com/2010/03/seam-pierwsze-kroki.html"&gt;&lt;span style="font-weight: bold;"&gt;seam - pierwsze kroki&lt;/span&gt;&lt;/a&gt; i &lt;a href="http://aludwikowski.blogspot.com/2010/03/seam-gen-w-akcji.html"&gt;&lt;span style="font-weight: bold;"&gt;seam-gen w akcji&lt;/span&gt;&lt;/a&gt; oraz aby mój kolega (który zaczął zajmować się seamem) w końcu dał mi święty spokój:P&lt;br /&gt;&lt;br /&gt;Ideą tutoriala jest zintegrowanie aplikacji wygenerowanej przez &lt;span style="font-weight: bold;"&gt;seam-gen&lt;/span&gt; z IDE w tym przypadku z eclipsem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Co potrzebujemy?&lt;/span&gt;&lt;br /&gt;1. Projekt seam, jak to zrobić można przeczytać w wcześniejszym tutorialu &lt;a href="http://aludwikowski.blogspot.com/2010/03/seam-gen-w-akcji.html"&gt;&lt;span style="font-weight: bold;"&gt;seam-gen w akcji&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;2. Eclipse (najlepiej wersja EE): &lt;a href="http://www.eclipse.org/downloads/"&gt;link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Jak podłączyć projekt seam pod Eclipsa?&lt;/span&gt;&lt;br /&gt;Procedura jest dość prosta i nie wymaga wiele wysiłku.&lt;br /&gt;&lt;br /&gt;1. Wybieramy &lt;span style="font-weight: bold;"&gt;File&gt;import&lt;/span&gt;&lt;br /&gt;2. Z zakładki &lt;span style="font-weight: bold;"&gt;General&lt;/span&gt; wybieramy &lt;span style="font-weight: bold;"&gt;Existing Projects into Workspace&lt;/span&gt; i dajemy &lt;span style="font-weight: bold;"&gt;Next&lt;/span&gt;&lt;br /&gt;3. Natępnym krokiem jest wybranie katalogu w którym mamy projekt (&lt;span style="font-weight: bold;"&gt;Browse&lt;/span&gt;)&lt;br /&gt;4. Klikamy &lt;span style="font-weight: bold;"&gt;Finish&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I to by było na tyle, w końcu przechodzimy z poziomu konsoli do kontentego środowiska i rozwijamy nasz projekt wedle uznania.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;UWAGI:&lt;/span&gt;&lt;br /&gt;1. Podczas pracy nad projektem Eclipse używa pliku build.xml do tzn. hot-deploy'ingu, kiedy zapisujemy dany plik, np. widoku, Eclipse automatycznie wykonuje polecenie seam explode (czy też ant explode), od tej pory nie musimy wykonywać go z poziomu konsoli. &lt;span style="color: rgb(255, 0, 0);"&gt;UWAGA&lt;/span&gt; hot-deploy nie działa w przypadku części plików konfiguracyjnych i innych, dlatego od czasu do czasu potrzebny będzie restart serwera. Więcej na ten temat można poczytać w specyfikacji seam.&lt;br /&gt;2. Warto dodać sobie serwer JBoss do IDE, żeby nie było potrzeby odpalania go z poziomu konsoli. W tym celu wykonujemy: &lt;span style="font-weight: bold;"&gt;File&gt;new&gt;other&gt;server&lt;/span&gt;, wybieramy rodzaj serwera oraz wskazujemy jego katalog główny.&lt;br /&gt;3. Dobrym pomysłem może być zainstalowanie wtyczki JBoss tools do Eclipsa, która pozwala na wizualizację wielu plików konfiguracyjnych, widoków, itd.  Najprawdopodobniej pozwala również na używanie seam-gen z poziomu IDE, aczkolwiek nie zgłębiłem tej kwestii.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-313475766024971203?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/313475766024971203/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/seam-eclipse-tutorial.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/313475766024971203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/313475766024971203'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/04/seam-eclipse-tutorial.html' title='Seam + Eclipse tutorial.'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-7040248949792127455</id><published>2010-03-25T13:03:00.001+01:00</published><updated>2010-03-31T21:18:04.877+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='seam-gen'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><category scheme='http://www.blogger.com/atom/ns#' term='jdbc'/><category scheme='http://www.blogger.com/atom/ns#' term='db2'/><title type='text'>Seam-gen + DB2</title><content type='html'>Udało mi się w końcu połączyć działanie seam-gen z DB2, co nie było takim prostym zadaniem jak myślałem. Ogólnie DB2, jak na komercyjne rozwiązanie, sprawia wiele problemów dla użytkownika, który ma pierwszy raz z nim styczność. Żeby wygenerować projekt używając seam-gen na podstawie bazy danych w DB2 (v. 9.7), musimy zmienić kilka rzeczy:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt; Potrzebujemy odpowiedni sterownik JDBC, który możeby znaleźć standardowo w: &lt;span style="font-weight: bold;"&gt;"C:\Program Files\IBM\SQLLIB\java\db2jcc.jar"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. &lt;/span&gt;W pliku konfiguracyjnym seam-gen musimy nanieść kilka zmian:&lt;br /&gt;2.1. hibernate.connection.driver_class=com.ibm.db2.jcc.DB2Driver&lt;br /&gt;2.2. hibernate.default_schema=ANDRZEJ&lt;br /&gt;     //oczywiście powinien być to odpowiednia wartość dla danej bazy&lt;br /&gt;2.3. użytkownika i hasło pozostawić puste, ponieważ nie są wymagane przy łączeniu się z localhost'a&lt;br /&gt;2.4. hibernate.connection.url=jdbc\:db2\:NAZWA_BAZY //jeśli używamy kreatora, podajemy oczywiście: jdbc:db2:NAZWA_BAZY&lt;br /&gt;2.5. driver.jar=c\:/java_libs/db2jcc.jar&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. &lt;/span&gt;Po uruchomieniu polecenia: &lt;span style="font-weight: bold;"&gt;seam generate&lt;/span&gt;, posypie się jeden błąd, który niema znaczenia i cała operacja powinna zakończyć się sukcesem&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4.&lt;/span&gt; Co mnie najbardziej zdziwiło, to fakt, że tak wygenerowany projekt w moim przypadku nie chciał się deployować na serwerze z powodu błędu:&lt;br /&gt;&lt;blockquote&gt;2010-03-25 11:45:27,781 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/DB2Test3]] Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener&lt;br /&gt;org.jboss.seam.InstantiationException: Could not instantiate Seam component: DB2Test3EntityManagerFactory&lt;/blockquote&gt;Powodowanego przez:&lt;br /&gt;&lt;blockquote&gt;Caused by: org.hibernate.HibernateException: Wrong column type: CO_CD, expected: varchar(3)&lt;/blockquote&gt;Rozwiązaniem problemu była zmiana typu kolumn w bazie z &lt;span style="font-weight: bold;font-family:Courier New;font-size:85%;"  &gt;CHARACTER&lt;/span&gt;&lt;span style="font-family:arial;"&gt; &lt;/span&gt;na &lt;span style="font-weight: bold;"&gt;VARCHAR&lt;/span&gt;, przypuszczam, że wiąże się to z jakimiś niepasującymi dialektami, i bardzo możliwe, że istnieje lepsze rozwiązanie, aczkolwiek na chwilę obecną nie jest mi ono znane.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-7040248949792127455?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/7040248949792127455/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-gen-db2.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/7040248949792127455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/7040248949792127455'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-gen-db2.html' title='Seam-gen + DB2'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-4795750658277978300</id><published>2010-03-25T09:37:00.001+01:00</published><updated>2010-05-27T13:53:02.219+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kurs'/><category scheme='http://www.blogger.com/atom/ns#' term='seam-gen'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><title type='text'>Seam-gen w akcji</title><content type='html'>Od 2 tygodniu tonę w dokumentacji/artykułach dotyczących Seam'a, ciężko by było to wszystko przyswajać bez motywacji. Dla tych, którzy jeszcze nie przekonali się do tego, że warto poczytać trochę o tym Seam'ie, proponuje mały tutorial o &lt;span style="font-weight: bold;"&gt;seam-gen&lt;/span&gt;  – coś co w moim wypadku przeważyło szalę: warto, czy nie warto czytać o Seam'ie.&lt;br /&gt;&lt;br /&gt;Seam-gen ogólnie przywrócił moją wiarę w JaveEE, w której od zawsze widziałem ogromny potencjał, ale nie mogłem pojąć, dlaczego tworzenie w niej czegokolwiek jest tak trudne, a przede wszystkim czasochłonne? Ktoś kto używał np. cakePHP wie o czym mówię, ponieważ używając caka, możemy zrobić w pełni działającego CRUD'a w kilka minut. I tą lukę w Javie wypełnia Seam-gen – narzędzie do tworzenia CRUD'a na podstawie bazy danych. Koniec gadania, przejdźmy do rzeczy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Co potrzebujemy:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1. Wszystko to co było potrzebne w poprzednim tutorialu (wybieramy 1 serwer który bardziej nam odpowiada w tym przypadku będę bazował na JBoss'ie)&lt;br /&gt;2. Serwer bazy danych, proponuje zainstalować MySql, najlepiej z jakimś przyjemnym supportem, żebyśmy nie musieli go obsługiwać z poziomu konsoli. Instalacja wamp'a załatwi sprawę: &lt;a href="http://www.wampserver.com/en/download.php"&gt;link&lt;/a&gt;&lt;br /&gt;3. Sterownik JDBC do MySql'a, &lt;a href="http://dev.mysql.com/downloads/connector/j/"&gt;link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Przygotowanie:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;- Wszystko co to zostało napisane we wcześniejszym tutorialu.&lt;br /&gt;- Przygotowanie MySql:&lt;br /&gt;- należy utworzyć nową bazę danych, wraz z przykładowymi tabelami – pozostawiam to czytelnikowi.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 130%;"&gt;&lt;span style="font-weight: bold;"&gt;Odpalenie Seam-gen:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt; Przechodzimy do katalogu głównego Seam'a i edytujemy plik: build.properties, gdzie umieszczamy ścieżkę do katalogu głównego JBoss'a w moim przypadku:&lt;br /&gt;&lt;blockquote&gt;jboss.home=C:\\jboss-4.2.3.GA&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2. &lt;/span&gt;Uruchamiany kreator konfiguracji seam-gen:&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1&amp;gt;seam setup&lt;/blockquote&gt;w tym momencie kreator konfiguracji zada nam serię pytań, których wynikiem będzie plik konfiguracyjny znajdujący się w &lt;span style="color: #990000; font-weight: bold;"&gt;seam-gen/build.properties&lt;/span&gt;. Generalnie możemy edytować go ręcznie lub używać kreatora.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3.&lt;/span&gt; W nawiasach kwardatowych znajdują się defaultowe (lub zapamiętane z wcześniejszego użycia) odpowiedzi – możemy je zatwierdzić naciskając po prostu ENTER.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter your Java project workspace (the directory that contains your Seam projects) [C:/Projects] [C:/Projects]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: c:/eclipse/workspace&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;//Używam '/' zamiast '\\' - mniej pisania.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter your JBoss home directory [C:/Program Files/jboss-4.2.2.GA] [C:/Program Files/jboss-4.2.2.GA]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: C:/jboss-4.2.3.GA&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;//ścieżka do katalogu głównego z JBoss&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the project name [myproject] [myproject]&lt;br /&gt;Odp: NowyProjekt&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;//Wybieramy nazwe dla projektu:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Do you want to use ICEFaces instead of RichFaces [n](y, [n])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Select a RichFaces skin [blueSky] ([blueSky], classic, ruby, wine, deepMarine, emeraldTown, sakura, DEFAULT)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Is this project deployed as an EAR (with EJB components) or a WAR (with no EJB support) [ear] ([ear], war)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: war&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;// wybieramy war, jeśli chcemy korzystać z JavaBeans, zamiast EJB, oraz jeśli chcemy później używać tzn. „hot deployment”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the Java package name for your session beans [com.mydomain.NowyProjekt] [com.mydomain.NowyProjekt]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: com.mydomain.NowyProject.action&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the Java package name for your entity beans [com.mydomain.NowyProject.action] [ com.mydomain.NowyProject.action]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: com.mydomain.NowyProject.model&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the Java package name for your test cases [com.mydomain.NowyProject.action.test] [com.mydomain.NowyProject.action.test]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: com.mydomain.NowyProject.test&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] What kind of database are you using? [hsql] ([hsql], mysql, oracle,postgres, mssql, db2, sybase, enterprisedb, h2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: mysql&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the Hibernate dialect for your database [org.hibernate.dialect.MySQLDialect] [org.hibernate.dialect.MySQLDialect]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the filesystem path to the JDBC driver jar [../lib/hsqldb.jar][../lib/hsqldb.jar]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: C:/java_libs/mysql-connector-java-5.1.12-bin.jar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter JDBC driver class for your database [com.mysql.jdbc.Driver] [com.mysql.jdbc.Driver]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the JDBC URL for your database [jdbc:mysql:///test] [jdbc:mysql://test]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: jdbc:mysql://localhost/cms&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;//url do bazki, w moim przypadku baza ma nazwę „cms”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter database username [sa] [są]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: root&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter database password [] []&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER //ponieważ nie mam ustawionego hasła&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Enter the database catalog name (it is OK to leave this blank) [] []&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: ENTER&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Are you working with tables that already exist in the database? [n] (y, [n])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: y&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Pyt: [input] Do you want to drop and recreate the database tables and data in import.sql each time you deploy? [n] (y, [n])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;Odp: n&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Kreator powinien zakończyć swoje działanie poprawnie:&lt;br /&gt;&lt;blockquote&gt;BUILD SUCCESSFUL&lt;br /&gt;&lt;br /&gt;Total time: 15 minutes 56 seconds&lt;/blockquote&gt;&lt;br /&gt;Możemy podejrzeć jak wygląda plik konfiguracji seam-gen:&lt;span style="font-weight: bold;"&gt; seam-gen/build.properties.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4.&lt;/span&gt; Kolejnym krokiem jest utworzenie bazowej struktury projektu, używając polecenia: seam create-project&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1&amp;gt;seam create-project&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;5. &lt;/span&gt;Wykonując polecenie: seam generate dokonujemy inżynierii odwrotnej i na podstawie bazy generowane są odpowiednie widoki oraz klasy.&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1&amp;gt;seam generate&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;6. &lt;/span&gt;Ostatnim poleceniem jest: seam explode, które pozwoli nam zdeployować projekt i być oczarowanym tym jak ładnie seam-gen wygenerował nam CRUD'a&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1&amp;gt;seam explode&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;7. &lt;/span&gt;Uruchamiamy JBoss'a i sprawdzamy jak wygląda nasz projekt w  przeglądarce:&lt;br /&gt;&lt;blockquote&gt;http://localhost:8080/NowyProjekt/&lt;/blockquote&gt;&lt;br /&gt;W następnej notce postaram się napisać jak podłączyć tak wygenerowany projekt pod Eclipsa lub NetBeansa&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-4795750658277978300?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/4795750658277978300/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-gen-w-akcji.html#comment-form' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4795750658277978300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/4795750658277978300'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-gen-w-akcji.html' title='Seam-gen w akcji'/><author><name>Andrzej Ludwikowski</name><uri>http://www.blogger.com/profile/16655895560488629775</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_-EhdUDK1j_U/S6eQ3cjNjjI/AAAAAAAAAAU/kNtrbwwu7CU/S220/ja.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-5979885196430917773</id><published>2010-03-20T11:41:00.000+01:00</published><updated>2010-03-31T21:19:26.666+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='przykłady'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='examples'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><title type='text'>Seam - pierwsze kroki.</title><content type='html'>Biorąc pod uwagę swoje własne lenistwo, oraz to, że po prostu lubię jak mi ktoś pewne rzeczy wytłumaczy łopatologicznie, postanowiłem, że napisze krótki tutorial jak uruchomić przykładowe aplikacje z seam'a (mimo wcześniejszego posta, w którym w sumie napisałem gdzie najlepiej szukać pomocy). Tutorial obejmuje 2 rodzaje serwerów Tomcat i JBoss, ale możemy wybrać jeden z nich. Dla wszystkim miłośników Tomcat'a (sam do nich należę) polecałbym jednak spróbowanie JBoss'a.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Co potrzebujemy?&lt;/b&gt;&lt;br /&gt;1. Seam w wersji 2.0.2.SP1: &lt;a href="http://seamframework.org/Download"&gt;link&lt;/a&gt;&lt;br /&gt;2. Tomcat w wersji 6.x: &lt;a href="http://tomcat.apache.org/download-60.cgi"&gt;link&lt;/a&gt;&lt;br /&gt;3. lub JBoss w wersji 4.2.3: &lt;a href="http://www.jboss.org/jbossas/downloads/"&gt;link&lt;/a&gt;&lt;br /&gt;4. Ant w wersji 1.8: &lt;a href="http://ant.apache.org/bindownload.cgi"&gt;link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Przygotowanie:&lt;/b&gt;&lt;br /&gt;należy ściągnąć wyżej wymienione oprogramowanie i rozpakować. Oczywiście zakładamy, że mamy zainstalowane JDK w wersji minimum 5. oraz ustawione są zmienne środowiskowe JRE_HOME i JAVA_HOME w zależności od tego gdzie zainstalowaliśmy Javę. Jak to zrobić można przeczytać m.in. &lt;a href="http://wso2.org/project/wsas/java/1.1/docs/setting-java-home.html"&gt;tu&lt;/a&gt;. Aby sprawdzić czy zmienna jest prawidłowo ustawiona możemy ją wyświetlić używając komendy set:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;C:\Documents and Settings\andrzej&amp;gt;set JRE_HOME&lt;br /&gt;JRE_HOME=C:\Program Files\Java\jre6&lt;/blockquote&gt;Po ustawieniu zmiennej, bardzo często trzeba uruchomić ponownie konsolę, żeby było ją widać - nie mam pojęcia dlaczego.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Przygotowanie Ant'a:&lt;/b&gt;&lt;br /&gt;po ściągnięciu Ant'a i rozpakowaniu musimy ustawić zmienną środowiskową ANT_HOME na katalog w którym mamy Ant'a (%ANT_HOME%\bin\ant.bat), w moim przypadku:&lt;br /&gt;&lt;blockquote&gt;C:\Documents and Settings\andrzej&amp;gt;set ant&lt;br /&gt;ANT_HOME=C:\apache-ant-1.8.0&lt;/blockquote&gt; Musimy również dodać do zmiennej &lt;span style="font-weight: bold;"&gt;PATH&lt;/span&gt; (oczywiście po średniku) "%ANT_HOME%\bin", czyli w moim przypadku: "C:\apache-ant-1.8.0\bin".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Przygotowanie Tomcat'a:&lt;/b&gt;&lt;br /&gt;Tomcat sam w sobie nie wymaga wielu przygotowań, oprócz prawidłowej instalacji Javy, aczkolwiek jeśli chcemy przetestować przykłady korzystające z EJB, musimy zainstalować Embedded JBoss, bardzo dobrą instrukcję jak to zrobić, możemy znaleźć &lt;a href="http://docs.jboss.com/seam/latest/reference/en-US/html/configuration.html#config.install.embedded"&gt;tutaj&lt;/a&gt;. Dla tych którzy mają u siebie Java EE 6, należy nie zapomnieć o dodaniu jednej linii na początku pliku catalina.bat:&lt;br /&gt;&lt;blockquote&gt;&lt;pre class="programlisting"&gt;set JAVA_OPTS=%JAVA_OPTS% -Dsun.lang.ClassLoader.allowArraySyntax=true&lt;/pre&gt;&lt;/blockquote&gt;&lt;b&gt; Przygotowanie JBoss'a:&lt;/b&gt;&lt;br /&gt;none&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Odpalanie przykładowych aplikacji Seam:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1.&lt;/span&gt; Przechodzimy do &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;katalogu głównego&lt;/span&gt; seam (nie pomylić plików!, ponieważ pliki build są praktycznie w każdym pod katalogu)  i edytujemy plik: &lt;b&gt;&lt;span style="color:black;"&gt;build.properties&lt;/span&gt;&lt;/b&gt; dodając w nim wspomniane wcześniej) ścieżki do katalogów głównych JBoss'a i Tomcat'a, w moim przypadku:&lt;br /&gt;&lt;blockquote&gt;jboss.home=C:\\jboss-4.2.3.GA&lt;br /&gt;tomcat.home=C:\\apache-tomcat-6.0.24 &lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2. &lt;/span&gt;Przechodzimy do folderu "examples" i wybieramy jeden z przykładów, standardowo niech to będzie: "registration", przychodzimy do folderu wybranego przykładu z poziomu linii komend wykonujemy:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2.A.1. &lt;/span&gt;W przypadku JBoss'a polecenie &lt;b&gt;ant&lt;/b&gt; &lt;b&gt;explode&lt;/b&gt;:&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1\examples\registration&amp;gt;ant explode &lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2.A.2.&lt;/span&gt; Następnie uruchamiany JBossa z linii komend:&lt;br /&gt;&lt;blockquote&gt;C:\jboss-4.2.3.GA\bin&amp;gt;run.bat&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2.A.3.&lt;/span&gt; Odpalamy przeglądarkę i uruchamiamy nasz przykład:&lt;br /&gt;&lt;blockquote&gt;http://localhost:8080/seam-registration/&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2.B.1. &lt;/span&gt;W przypadku Tomcat'a (jeśli wczęśniej uruchamialiśmy przykład na JBoss'ie to musimy zatrzymać serwer oraz w katalogu przykładu wykonać &lt;b&gt;ant clean&lt;/b&gt;):&lt;br /&gt;&lt;blockquote&gt;C:\Andrzej\seam\jboss-seam-2.0.2.SP1\examples\registration&amp;gt;ant tomcat.deploy&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2.B.2. &lt;/span&gt;Uruchamiamy Tomcat'a:&lt;br /&gt;&lt;blockquote&gt;C:\apache-tomcat-6.0.24\bin&amp;gt;startup.bat&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;2.B.3.&lt;/span&gt; Odpalamy przeglądarkę i uruchamiamy nasz przykład (link jest trochę inny niż w przypadku JBoss'a, należy pamiętać o przedrostku "jboss-"):&lt;br /&gt;&lt;blockquote&gt;http://localhost:8080/jboss-seam-registration/&lt;/blockquote&gt;I to by było na tyle, aby odpalić inne przykłady postępujemy analogicznie, zmieniając odpowiednio nazwę przykładu, tam gdzie jest to potrzebne.&lt;br /&gt;W następnym poście postaram się napisać coś o seam-gen - bardzo przydatne narzędzie.&lt;br /&gt;Tymczasem pozdrawiam.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-5979885196430917773?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/5979885196430917773/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-pierwsze-kroki.html#comment-form' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5979885196430917773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/5979885196430917773'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/seam-pierwsze-kroki.html' title='Seam - pierwsze kroki.'/><author><name>aludwikowski</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_5-YyC6peeeQ/S5pQCKOHqxI/AAAAAAAAAAM/D3LGfEO9H2M/S220/ja.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8583476407209452685.post-7025415517136751900</id><published>2010-03-12T12:40:00.000+01:00</published><updated>2010-03-22T14:46:54.851+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IBM'/><category scheme='http://www.blogger.com/atom/ns#' term='seam'/><category scheme='http://www.blogger.com/atom/ns#' term='ESI'/><title type='text'>ESI - praktyki edukacje w IBM</title><content type='html'>Od następnego tygodnia (tj. 12.03.2010) zaczynam już na poważnie praktyki w firmie IBM, uczestnicząc w tzw. programie ESI (Educational Students Intership).&lt;br /&gt;&lt;br /&gt;Tematyka moich praktyk będzie głównie krążyła wokół aspektów związanych z technologią JavaEE a konkretnie z frameworkiem SEAM.&lt;br /&gt;&lt;br /&gt;Moim mentorem podczas praktyk będzie &lt;a href="http://jlaskowski.blogspot.com/"&gt;Jacek Laskowski&lt;/a&gt;, a najnowsze informacje o postępach będzie można śledzić na &lt;a href="http://twitter.com/aludwikowski"&gt;twitterze&lt;/a&gt; oraz &lt;a href="http://andrzejludwikowski.blip.pl/"&gt;bliperze&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jeśli chodzi o ten tydzień to głównie przygotowywałem swoją maszynę do pracy, co wymagało ściągnięcia całej masy instalek, bibliotek, tutoriali. Oczywiście nie byłbym sobą gdybym już czegoś nie zaczął robić, więc wstępnie zapoznałem się z frameworkiem SEAM, ustawiłem odpowiednio serwer toccat 6.0, aby mógł współpracować z SEAM. Ogólnie tomcat bez żadnych dodatkowych ustawień może współpracować z SEAM aczkolwiek jeśli chcemy odpalić przykłady korzystające z EJB, to musimy doinstalować do niego Embedded JBoss, instrukcje jak to wykonać możemy znaleźć tu:&lt;br /&gt;&lt;a href="http://community.jboss.org/wiki/EmbeddedAndTomcat"&gt;http://community.jboss.org/wiki/EmbeddedAndTomcat&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;W swoich dotychczasowych testach wykorzystywałem SEAM’a w wersji: 2.0.2.SP1, na oficjalnej stronie SEAM’a jest już nowsza wersja aczkolwiek zauważyłem, że większość tutoriali w internecie jest przygotowanych pod tą wersje.&lt;br /&gt;Przed przystąpieniem do odpalania przykładów z SEAM, radziłbym oprócz zapoznania się z oficjalną dokumentacją:&lt;br /&gt;&lt;a href="http://docs.jboss.com/seam/latest/reference/en-US/html/index.html"&gt;http://docs.jboss.com/seam/latest/reference/en-US/html/index.html&lt;/a&gt;&lt;br /&gt;zapoznać się również z plikiem readme.txt – znajdującym się w folderze: seam/examples. Jest tam najlepiej wytłumaczone jak odpalać wszystkie przykłady dla tomcat’a i jboss’a używając ant’a. Jeszcze jeden mały tips z mojej strony dla użytkowników windowsa, plik build.properties (w katalogu seam), powinien być uzupełniony o ścieżki do obu serwerów np. w ten sposób:&lt;br /&gt;&lt;blockquote&gt;jboss.home=C:\\Andrzej\\jboss\\jboss-4.2.3.GA&lt;br /&gt;tomcat.home=C:\\apache-tomcat-6.0.24&lt;/blockquote&gt;&lt;br /&gt;“\\” - podwójny ukośnik zajął mi sporą część dnia w poszukiwaniu, co jest nie tak.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8583476407209452685-7025415517136751900?l=aludwikowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://aludwikowski.blogspot.com/feeds/7025415517136751900/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/od-nastepnego-tygodnia-tj.html#comment-form' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/7025415517136751900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8583476407209452685/posts/default/7025415517136751900'/><link rel='alternate' type='text/html' href='http://aludwikowski.blogspot.com/2010/03/od-nastepnego-tygodnia-tj.html' title='ESI - praktyki edukacje w IBM'/><author><name>aludwikowski</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='28' height='32' src='http://4.bp.blogspot.com/_5-YyC6peeeQ/S5pQCKOHqxI/AAAAAAAAAAM/D3LGfEO9H2M/S220/ja.jpg'/></author><thr:total>2</thr:total></entry></feed>
