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

<channel>
	<title>Splatch's devblog &#187; Java</title>
	<atom:link href="http://blog.dywicki.pl/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.dywicki.pl</link>
	<description>Pragmatyzm kontrolowany</description>
	<lastBuildDate>Thu, 01 Dec 2011 15:47:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Java Servlet API 3.0</title>
		<link>http://blog.dywicki.pl/2008/12/22/java-servlet-api-3/</link>
		<comments>http://blog.dywicki.pl/2008/12/22/java-servlet-api-3/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 10:35:47 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[tlumaczenia]]></category>
		<category><![CDATA[Wiadomości]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=243</guid>
		<description><![CDATA[Dnia wczorajszego na InfoQ o tym, że został udostępniony szkic specyfikacji Servlet API 3.0. Największe nowości to&#8230; adnotacje, które będą mogły być użyte w miejsce interfejsów i dziedziczenia. Łatwiejsze tworzenie, ang. Ease of Development (Eod): W wcześniejszym szkicu zostały zaprezentowane adnotacje jako sposób na stworzenie Servletu &#8211; POJO. Jakkolwiek po dyskusji i odpowiedzi społeczności adnotacje [...]]]></description>
			<content:encoded><![CDATA[<p>Dnia wczorajszego na <a href="http://infoq.com">InfoQ</a> o tym, że został udostępniony <a href="http://www.infoq.com/news/2008/12/servlet3_debate">szkic specyfikacji</a> Servlet <acronym title="Application Programming Interface">API</acronym> 3.0. Największe nowości to&#8230; adnotacje, które będą mogły być użyte w miejsce interfejsów i dziedziczenia.<br />
<span id="more-243"></span></p>
<blockquote>
<ul>
<li>Łatwiejsze tworzenie, ang. <em>Ease of Development</em> (Eod): W wcześniejszym szkicu zostały zaprezentowane adnotacje jako sposób na stworzenie Servletu &#8211; POJO. Jakkolwiek po dyskusji i odpowiedzi społeczności adnotacje @GET i @POST na poziomie metod zostały wycofane. Zostają jednak adnotacje dla typów &#8211; deklaracja sevletu @WebServlet oraz deklaracja filtru @ServletFilter, @WebServletContextListener będzie alternatywnym sposobem na zdefiniowanie context listenera. Dodatkowo adnotacje takie jak @Resouorce będą wspierane w aplikacjach webowych będą zachowywać się tak jak w starszej wersji specyfikacji (2.5).</li>
<li>Rozszerzalność: szkielety webowe zbudowane na bazie servletów są bardzo popularne. Jest ich bardzo wiele, do wyboru w zależności od problemów, które mają rozwiązywać. Specyfikacja będzie umożliwiała łatwiejszą konfigurację tychże szkieletów.</li>
<li>Przetwarzanie asynchroniczne: największym wyzwaniem i zmianą jaką podjęli autorzy specyfikacji. W poprzedniej wersji zostały zdefiniowane operacje zatrzymania (suspend) oraz wznowienia (resume). Po publikacji grupa ekspertów podjęła dyskusję na temat przypadków użycia takiego rozwiązania.</li>
</ul>
</blockquote>
<p>Na łamach <a href="http://www.infoq.com/news/2008/12/servlet3_debate">InfoQ</a> są fragmenty dyskusji na temat fragmentów specyfikacji. Ludzie z JBossa krytykują Jetty, inni krytykują grupę która pracuje nad specyfikacją, że kiepsko współpracuje ze społecznością.</p>
<p>Mam osobiście nadzieję, że ta burza mózgów wyjdzie nam na dobre i adnotacje w Servlet <acronym title="Application Programming Interface">API</acronym> 3.0 nie będą jedyną nowością. :-)</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/12/22/java-servlet-api-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Typ wyliczeniowy TimeUnit w Javie oraz klasa w PHP</title>
		<link>http://blog.dywicki.pl/2008/12/09/timeunit-enum-in-java-and-class-inphp/</link>
		<comments>http://blog.dywicki.pl/2008/12/09/timeunit-enum-in-java-and-class-inphp/#comments</comments>
		<pubDate>Tue, 09 Dec 2008 16:10:00 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=242</guid>
		<description><![CDATA[Java od wersji 5.0 zawiera możliwość definiowania typów wyliczeniowych. Jednym z praktycznych przykładów zastosowania tego mechanizmu jest TimeUnit. Enum ten służy do konwertowania jednostek czasu pomiędzy różnymi wielkościami &#8211; na przykład z minut na sekundy. import java.util.concurrent.TimeUnit; // ... TimeUnit.MINUTES.toSeconds(55); Fajna sprawa &#8211; jeśli mamy do czynienia z konwersjami. Inny pożyteczny przykład to przekazywanie czasu [...]]]></description>
			<content:encoded><![CDATA[<p>Java od wersji 5.0 zawiera możliwość definiowania typów wyliczeniowych. Jednym z praktycznych przykładów zastosowania tego mechanizmu jest <a href="http://www.docjar.com/docs/api/java/util/concurrent/TimeUnit.html">TimeUnit</a>. Enum ten służy do konwertowania jednostek czasu pomiędzy różnymi wielkościami &#8211; na przykład z minut na sekundy.<br />
<span id="more-242"></span></p>
<pre class="brush: java;">
import java.util.concurrent.TimeUnit;
// ...
TimeUnit.MINUTES.toSeconds(55);
</pre>
<p>Fajna sprawa &#8211; jeśli mamy do czynienia z konwersjami. Inny pożyteczny przykład to przekazywanie czasu jako argumentu:</p>
<pre class="brush: java;">
package org.code_house.concurrent;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Lock {
    void lock(TimeUnit unit, long value) throws InterruptedException {
        Thread.sleep(unit.toMillis(value));
    }

    public static void main(String[] args) throws Exception {
        System.out.println(&quot;before &quot; + new Date());

        new Lock().lock(TimeUnit.SECONDS, 30);

        System.out.println(&quot;after &quot; + new Date());
    }

}
</pre>
<p>Programista, który używa takiej klasy nie musi się więc przejmować konwertowaniem jednostek na milisekundy, które są podstawą do wywołania metody Thread.sleep.</p>
<p>TimeUnit obsługuje następujące wielkości:</p>
<ul>
<li>nanosekundy</li>
<li>mikrosekundy</li>
<li>milisekundy</li>
<li>sekundy</li>
<li>minuty</li>
<li>godziny</li>
<li>dni</li>
</ul>
<p>Posługując się kodem z Javy postanowiłem sobie przypomnieć nieco <acronym title="Pre-Hypertext Processing">PHP</acronym> i napisałem wersję tego typu wyliczeniowego dla PHP:</p>
<pre class="brush: php;">&lt;?php
// namespace org\code_house\util;
/**
 * A simple class for converting between time units.
 *
 * @author Łukasz Dywicki &lt;luke@code-house.org&gt;
 */
class TimeUnit {

    /**
     * Nanoseconds.
     */
    const NANOS     = 0;

    /**
     * Microseconds.
     */
    const MICROS    = 1;

    /**
     * Milliseconds
     */
    const MILLIS    = 2;

    /**
     * Seconds.
     */
    const SECONDS   = 3;

    /**
     * Minutes.
     */
    const MINUTES   = 4;

    /**
     * Hours.
     */
    const HOURS     = 5;

    /**
     * Days.
     */
    const DAYS      = 6;

    /**
     * Conversion table between time units.
     * @var array
     */
    private static $modifiers = array(
         self::NANOS     =&gt; 0.000000001,
         self::MICROS    =&gt; 0.000001,
         self::MILLIS    =&gt; 0.001,
         self::SECONDS   =&gt; 1,
         self::MINUTES   =&gt; 60,
         self::HOURS     =&gt; 3600,
         self::DAYS      =&gt; 86400,
    );

    /**
     * Constructs new time unit.
     *
     * @param $type TimeUnit Time unit base.
     */
    public function __construct($type) {
        if ($type &lt; TimeUnit::NANOS || $type &gt; TimeUnit::DAYS) {
            throw new RuntimeException('Time unit base is out of range');
        }
        $this-&gt;type = $type;
    }

    public function toNanos($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::NANOS);
    }

    public function toMicros($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::MICROS);
    }

    public function toMilis($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::MILLIS);
    }

    public function toSeconds($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::SECONDS);
    }

    public function toMinutes($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::MINUTES);
    }

    public function toHours($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::HOURS);
    }

    public function toDays($value) {
        return TimeUnit::convert($this-&gt;type, $value, TimeUnit::DAYS);
    }

    /**
     * Convert method.
     *
     * @param $from Time unit
     * @param $value Number of values.
     * @param $to Time unit
     * @return decimal
     */
    private final static function convert($from, $value, $to) {
        if ($from === $to) {
            return $value;
        }

        $value *= self::$modifiers[$from];
        return $value / self::$modifiers[$to];
    }
}

// przykład użycia
$unit = new TimeUnit(TimeUnit::SECONDS);
echo $unit-&gt;toMinutes(60) .&quot;\n&quot;;

$unit = new TimeUnit(TimeUnit::HOURS);
echo $unit-&gt;toMinutes(1) .&quot;\n&quot;;

?&gt;</pre>
<p>Niestety brak pól z modyfikatorami <b>public static final</b> w <acronym title="Pre-Hypertext Processing">PHP</acronym> uniemożliwił zastosowanie choćby czegoś podobnego do typu wyliczeniowego.. Kod klasy dla <acronym title="Pre-Hypertext Processing">PHP</acronym> jest wolnodostępny. :-)</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/12/09/timeunit-enum-in-java-and-class-inphp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>EasyMock i IAnswer, recepta na zachowanie metod</title>
		<link>http://blog.dywicki.pl/2008/12/03/easymock-inaswer-as-method-behaviour-recipe/</link>
		<comments>http://blog.dywicki.pl/2008/12/03/easymock-inaswer-as-method-behaviour-recipe/#comments</comments>
		<pubDate>Wed, 03 Dec 2008 16:06:42 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Porady]]></category>
		<category><![CDATA[Testy jednostkowe]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=240</guid>
		<description><![CDATA[Złym zwyczajem jest modyfikowanie argumentów zamiast zwracania nowej wartości, jakkolwiek trafiają się sytuacje gdy testowany kod powinien weryfikować takie wywołania. W EasyMock mamy do dyspozycji w takim przypadku interfejs IAnswer. Jego użycie jest w miarę proste &#8211; dobieramy się do tablicy argumentów i robimy z nią co potrzeba. Oto przykład &#8211; interfejs Populator dodaje do [...]]]></description>
			<content:encoded><![CDATA[<p>Złym zwyczajem jest modyfikowanie argumentów zamiast zwracania nowej wartości, jakkolwiek trafiają się sytuacje gdy testowany kod powinien weryfikować takie wywołania. W EasyMock mamy do dyspozycji w takim przypadku interfejs IAnswer. Jego użycie jest w miarę proste &#8211; dobieramy się do tablicy argumentów i robimy z nią co potrzeba.<br />
<span id="more-240"></span><br />
Oto przykład &#8211; interfejs Populator dodaje do przekazanej tablicy określoną wartość w puste miejsca. Zwraca też ilość zmian, które zaprowadził. Całość jest oparta na bardzo prostym kodzie, zaledwie jedna pętla, jakkolwiek na potrzeby przykładu jest to wystarczające. Pragnę jednak nadmienić, że w podobny sposób można testować bardziej złożony kod, gdzie kolaborują ze sobą dwa obiekty &#8211; tj. Observator i Observable czy też Visitor i Visitable.</p>
<pre class="brush: java;">package org.code_house.test.mock;

interface Populator {
    int fill(String value, String[] arguments);
}
</pre>
<p>Implementacja interfejsu jest bardzo prosta:</p>
<pre class="brush: java;">package org.code_house.test.mock;

class FillAnswer implements IAnswer&lt;Integer&gt; {
    public Integer answer() throws Throwable {
        // pobranie argumentow
        Object[] arguments = EasyMock.getCurrentArguments();
        String name = (String) arguments[0];
        Object[] values = (Object[]) arguments[1];

        // logika potrzebna do testu
        int populated = 0;
        for (int i = 0; i &lt; values.length; i++) {
            if (values[i] == null) {
                populated++;
                values[i] = name;
            }
        }
        return populated;
    }
}
</pre>
<p>Test jest również niezbyt skomplikowany &#8211; bazuje on na poprzedniej nocie &#8211; &#8220;Testowanie tablic argumentów z EasyMock&#8221;:</p>
<pre class="brush: java;">package org.code_house.test.mock;

import static org.easymock.EasyMock.*;
import org.easymock.IAnswer;

import java.util.Arrays;

import junit.framework.TestCase;

public class AnswerTest extends TestCase {

    public void testPopulate() {
        Populator populator = createMock(Populator.class);
        expect(populator.fill(eq(&quot;Code House&quot;), aryEq(new String[3])))
            .andAnswer(new FillAnswer());
        expect(populator.fill(eq(&quot;Code House&quot;), aryEq(new String[] {&quot;1&quot;})))
            .andAnswer(new FillAnswer());
        replay(populator);

        // tablica do wypełnienia
        String[] populated = new String[3];
        int added = populator.fill(&quot;Code House&quot;, populated);
        assertEquals(3, added);
        // w odpowiedzi oczekujemy dodania 3 nowych elementów
        assertTrue(Arrays.equals(
            new String[] {&quot;Code House&quot;, &quot;Code House&quot;, &quot;Code House&quot;},
            populated
        ));

        // w tym przypadku nie oczekujemy nowości
        added = populator.fill(&quot;Code House&quot;, new String[] {&quot;1&quot;});
        assertEquals(0, added);
    }
}
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/12/03/easymock-inaswer-as-method-behaviour-recipe/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Testowanie tablic argumentów z EasyMock</title>
		<link>http://blog.dywicki.pl/2008/11/26/testing-array-parameters-with-easymock/</link>
		<comments>http://blog.dywicki.pl/2008/11/26/testing-array-parameters-with-easymock/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 06:00:02 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Porady]]></category>
		<category><![CDATA[Testy jednostkowe]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=239</guid>
		<description><![CDATA[Często zdarza się że metody, które piszemy i później testujemy mają argumenty w postaci tablic. EasyMock wówczas potrafi zgłosić wyjątek, że przekazana tablica jest różna od oczekiwanej mimo, że zawartość tablic jest identyczna. java.lang.AssertionError: Unexpected method call find([Ljava.lang.String;@1ad77a7): find([Ljava.lang.String;@b8f82d): expected: 1, actual: 0 package org.code_house.test.mock; import static org.easymock.EasyMock.aryEq; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import [...]]]></description>
			<content:encoded><![CDATA[<p>Często zdarza się że metody, które piszemy i później testujemy mają argumenty w postaci tablic. EasyMock wówczas potrafi zgłosić wyjątek, że przekazana tablica jest różna od oczekiwanej mimo, że zawartość tablic jest identyczna.<br />
<span id="more-239"></span></p>
<pre class="brush: java;">java.lang.AssertionError:
  Unexpected method call find([Ljava.lang.String;@1ad77a7):
    find([Ljava.lang.String;@b8f82d): expected: 1, actual: 0
</pre>
<pre class="brush: java;">
package org.code_house.test.mock;

import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;

import java.util.Collections;
import java.util.List;

import junit.framework.TestCase;

interface Finder {
    List&lt;String&gt; find(String[] names);
}

public class FinderTest extends TestCase {

    public void testFind() {
        Finder mock = createMock(Finder.class);
        expect(mock.find(aryEq(new String[] {&quot;Amy&quot;, &quot;Luke&quot;}))).andReturn(
            Collections.EMPTY_LIST);
        replay(mock);

        List&lt;String&gt; list = mock.find(new String[] {&quot;Amy&quot;, &quot;Luke&quot;});
        assertTrue(list.isEmpty());
    }
}
</pre>
<p>Rozwiązaniem tych problemów jest użycie mechanizmu &#8220;matcherów&#8221;, które są wbudowane w sam szkielet. Najprostszym sposobem na ich użycie jest odwołanie przy pomocy statycznego wywołania którejś z metod EasyMock. Poniżej znajduje się lista dostępnych matcherów. Wartość &#8220;given&#8221; to argument przekazany w wywołaniu metody. </p>
<ul>
<li><strong>eq</strong>(X value)<br />
    Argument pasuje jeśli wyrażenie value.equals(given) zwróci true. Dostępny dla wszystkich typów prostych i obiektów.</li>
<li><strong>anyBoolean</strong>(), <strong>anyByte</strong>(), <strong>anyChar</strong>(), <strong>anyDouble</strong>(), <strong>anyFloat</strong>(), <strong>anyInt</strong>(), <strong>anyLong</strong>(), <strong>anyObject</strong>(), <strong>anyShort</strong>()<br />
    Dowolna wartość zostanie przepuszczona niezależnie od tego co będzie przekazane. Dostępny dla wszystkich typów.
</li>
<li><strong>eq</strong>(X value, X delta)<br />
    Pasuje jeśli aktualna jeśli wyrażenie given jest równe value z dokładnością do delta. Dostępne dla typów float oraz double.</li>
<li><strong>aryEq</strong>(X value)<br />
    Pasuje jeśli wyrażenie Arrays.equals(value, given) zwraca true. Dostępne dla tablic typów prostych jak i dla obiektów.</li>
<li><strong>isNull</strong>()<br />
    Pasuje jeśli given == null. Dostępne tylko dla obiektów.</li>
<li><strong>notNull</strong>()<br />
    Pasuje jeśli given != null. Dostępne tylko dla obiektów.</li>
<li><strong>same</strong>(X value)<br />
    Pasuje jeśli wyrażenie value == given jest prawdziwe. Dostępne tylko dla obiektów.</li>
<li><strong>isA</strong>(Class clazz)<br />
    Pasuje jeśli given instanceof clazz zwraca true. Given może być instancję clazz jak i pochodną.</li>
<li><strong>lt</strong>(X value), <strong>leq</strong>(X value), <strong>geq</strong>(X value), <strong>gt</strong>(X value)<br />
    Zwraca true jeśli given jest mniejsze, mniejsze równe, większe równe bądź większe niż value. Dostępne dla wszystkich numerycznych typów prostych.</li>
<li><strong>startsWith</strong>(String prefix), <strong>contains</strong>(String substring), <strong>endsWith</strong>(String suffix)<br />
    Zwraca true jeśli given  zaczyna się, zawiera bądź kończy się daną wartością. Dostępne dla argumentów typu String.</li>
<li><strong>matches</strong>(String regex), <strong>find</strong>(String regex)<br />
    Pasuje jeśli given pasuje w całości do wyrażenia/fragment pasuje. Dostępne dla argumentów typu String.</li>
<li><strong>and</strong>(X first, X second)<br />
    Zwraca true jeśli matcher first oraz second zwracają prawdę.</li>
<li><strong>or</strong>(X first, X second)<br />
    Zwraca true jeśli matcher first bądź second pasuje.</li>
<li><strong>not</strong>(X value)<br />
    Zwraca true jeśli matcher value zwrócił fałsz.</li>
</ul>
<p>Uzbrojeni w taki zestaw matcherów możemy poprawić kod testu tak by był on poprawny:</p>
<pre class="brush: java;">

public class FinderTest extends TestCase {

    public void testFind() {
        Finder mock = createMock(Finder.class);
        expect(mock.find(aryEq(new String[] {&quot;Amy&quot;, &quot;Luke&quot;}))).andReturn(
            Collections.EMPTY_LIST);
        replay(mock);

        List&lt;String&gt; list = mock.find(new String[] {&quot;Amy&quot;, &quot;Luke&quot;});
        assertTrue(list.isEmpty());
    }
}
</pre>
<p>Inny przykład:</p>
<pre class="brush: java;">
public class FinderTest extends TestCase {

    public void testFind() {
        Finder mock = createMock(Finder.class);
        expect(mock.find(&quot;Lucy&quot;, aryEq(new String[] {&quot;Amy&quot;, &quot;Luke&quot;}))).andReturn(
            Collections.EMPTY_LIST);
        replay(mock);

        List&lt;String&gt; list = mock.find(&quot;Lucy&quot;, new String[] {&quot;Amy&quot;, &quot;Luke&quot;});
        assertTrue(list.isEmpty());
    }
}
</pre>
<p>Warto zwrócić uwagę na to, że jeśli korzystamy dla matchera aby dopasować argument to musimy zrobić to dla wszystkich, inaczej poleci wyjątek:</p>
<pre class="brush: java;">
java.lang.IllegalStateException: 2 matchers expected, 1 recorded.
</pre>
<p>Stąd nasz test w końcowej postaci powinien wyglądać następująco:</p>
<pre class="brush: java;">
package org.code_house.test.mock;

import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;

import java.util.Collections;
import java.util.List;

import junit.framework.TestCase;

interface Finder {
    List&lt;String&gt; find(String[] names);

    List&lt;String&gt; find(String name, String[] names);
}

public class FinderTest extends TestCase {

    public void testFind() {
        Finder mock = createMock(Finder.class);
        expect(mock.find(eq(&quot;Lucy&quot;), aryEq(new String[] {&quot;Amy&quot;, &quot;Luke&quot;}))).andReturn(
            Collections.EMPTY_LIST);
        replay(mock);

        List&lt;String&gt; list = mock.find(&quot;Lucy&quot;, new String[] {&quot;Amy&quot;, &quot;Luke&quot;});
        assertTrue(list.isEmpty());
    }
}
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/11/26/testing-array-parameters-with-easymock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uruchom inny język w Javie</title>
		<link>http://blog.dywicki.pl/2008/11/24/scripting-inside-java/</link>
		<comments>http://blog.dywicki.pl/2008/11/24/scripting-inside-java/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 06:00:02 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Porady]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=236</guid>
		<description><![CDATA[Do Javy 6.0 zostało dołączone API (JSR 223) umożliwiające wywoływanie różnych języków wewnątrz wirtualnej maszyny. Można w ten sposób przesunąć chociażby moment kompilowania kodu na później bądź od razu podpiąć język interpretowany. Poniżej przykład: package org.code_house.scripting; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; public class JSMain { public static void main(String[] args) throws Exception { ScriptEngineManager [...]]]></description>
			<content:encoded><![CDATA[<p>Do Javy 6.0 zostało dołączone <acronym title="Application Programming Interface">API</acronym> (<a href="http://www.jcp.org/en/jsr/detail?id=223">JSR 223</a>) umożliwiające wywoływanie różnych języków wewnątrz wirtualnej maszyny. Można w ten sposób przesunąć chociażby moment kompilowania kodu na później bądź od razu podpiąć język interpretowany.<br />
<span id="more-236"></span><br />
Poniżej przykład:</p>
<pre class="brush: java;">
package org.code_house.scripting;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;

public class JSMain {

    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();

        System.out.println(&quot;Dostępne języki&quot;);
        for (ScriptEngineFactory engine : manager.getEngineFactories()) {
            System.out.println(engine.getNames());
        }

        ScriptEngine engine = manager.getEngineByName(&quot;js&quot;);
        engine.put(&quot;y&quot;, 12);

        if (engine != null) {
            engine.eval(&quot;var x = 1; print(x + y);&quot;);
        }
    }

}
</pre>
<p>W taki oto sposób na naszej konsoli powinno wylądować coś takiego:</p>
<pre class="brush: java;">
[js, rhino, JavaScript, javascript, ECMAScript, ecmascript]
13
</pre>
<p>
<img src="http://blog.dywicki.pl/wp-content/uploads/2008/11/js-swing.jpg" alt="Swing + Java Script" title="Swing + Java Script" width="180" height="80" align="right" /></p>
<p>Możemy również uruchomić plik js. Wystarczy do metody <b>eval</b> przekazać FileReader. Po uruchomieniu kodu który jest niżej powinno pokazać się okienko podobne do tego, które widzicie przy tym akapicie.
</p>
<pre class="brush: java;">package org.code_house.scripting;

import java.io.*;
import javax.script.*;

public class JavaScriptMain {
    public static void main(String[] args) throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName(&quot;js&quot;);
        engine.eval(new FileReader(new File(&quot;print.js&quot;)));
    }
}</pre>
<pre class="brush: jscript;">
frame = new javax.swing.JFrame;
frame.defaultCloseOperation = javax.swing.JFrame.EXIT_ON_CLOSE;
frame.title = &quot;Test&quot;
frame.setSize(new java.awt.Dimension(180, 80));

button = new javax.swing.JButton(&quot;Kliknij mnie&quot;)
button.addActionListener(function(event) {
    print(event.source);
});
frame.add(button);

frame.show()
</pre>
<p>Z dodatkowych języków można podpiąć między innymi <a href="http://php.net"><acronym title="Pre-Hypertext Processing">PHP</acronym></a>, <a href="http://java.sun.com/javafx/">Java FX</a>, <a href="http://groovy.codehaus.org">Groovy</a>, <a href="http://www.beanshell.org/">BeanShell</a> i wiele innych. Aby to zrobić należy ściągnąć ze strony <a href="https://scripting.dev.java.net/">scripting.dev.java.net</a> rozszerzenia (dostępne w sekcji Documents &#038; files) i dodać JAR dla języka którego potrzebujemy do classpath.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/11/24/scripting-inside-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interfejs InitializingBean</title>
		<link>http://blog.dywicki.pl/2008/11/21/interfejs-initializingbean/</link>
		<comments>http://blog.dywicki.pl/2008/11/21/interfejs-initializingbean/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 06:00:27 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Porady]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=235</guid>
		<description><![CDATA[Każdy z obiektów który jest konfigurowany w kontekście Springa ma szansę zweryfikować swój stan tuż po zainicjowaniu wszystkich wartości, które zostały mu przekazane. Wynika to z tego, że czasami obiekty potrafią działać na kilku różnych zasobach i można wstrzyknąć do nich tylko jeden rodzaj tegoż. Czasami po prostu potrzebujemy sprawdzić czy są przekazane wszystkie ustawienia [...]]]></description>
			<content:encoded><![CDATA[<p>Każdy z obiektów który jest konfigurowany w kontekście Springa ma szansę zweryfikować swój stan tuż po zainicjowaniu wszystkich wartości, które zostały mu przekazane. Wynika to z tego, że czasami obiekty potrafią działać na kilku różnych zasobach i można wstrzyknąć do nich tylko jeden rodzaj tegoż. Czasami po prostu potrzebujemy sprawdzić czy są przekazane wszystkie ustawienia konfiguracyjne bądź zainicjować połączenie do bazy danych na podstawie przekazanych parametrów.<br />
<span id="more-235"></span><br />
Mamy wówczas do wyboru dwie metody. Pierwszą z nich jest implementacja interfejsu <a href="http://www.docjar.com/docs/api/org/springframework/beans/factory/InitializingBean.html">org.springframework.beans.factory.InitializingBean</a>. Jeśli wyrzuci ona jakiś wyjątek to Spring wyrzuci wyjątek wyżej i wstrzyma powoływanie kontekstu. Oto przykład:</p>
<pre class="brush: java;">
package org.code_house.samples.spring;

import java.util.Properties;

import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;

public class PropertiesConfiguration implements InitializingBean {

    /**
     * Ustawienia konfiguracyjne.
     */
    private Properties properties;

    public void setProperties(Properties props) {
        this.properties = props;
    }

    public void afterPropertiesSet() throws Exception {
        if (properties == null) {
            throw new BeanInitializationException(&quot;Nie przekazano ustawień &quot;
                +&quot;konfiguracyjnych. Pole properties jest wymagane.&quot;);
        }
    }
}
</pre>
<p>Spring nie wymusza jednak implementowania interfejsu. Jeśli nasz kod już istnieje i jest metoda która weryfikuje stan obiektu możemy użyć atrybutu init-method dla znacznika bean:</p>
<pre class="brush: xml;">
    &lt;bean class=&quot;org.code_house.samples.xml.JaxbConfiguration&quot;
        init-method=&quot;verify&quot;&gt;
        &lt;property name=&quot;source&quot; value=&quot;classpath:data.xml&quot; /&gt;
    &lt;/bean&gt;
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/11/21/interfejs-initializingbean/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Odwołanie do klasy Properties w kontekście springa</title>
		<link>http://blog.dywicki.pl/2008/11/20/odwolanie-do-klasy-properties-w-kontekscie-springa/</link>
		<comments>http://blog.dywicki.pl/2008/11/20/odwolanie-do-klasy-properties-w-kontekscie-springa/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 06:00:46 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Porady]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=233</guid>
		<description><![CDATA[Jako, że nie zawsze mam czas pisać dłuższe noty, a nie wszyscy znają Springa postanowiłem publikować krótkie porady, które mogą kiedyś komuś się przydać. Klasa java.util.Properties to jeden z najprostszych sposobów na odwołanie do prostych ustawień konfiguracyjnych. Składnia pliku properties jest zbliżona do ini i wygląda następująco: nazwa.wlasnosci wartosc inna.nazwa.wlasnosci=costam # to jest komentarz jeszcze.cos.nowego [...]]]></description>
			<content:encoded><![CDATA[<p><em>Jako, że nie zawsze mam czas pisać dłuższe noty, a nie wszyscy znają Springa postanowiłem publikować krótkie porady, które mogą kiedyś komuś się przydać.</em><br />
<span id="more-233"></span><br />
Klasa java.util.Properties to jeden z najprostszych sposobów na odwołanie do prostych ustawień konfiguracyjnych. Składnia pliku properties jest zbliżona do ini i wygląda następująco:</p>
<p>nazwa.wlasnosci wartosc<br />
inna.nazwa.wlasnosci=costam<br />
# to jest komentarz<br />
jeszcze.cos.nowego</p>
<p>Jeśli chcemy przekazać obiekt klasy Properties do jakiegoś innego obiektu możemy skorzystać z poniższej wstawki w kontekście springa:</p>
<pre class="brush: xml;">
&lt;bean class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot;&gt;
    &lt;property name=&quot;location&quot; value=&quot;classpath:corba.properties&quot; /&gt;
&lt;/bean&gt;
</pre>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/11/20/odwolanie-do-klasy-properties-w-kontekscie-springa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Log4j, przejrzyste komunikaty</title>
		<link>http://blog.dywicki.pl/2008/10/15/log4j-przejrzyste-komunikaty/</link>
		<comments>http://blog.dywicki.pl/2008/10/15/log4j-przejrzyste-komunikaty/#comments</comments>
		<pubDate>Wed, 15 Oct 2008 08:00:10 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Framework]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[log4j]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=229</guid>
		<description><![CDATA[Log4j jest najpopularniejszą biblioteką do logowania dla Javy. Została ona wydana już jakiś czas temu i w chwili obecnej rozwija się znacznie wolniej niż kiedyś, warto jednak nadmienić że społeczność wciąż dostarcza nowych możliwości. Może najpierw o samej strukturze log4j. Najważniejsze elementy Log4j ma kilka składowych: Appender Layout Category Dzisiaj skupię się tylko na dwóch [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://logging.apache.org/log4j/">Log4j</a> jest najpopularniejszą biblioteką do logowania dla Javy. Została ona wydana już jakiś czas temu i w chwili obecnej rozwija się znacznie wolniej niż kiedyś, warto jednak nadmienić że społeczność wciąż dostarcza nowych możliwości. Może najpierw o samej strukturze log4j.<br />
<span id="more-229"></span></p>
<h2>Najważniejsze elementy</h2>
<p>Log4j ma kilka składowych:</p>
<ul>
<li>Appender</li>
<li>Layout</li>
<li>Category</li>
</ul>
<p>Dzisiaj skupię się tylko na dwóch pierwszych. Appender jest odpowiedzialny za zapis bądź wysyłanie komunikatów do wybranego miejsca podczas gdy Layout konwertuje wpis do określonego formatu.</p>
<p>Z najciekawszych Appenderów wymienię</p>
<ul>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/RollingFileAppender.html">RollingFileAppender</a> rotuje logi do określonego rozmiaru, po osiągnięciu np 10mb kopiuje stary plik zgodnie ze schematem i zaczyna zapisywać do nowego.</li>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/DailyRollingFileAppender.html">DailyRollingFileAppender</a> zachowuje się podobnie jak wyżej wymieniony z tym, że umożliwia zapis z podziałem na lata, miesiące, dni czy nawet minuty.</li>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/SyslogAppender.html">SyslogAppender</a>, który wysyła komunikaty do <a href="http://pl.wikipedia.org/wiki/Syslog">Sysloga</a></li>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/lf5/LF5Appender.html">LF5Appender</a> wyświetlający logi w okienku tworzonym przy pomocy Swinga.
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/SMTPAppender.html">SMTPAppender</a> wysyłający maile z komunikatami. Jeśli się go źle skonfiguruje gwarantowane zapchanie skrzynki ;-)</li>
<li><a href="http://sourceforge.net/projects/nagiosappender/">NagiosAppender</a> przesyłający komunikaty do <a href="http://www.nagios.org/">Nagiosa</a>, narzędzia służącego do monitorowania.</li>
</ul>
<p>Mając już appender, który wie gdzie zapisywać wypada powiedzieć Log4j też <b>co powinien zapisywać</b>.</p>
<ul>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/HTMLLayout.html">HTMLLayout</a> produkujący tabelę <acronym title="HyperText Markup Language">HTML</acronym></li>
<li><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html">PatternLayout</a> posiadający możliwość określenia &#8220;szablonu&#8221; wpisu.</li>
</ul>
<p>Więcej Layoutów można znaleźć w <a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Layout.html">Javadocu Log4j</a>.</p>
<p>Jako, że zdecydowanie najczęściej używa się PatternLayout dodam parę słów na temat tego co potrafi. We wzorze który będzie później użyty do stworzenia komunikatu możemy używać następujących wyrażeń:</p>
<ul>
<li><b>%c</b> kategoria zdarzenia</li>
<li><b>%C</b> nazwa klasy z której zostało wysłane zdarzenie</li>
<li><b>%d</b> data zdarzenia (przykład: %d{HH:mm:ss,SSS} )</li>
<li><b>%m</b> komunikat wysłany z aplikacji</li>
<li><b>%n</b> separator lini</li>
<li><b>%p</b> priorytet zdarzenia</li>
<li><b>%r</b> ilość milisekund, które zdążyły upłynąć od startu aplikacji</li>
<li><b>%t</b> nazwa wątku z którego zostało wysłane zdarzenie</li>
<li><b>%x</b> kontekst diagnostyczny powiązany z wątkiem (wie ktokolwiek co to znaczy?)</li>
<li><b>%%</b> pojedynczy znak %</li>
<li><b>%M</b> nazwa metody z której zostało wysłane zdarzenie (uwaga, bardzo wolne)</li>
<li><b>%L</b> numer linii z której zdarzenie pochodzi (uwaga, bardzo wolne)</li>
<li><b>%F</b> nazwa pliku z którego pochodzi zdarzenie (uwaga, bardzo wolne)</li>
<li><b>%l</b> informacja o wywołującym zdarzenie (uwaga, bardzo wolne, wskazuje na lokalizację z naszego kodu)</li>
</ul>
<p>Przykłady modyfikatorów:</p>
<ul>
<li><b>%20c</b> dodaje spacje z lewej strony jeśli nazwa kategorii jest krótsza niż 20 znaków</li>
<li><b>%-20c</b> dodaje spacje z prawej strony jeśli nazwa kategorii jest krótsza niż 20 znaków</li>
<li><b>%.30c</b> przycina kategorię pozostawiając ostatnie 30 znaków</li>
<li><b>%20.30c</b> wypełnia z lewej strony nazwę kategorię spacjami do 20 znaków oraz przycina początkowe znaki jeżeli jest dłuższa on 30 znaków</li>
<li><b>%-20.30c</b> analogicznie jak wyżej, z tym że znaki zostaną dodane z prawej strony. Ze swojej strony polecam używanie formatu np %-20.20, co zagwarantuje że element będzie miał zawsze 20 znaków. Jeśli pozostawimy <b>-20.30</b> to element będzie miał 20 znaków jeśli kategoria jest zbyt krótka a 30 gdy będzie za długa</li>
</ul>
<h2>Przykład konfiguracji</h2>
<p>Log4j można konfigurować na kilka sposobów. Programowo, przez plik properties oraz konfigurację <acronym title="eXtensible Markup Language">XML</acronym>. Zdecydowanie najpopularniejszy jest plik properties. Jego użycie jest banalnie proste. Włączamy log4j.jar do tak by był on dostępny w classpathu, a następnie tworzymy plik <em>log4j.properties</em>, który domyślnie jest poszukiwany przez bibliotekę jeśli nie została przekazana żadna konfiguracja. Aby jednak to się stało nasz kod musi spróbować wysłać jakąś wiadomość do Log4j.</p>
<p>log4j.rootLogger DEBUG, out</p>
<p># loggery<br />
log4j.logger.org.springframework INFO<br />
log4j.logger.org.apache.activemq INFO<br />
log4j.logger.org.apache.activemq.spring WARN<br />
log4j.logger.org.apache.servicemix DEBUG, stdout</p>
<p>#appendery<br />
log4j.appender.stdout org.apache.log4j.ConsoleAppender<br />
log4j.appender.stdout.layout org.apache.log4j.PatternLayout<br />
log4j.appender.stdout.layout.ConversionPattern %d{ABSOLUTE} | %-5p | %t | %c | %m%n</p>
<p>log4j.appender.out org.apache.log4j.DailyRollingFileAppender<br />
log4j.appender.out.DatePattern &#8216;-&#8217;yyyy-MM-dd&#8217;.log&#8217;&quot;/&gt;<br />
log4j.appender.out.layout org.apache.log4j.PatternLayout<br />
log4j.appender.out.layout.ConversionPattern %d{ABSOLUTE} | %-5p | %t | %c | %m%n<br />
log4j.appender.out.file E:/fuse-esb/data/log/servicemix</p>
<p>Założenie powyższej konfiguracji jest następujące. Domyślny poziom logowania jest ustawiony na <em>DEBUG</em> a komunikaty są zapisywane do pliku (rootLogger). Zdefiniowane są dwa appendery <em>stdout</em> oraz <em>out</em>. Pierwszy jest użyty tylko dla paczki <em>org.apache.servicemix</em>. Pozostałe loggery mają określony tylko poziom logowania. Pliki z logami będą dzielone na dni, także w lokalizacji <em>E:/fuse-esb/data/log/</em> po 3 dniach działania od 13 do 15 października będziemy mieli 3 pliki:</p>
<ul>
<li>servicemix &#8211; logi z bierzącego dnia</li>
<li>servicemix-2008.10.14.log &#8211; logi z 14 października</li>
<li>servicemix-2008.10.13.log &#8211; logi z 13 października</li>
</ul>
<p>Mam nadzieję że od dzisiaj Log4j będzie Wam drodzy czytelnicy mówił więcej i prościej. Jeśli są jakieś kwestie które pozostają niewyjaśnione &#8211; proszę pytać.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/10/15/log4j-przejrzyste-komunikaty/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Spring &#8220;Commercial&#8221; Source zastępuje Open Source</title>
		<link>http://blog.dywicki.pl/2008/09/28/spring-commercial-source-replaces-open-source/</link>
		<comments>http://blog.dywicki.pl/2008/09/28/spring-commercial-source-replaces-open-source/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 19:59:10 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=227</guid>
		<description><![CDATA[Pamiętam, jak jakiś już czas temu, kiedy pracowałem w PZU dyskutowałem z kolegą na temat Springa. Obaj podziwialiśmy wówczas jego jakość. Chyba wszyscy ludzie którzy mieli styczność z tym narzędziem przyznają, że jest to na prawdę porządnie napisany kawałek kodu. Połączenie bardzo dobrej dokumentacji oraz duża społeczność sprzyjały cały czas Springowi w odnoszeniu kolejnych sukcesów. [...]]]></description>
			<content:encoded><![CDATA[<p>Pamiętam, jak jakiś już czas temu, kiedy pracowałem w <a href="http://pzu.pl">PZU</a> dyskutowałem z kolegą na temat <a href="http://www.springframework.org/">Springa</a>. Obaj podziwialiśmy wówczas jego jakość. Chyba wszyscy ludzie którzy mieli styczność z tym narzędziem przyznają, że jest to na prawdę porządnie napisany kawałek kodu. Połączenie bardzo dobrej dokumentacji oraz duża społeczność sprzyjały cały czas Springowi w odnoszeniu kolejnych sukcesów.</p>
<p>Do dnia 17 września, kiedy to <a href="http://springsource.com">SpringSource</a> ogłosiło zmianę zasad &#8211; i poniekąd <a href="http://www.springsource.com/node/558">konieczność wykupywania subskrypcji</a>. Wiadomość ta zaiste zelektryzowała społeczność.<br />
<span id="more-227"></span><br />
Trudno poniekąd dziwić się zmianom w SpringSource ponieważ w <a href="http://www.springsource.com/node/393">czerwcu tego roku</a> do grona właścicieli dołączyła kolejna spółka typu <a href="http://pl.wikipedia.org/wiki/Venture_capital">venture capital</a>. Chyba podobnie tak jak w przypadku przejęcia BEA przez Oracle konieczne było odbicie sobie kosztów podnosząc ceny. Póki co Spring Application Platform nie ma wielkiego przebicia na rynku serwerów, ponieważ jest (chyba?) rozwiązaniem zbyt rewolucyjnym, na wsparcie wielu klientów się nie decydowało, szkolenia organizuje nie tylko SpringSource ale też cała masa innych firm, więc de-facto źródeł dochodów producent Springa nie miał wielu. Po prostu ilość użytkowników tego frameworka nie przekładała się w widoczny sposób na zasobność kiesy. Inwestorzy wykorzystując popularność narzędzia chcą skierować wielki strumień pieniędzy prosto do swojej kieszeni. Oczywiście pieniądze te nie będą przeznaczone tylko na honoraria ale również na dalszą ekspansję na rynku. Już teraz wiadomo, że Spring 3.0 będzie zgodny ze specyfikacją EJB 3.1, co zwiastuje koniec wojny <a href="http://www.ryandelaplante.com/rdelaplante/entry/end_of_spring_vs_ejb">EJB vs Spring</a>. Pod w/w linkiem jest też kilka komentarzy na temat zmian:</p>
<blockquote><p>To smutne, ale kończę wierzyć marzyć, pora spojrzeć na wszystko trzeźwo, standardy nie są złe, są oparte na idei Springa, dzięki Bogu.</p></blockquote>
<blockquote><p>Nie będę płacił myta za korzystanie z kontenera DI. Jeśli będię potrzebował portfolio SpringSource pomyślę czy zapłacić, ale żebym musiał płacić za sam kontener DI? Nie ma mowy, wolę poczekać na &#8220;STANDARD&#8221; EJB 3.1 albo przesiąść się na Guice czy nawet kontener DI z Tapestry 5</p></blockquote>
<blockquote><p>Jak ktoś już powiedział kontener DI Springa nie jest jakimś nadzwyczajnym wynalazkiem, może powinniśmy zacząć używać Guice bądź nadchodzącego EJB 3.1?</p></blockquote>
<blockquote><p>Pi** SpringSource!! TO wszystko co powiem. Jesteśmy społecznością i to my pomogliśmy wyrosnąć Spinrgowi a traz oni wbijają nam nóż w plecy. Witam EJB 3.1 jako standard i myślę, że powinienem zacząć poważnie myśleć o Seamie bądź innej alternatywie, może Guice? SpringSource tylko się pogrąża. Panie Rod, miałem Cię za naszego zbawiciela ale okazałeś się takim samym du*** jak wszystko w Open Source</p></blockquote>
<blockquote><p>Niestety, sterowany marketingiem szum (&#8220;the de facto standard in enterprise Java&#8221;) wokół Springa w końcu dobiegł końca. Świetnie!</p></blockquote>
<p>Więcej opinii znajdziecie jeszcze na <a href="http://www.theserverside.com/news/thread.tss?thread_id=50727">The Server Side: New Spring maintenance policy</a>. </p>
<h2>Moim skromnym zdaniem</h2>
<p>Nie pisał bym o tym wszystkim gdybym nie miał na to własnego zdania. Oczywiście szkoda, że losy Springa teraz idą w kierunku niezbyt sprzyjającym dla większości z nas. Z drugiej jednak strony gwarancja łatania dziur w celu zapewnienia stabilności działania aplikacji produkcyjnych jest kusząca i odciąża developerów. Jakkolwiek nie ma tu już równowagi, ponieważ wg. nowych założeń albo płacisz i masz wszystkie poprawki albo nie płacisz i masz tylko główne wydania (major releases). Czy znajdzie się ktoś kto zacznie rozwijać alternatywę dla Springa?</p>
<p>Nie chodzi mi tu o sam kontener DI bo zdaję sobie doskonale sprawę z tego, że Spring już od bardzo dawna przestał być tylko nośnikiem DI. Masa modułów &#8211; wspierających pracę z bazami danych, zarządzanie transakcjami, moduły do JMS, web services, EJB czy nawet integracji. To wszystko miało swoich nabywców. Osobiście zmiana ta średnio mi odpowiada, ponieważ dosłownie zmusza do wykupienia wsparcia (wyobraża sobie ktoś korzystanie ze Springa tylko w wersjach 2.5, 2.0, 1.2, 1.1, 1.0?). W tej chwili nie ma żadnego zastępnika dla Springa i jego inwestorzy doskonale sobie z tego zdają sprawę. Po wejściu EJB 3.1 wszystko się rozmyje, a póki co jest bardzo dobra okazja do łowienia klientów.</p>
<p>Model licencjonowania w przypadku <a href="http://servicemix.apache.org">Service Mixa</a> jest jasny &#8211; jest za darmo. Ma dokumentację jaką ma, ma dziury, są z nim oczywiście problemy, ale <a href="http://open.iona.com">Iona</a> na jego bazie dostarcza produkt i wsparcie do niego. Nikt nie ma obowiązku korzystania z usług Iony, w ogóle nie musi o jej istnieniu wiedzieć. Jeśli ktoś będzie potrzebował wsparcia to je i tak przecież kupi!</p>
<p>Różnicą i to znaczną są wyraźne ambicje SpringSource by walczyć o miano pretendenta na rynku serwerów z IBM i BEA. Problem w tym, że w tym momencie jest on pozbawiony silnego argumentu, jakim był kod Open Source, w obecnej formie jest to po prostu wypaczenie idei otwierania kodu. Społeczność zdaje się, że jest zniesmaczona, ale cóż zrobić.</p>
<p><b>Za jakość się płaci i nauczka jest taka że w przypadku Springa przychodzi nam płacić po znacznie dłuższym czasie.</b></p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/09/28/spring-commercial-source-replaces-open-source/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Budowanie klienta usługi sieciowej w oparciu o Apache CXF</title>
		<link>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/</link>
		<comments>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 07:28:27 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[CXF]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=223</guid>
		<description><![CDATA[W nawiązaniu do poprzedniej noty o CXFie, którą napisałem jakiś czas temu, gonię aby uzupełnić brak konfiguracji klienta. Sam proces jest bardzo zbliżony do tworzenia klienta w oparciu o XFire. Nie jest wymagana duża ilość kodu Javy, a w zasadzie tylko dwa pliki XML (client.xml, myservice.xml). Pierwszy z nich odpowiada za wczytanie wymaganych rozszerzeń CXFa [...]]]></description>
			<content:encoded><![CDATA[<p>W nawiązaniu do <a href="http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/">poprzedniej noty o CXFie</a>, którą napisałem jakiś czas temu, gonię aby uzupełnić brak konfiguracji klienta. Sam proces jest bardzo zbliżony do tworzenia klienta w oparciu o XFire. Nie jest wymagana duża ilość kodu Javy, a w zasadzie tylko dwa pliki <acronym title="eXtensible Markup Language">XML</acronym> (client.xml, <em>myservice.xml</em>).</p>
<p>Pierwszy z nich odpowiada za wczytanie wymaganych rozszerzeń CXFa oraz definicję bazowej konfiguracji fabryki z interceptorami. W interceptorach możemy skonfigurować logowanie, obsługę załączników czy standardów WS-Security etc. Wszystkie te ustawienia będą dziedziczone, a fabryki docelowych usług będą dodawać tylko adres, do odpytywania. Na koniec bean klienta będzie miał określony <strong>autowire</strong> by nie przekazywać mu wszystkich własności.<br />
<span id="more-223"></span></p>
<p>Oto najważniejsze wstawki kodu oraz ich opis:</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
        &lt;artifactId&gt;parent&lt;/artifactId&gt;
        &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/parent&gt;

    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;client&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

    &lt;name&gt;Code House.Org - CXF - Client&lt;/name&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;log4j&lt;/groupId&gt;
            &lt;artifactId&gt;log4j&lt;/artifactId&gt;
            &lt;version&gt;1.2.12&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;contract&lt;/artifactId&gt;
            &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-transports-http-jetty&lt;/artifactId&gt;
            &lt;version&gt;${code-house.cxf.version}&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
            &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-test&lt;/artifactId&gt;
            &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-context&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;

&lt;/project&gt;</pre>
<p>Deskryptor nie jest zbyt złożony, istotny jest tylko kawałek z kontraktem, który jak wskazuje nazwa jest definicją używanych typów:</p>
<pre class="brush: xml;">&lt;dependency&gt;
    &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;contract&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>Teraz kolej na jedyną wstawkę Javy, która się pojawia w projekcie. Jest to zwykły bean, który będzie miał później wstrzykiwane obiekty pośredniczące w wywoływaniu usług.</p>
<pre class="brush: java;">package org.code_house.cxf.client;

import org.code_house.services.maven.MavenArtifactType;

/**
 * Klient usług Code-House.
 *
 * @author Łukasz Dywicki &lt;a href=&quot;splatch@code-house.org&quot;&gt;email&lt;/a&gt;
 *
 * $Id$
 */
public class Client {

    /**
     * Usługa do obsługi wyszukiwania artefaktów Mavena.
     */
    private MavenArtifactType maven;

    /**
     * Pobranie wartości pola maven.
     *
     * @return Wartość maven.
     */
    public MavenArtifactType getMaven() {
        return maven;
    }

    /**
     * Ustawienie wartości pola maven.
     *
     * @param maven Nowa wartość pola maven.
     */
    public void setMaven(MavenArtifactType maven) {
        this.maven = maven;
    }
}</pre>
<p>Resztę magii załatwia Spring:</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
    xsi:schemaLocation=&quot;

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

http://www.springframework.org/schema/context/spring-context.xsd

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

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

    &quot;&gt;
    &lt;!--  Konfiguracja placeholderów (znaczy wstawek ${}) --&gt;
    &lt;context:property-placeholder location=&quot;classpath:client.properties&quot; /&gt;

    &lt;!-- Importy rzeczy koniecznych do pracy CXF --&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf.xml&quot; /&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-soap.xml&quot; /&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-http-jetty.xml&quot; /&gt;

    &lt;!-- Konfiguracja poszczególnych usług wstrzykiwanych do klienta --&gt;
    &lt;import resource=&quot;classpath:services/*.xml&quot; /&gt;

    &lt;!-- Bean zawierający referencje do wygenerowanych klientów usług --&gt;
    &lt;bean id=&quot;client&quot; class=&quot;org.code_.housecxf.client.Client&quot; autowire=&quot;autodetect&quot; /&gt;

    &lt;!-- Bazowa konfiguracja fabryk - obiektów tworzących stuby klientów w runtime --&gt;
    &lt;bean id=&quot;baseClientFactory&quot; abstract=&quot;true&quot;
        class=&quot;org.apache.cxf.jaxws.JaxWsProxyFactoryBean&quot;&gt;
       &lt;property name=&quot;username&quot; value=&quot;${org.code_house.cxf.user}&quot; /&gt;
        &lt;property name=&quot;password&quot; value=&quot;${org.code_house.cxf.password}&quot; /&gt;
        &lt;property name=&quot;inInterceptors&quot;&gt;
            &lt;list&gt;
                &lt;ref bean=&quot;logIn&quot; /&gt;
            &lt;/list&gt;
        &lt;/property&gt;
        &lt;property name=&quot;outInterceptors&quot;&gt;
            &lt;list&gt;
                &lt;ref bean=&quot;logOut&quot; /&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;

    &lt;!-- Loggery dla CXF --&gt;
    &lt;bean id=&quot;logIn&quot; class=&quot;org.apache.cxf.interceptor.LoggingInInterceptor&quot; /&gt;
    &lt;bean id=&quot;logOut&quot; class=&quot;org.apache.cxf.interceptor.LoggingOutInterceptor&quot; /&gt;

&lt;/beans&gt;</pre>
<p>Zgodnie ze wstawką w linii 20 konieczna jest jeszcze konfiguracja usługi. Sztuczka polega na użyciu części konfiguracji zdefiniowanej wcześniej &#8211; baseClientFactory.</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;

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

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

    &quot;&gt;

    &lt;!-- Konfiguracja stuba dla usługi wyszukiwania artefaktów --&gt;
    &lt;bean id=&quot;mavenService&quot; class=&quot;org.code_house.services.maven.MavenArtifactType&quot;
        factory-bean=&quot;mavenServiceFactory&quot; factory-method=&quot;create&quot; /&gt;

    &lt;!-- Fabryka usługi wyszukującej --&gt;
    &lt;bean id=&quot;mavenServiceFactory&quot; parent=&quot;baseClientFactory&quot;&gt;
        &lt;!-- jedyne parametry jakich potrzebujemy --&gt;
        &lt;property name=&quot;serviceClass&quot;
            value=&quot;org.code_house.services.maven.MavenArtifactType&quot; /&gt;
        &lt;property name=&quot;address&quot; value=&quot;${org.code_house.cxf.service.maven}&quot; /&gt;
    &lt;/bean&gt;

&lt;/beans&gt;</pre>
<p>Ustawienia, które mogą ulec zmianie, to znaczy użytkownik, hasło oraz adres usługi są wyodrębnione do pliku client.properties:</p>
<p># Placeholdery dla kontekstow springa<br />
# Adresy uslug<br />
server.port = 8080<br />
host = localhost<br />
org.code_house.cxf.service.maven http://${host}:${server.port}/webapp/services/maven</p>
<p># Autoryzacja<br />
org.code_house.cxf.user<br />
org.code_house.cxf.password</p>
<p>No i na koniec opcjonalny test, który odpytuje usługę:</p>
<pre class="brush: java;">
package org.code_house.cxf.client;
import org.code_house.services.maven.definition.ArtifactInfo;
import org.code_house.services.maven.types.FindArtifactRequest;
import org.code_house.services.maven.types.FindArtifactRespose;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

/**
 * Proste wywołanie klasy klienta.
 *
 * @author Łukasz Dywicki &lt;a href=&quot;ldywicki@pocztowy.pl&quot;&gt;email&lt;/a&gt;
 *
 * $Id$
 */
public class MainTest extends AbstractDependencyInjectionSpringContextTests {

    /**
     * Wstrzyknięty klient.
     */
    private Client client;

    @Override
    protected String[] getConfigLocations() {
        return new String[] {&quot;classpath:client.xml&quot;};
    }

    public void testOne() {
        FindArtifactRequest request = new FindArtifactRequest();
        ArtifactInfo artifact = new ArtifactInfo();
        artifact.setGroupId(&quot;org.code_house.cxf&quot;);
        artifact.setArtifactId(&quot;contract&quot;);
        request.setQuery(artifact);

        FindArtifactRespose respose = client.getMaven().findArtifact(request);
        System.out.println(respose.getDownloadURL());
    }

    /**
     * Ustawienie wartości pola client.
     *
     * @param client Nowa wartość pola client.
     */
    public void setClient(Client client) {
        this.client = client;
    }

}</pre>
<p>To by było na tyle. Cały działający kod projektu jest już zamieszczony przy <a href="http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/">poprzedniej nocie</a>, paczka ze wszystkimi listingami <a href="http://media.dywicki.pl/blog/cxf/cxf.zip">gotowa do pobrania</a>.</p>
<p>Teraz chyba pora zacząć opisywać mechanizmy Springa. :)</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

