<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns: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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Michał Mech - W stronę Java</title>
	
	<link>http://blog.michalmech.pl</link>
	<description>Zapiski programisty</description>
	<lastBuildDate>Wed, 03 Feb 2010 09:28:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/MichalMech-WStroneJ2EE" /><feedburner:info uri="michalmech-wstronej2ee" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Usługi sieciowe – szybki efekt dzięki CXF</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/uw8718CqpBE/</link>
		<comments>http://blog.michalmech.pl/index.php/2010/02/02/uslugi-sieciowe-szybki-efekt-dzieki-cxf/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 23:52:48 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[CXF]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[WSDL]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=253</guid>
		<description><![CDATA[Mój nauczyciel matematyki zwykł mówić, że &#8220;dobry matematyk to leniwy matematyk&#8221;. Zwykł tak komentować karkołomne metody obliczeń stosowane w sytuacjach kiedy można coś zrobić prościej. Lubię tę zasadę stosować również w odniesieniu do programowania.
Kiedy przyszło mi niedawno stworzyć usługi sieciowe (ang. Web Services) w Javie pomyślałem o Apache CXF. CXF jest szkieletem (ang. framework) pomagającym [...]]]></description>
			<content:encoded><![CDATA[<p>Mój nauczyciel matematyki zwykł mówić, że <em>&#8220;dobry matematyk to leniwy matematyk&#8221;</em>. Zwykł tak komentować karkołomne metody obliczeń stosowane w sytuacjach kiedy można coś zrobić prościej. Lubię tę zasadę stosować również w odniesieniu do programowania.</p>
<p>Kiedy przyszło mi niedawno stworzyć usługi sieciowe (ang. <em>Web Services</em>) w <a title="Java" href="http://java.sun.com">Javie</a> pomyślałem o <a title="Apache CXF: An Open Source Service Framework" href="http://cxf.apache.org">Apache CXF</a>. CXF jest szkieletem (ang. <em>framework</em>) pomagającym budować usługi korzystające z <abbr title="Application Programming Interface">API</abbr> takich jak <a title="Java API for XML Web Services" href="https://jax-ws.dev.java.net">JAX-WS</a> i zdolne do komunikacji używając protokołów <abbr title="Simple Object Access Protocol">SOAP</abbr>, <abbr title="Representational State Transfer">REST</abbr> czy <abbr title="Hypertext Transfer Protocol">HTTP</abbr>.</p>
<p><span id="more-253"></span></p>
<h2>Kontrakt</h2>
<p>Przy tworzeniu usług sieciowych można stosować dwa podejścia:</p>
<ol>
<li><abbr title="Web Services Description Language">WSDL</abbr> first &#8211; najpierw tworzymy kontrakt, jakim jest plik <abbr title="Web Services Description Language">WSDL</abbr> opisujący nasze usługi a następnie przechodzimy do implementacji;</li>
<li>Implementation first &#8211; najpierw implementujemy logikę a później wystawiamy ją w formie usług sieciowych i generujemy <abbr title="Web Services Description Language">WSDL</abbr>;</li>
</ol>
<p>Ja osobiście lubię zabrać się do pracy kiedy wiem co mam zrobić, ot takie dziwactwo. Stąd zakładam sytuację kiedy najpierw definiujemy kontrakt jaki realizowała będzie moja usługa sieciowa.<br />
Dla zaprezentowania CXF utworzę bardzo prostą usługę sieciową, która będzie odpowiadała na zadane pytanie. Zakładam otrzymać ciąg znaków i ciąg znaków odeślę w odpowiedzi (taka pogawędka).</p>
<p>Kontrakt <abbr title="Web Services Description Language">WSDL</abbr> mógłby wyglądać tak (<em>talk.wsdl</em>):</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;
&lt;wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://michalmech.pl/service/talk/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	targetNamespace="http://michalmech.pl/service/talk/" name="talk"&gt;

	&lt;wsdl:message name="Ask"&gt;
		&lt;wsdl:part name="question" type="xsd:string" /&gt;
	&lt;/wsdl:message&gt;

	&lt;wsdl:message name="AskResponse"&gt;
		&lt;wsdl:part name="answer" type="xsd:string" /&gt;
	&lt;/wsdl:message&gt;

	&lt;wsdl:portType name="talk"&gt;
		&lt;wsdl:operation name="Ask"&gt;
			&lt;wsdl:input message="tns:Ask" /&gt;
			&lt;wsdl:output message="tns:AskResponse" /&gt;
		&lt;/wsdl:operation&gt;
	&lt;/wsdl:portType&gt;

	&lt;wsdl:binding name="talkSOAP" type="tns:talk"&gt;
		&lt;soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /&gt;
		&lt;wsdl:operation name="Ask"&gt;
			&lt;soap:operation soapAction="http://michalmech.pl/service/talk/ask" /&gt;
			&lt;wsdl:input&gt;
				&lt;soap:body use="literal" /&gt;
			&lt;/wsdl:input&gt;
			&lt;wsdl:output&gt;
				&lt;soap:body use="literal" /&gt;
			&lt;/wsdl:output&gt;
		&lt;/wsdl:operation&gt;
	&lt;/wsdl:binding&gt;

	&lt;wsdl:service name="TalkOperations"&gt;
		&lt;wsdl:port binding="tns:talkSOAP" name="talkSOAP"&gt;
			&lt;soap:address location="http://michalmech.pl" /&gt;
		&lt;/wsdl:port&gt;
	&lt;/wsdl:service&gt;
&lt;/wsdl:definitions&gt;</pre>
<h2>Aplikacja</h2>
<p>Teraz przyda się <a title="Apache Maven" href="http://maven.apache.org">Maven</a>, którym utworzymy szybko projekt aplikacji internetowej i zajmiemy się zależnościami. Sam Maven nie jest przedmiotem tego wpisu więc wspomnę tylko, że zaczynamy od polecenia:</p>
<pre class="brush: bash; gutter: false;">mvn archetype:generate</pre>
<p>Po utworzeniu projektu plik <em>talk.wsdl</em> umieszczamy w zasobach naszego projektu: <em>src/main/resources/</em><br />
Oto kompletny plik <abbr title="Project Object Model">POM</abbr>, który zawiera zależności oraz informacje o budowaniu projektu:</p>
<pre class="brush: xml;">&lt;project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;

	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
	&lt;groupId&gt;pl.michalmech.cxfdemo&lt;/groupId&gt;
	&lt;artifactId&gt;wsdl-first&lt;/artifactId&gt;
	&lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
	&lt;packaging&gt;war&lt;/packaging&gt;

	&lt;name&gt;CXF Demo - WSDL-first&lt;/name&gt;

	&lt;dependencies&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-rt-core&lt;/artifactId&gt;
			&lt;version&gt;2.2&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;version&gt;2.2&lt;/version&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;version&gt;2.2&lt;/version&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
			&lt;artifactId&gt;cxf-common-utilities&lt;/artifactId&gt;
			&lt;version&gt;2.2&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;3.0.0.RELEASE&lt;/version&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework&lt;/groupId&gt;
			&lt;artifactId&gt;spring-beans&lt;/artifactId&gt;
			&lt;version&gt;3.0.0.RELEASE&lt;/version&gt;
		&lt;/dependency&gt;
	&lt;/dependencies&gt;
	&lt;build&gt;
		&lt;plugins&gt;
			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
				&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
				&lt;configuration&gt;
					&lt;source&gt;1.5&lt;/source&gt;
					&lt;target&gt;1.5&lt;/target&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;

			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
				&lt;artifactId&gt;cxf-codegen-plugin&lt;/artifactId&gt;
				&lt;version&gt;2.1.4&lt;/version&gt;
				&lt;executions&gt;
					&lt;execution&gt;
						&lt;id&gt;generate-sources&lt;/id&gt;
						&lt;phase&gt;generate-sources&lt;/phase&gt;
						&lt;configuration&gt;
							&lt;sourceRoot&gt;${basedir}/src/main/java&lt;/sourceRoot&gt;
							&lt;wsdlOptions&gt;
								&lt;wsdlOption&gt;
									&lt;wsdl&gt;src/main/resources/talk.wsdl&lt;/wsdl&gt;
								&lt;/wsdlOption&gt;
							&lt;/wsdlOptions&gt;
						&lt;/configuration&gt;
						&lt;goals&gt;
							&lt;goal&gt;wsdl2java&lt;/goal&gt;
						&lt;/goals&gt;
					&lt;/execution&gt;
				&lt;/executions&gt;
			&lt;/plugin&gt;

			&lt;plugin&gt;
				&lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
				&lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
				&lt;version&gt;6.1.22&lt;/version&gt;
			&lt;/plugin&gt;
		&lt;/plugins&gt;
	&lt;/build&gt;
&lt;/project&gt;</pre>
<p>Widzimy zależności od pakietów CXF oraz pluginu CXF Codegen, który odwali za nas trochę roboty. <a title="Spring Framework" href="http://www.springsource.org">Spring Framework</a> dostarczy nam swój kontener <abbr title="Inversion of Control">IoC</abbr> a serwer <a title="Jetty WebServer" href="http://www.eclipse.org/jetty/">Jetty</a> przyda się do testowania aplikacji.</p>
<p>No dobrze czas na magię. Wspominałem o leniach no to wypadałoby teraz osiągnąć coś niewielkim nakładem pracy, co niniejszym czynimy wykonując polecenia:</p>
<pre class="brush: bash; gutter: false;">mvn generate-sources
mvn eclipse:clean eclipse:eclipse</pre>
<p>Pierwsze polecenie wygeneruje nam kod języka Java na podstawie kontraktu <abbr title="Web Services Description Language">WSDL</abbr>. Drugie utworzy pliki konfiguracyjne potrzebne do importu projektu do mojego ulubionego <abbr title="Integrated Development Environment">IDE</abbr>. Na obecnym etapie projekt powinien wyglądać tak:</p>
<p style="text-align: center;"><a href="http://blog.michalmech.pl/wp-content/uploads/2010/02/wsdl-first-project.png"><img class="aligncenter size-thumbnail wp-image-259" title="Projekt WSDL-first" src="http://blog.michalmech.pl/wp-content/uploads/2010/02/wsdl-first-project-150x122.png" alt="" width="150" height="122" /></a></p>
<p>Zajmijmy się teraz implementacją naszej usługi. Nie będzie zbyt wyszukana:</p>
<pre class="brush: java;">package pl.michalmech.service;

import pl.michalmech.service.talk.Talk;

public class TalkImpl implements Talk {

	public String ask(String question) {
		return "I don't know answer for \"" + question + "\" question.";
	}
}</pre>
<p>Aby nasza usługa sieciowa działała przyda nam się zdefiniowanie kontekstu aplikacji (<em>applicationContext.xml</em>) oraz deskryptora rozmieszczenia (<em>web.xml</em>):</p>
<p><em>src/main/webapp/WEB-INF/applicationContext.xml</em></p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:cxf="http://cxf.apache.org/core"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
		http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
		http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"&gt;

	&lt;import resource="classpath:META-INF/cxf/cxf.xml" /&gt;
	&lt;import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /&gt;
	&lt;import resource="classpath:META-INF/cxf/cxf-servlet.xml" /&gt;

	&lt;jaxws:endpoint implementor="pl.michalmech.service.TalkImpl" address="/service/talk" /&gt;
&lt;/beans&gt;</pre>
<p><em>src/main/webapp/WEB-INF/web.xml</em></p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;

	&lt;context-param&gt;
		&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
		&lt;param-value&gt;WEB-INF/*Context.xml&lt;/param-value&gt;
	&lt;/context-param&gt;

	&lt;listener&gt;
		&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
	&lt;/listener&gt;

	&lt;servlet&gt;
		&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
		&lt;servlet-class&gt;org.apache.cxf.transport.servlet.CXFServlet&lt;/servlet-class&gt;
		&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
	&lt;/servlet&gt;

	&lt;servlet-mapping&gt;
		&lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt;
		&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
	&lt;/servlet-mapping&gt;
&lt;/web-app&gt;</pre>
<p>I znów nie musimy martwić się o servlet ponieważ o wszystko zadba za nas CXF.</p>
<h2>Uruchomienie</h2>
<p>Teraz przyda nam się Jetty. Uruchamiamy aplikację poleceniem:</p>
<pre class="brush: bash; gutter: false;">mvn jetty:run</pre>
<p>oraz sprawdzamy rezultaty w przeglądarce. Wyniki działania aplikacji powinny być następujące:<br />
<em>http://localhost:8080/wsdl-first</em><br />
<a href="http://blog.michalmech.pl/wp-content/uploads/2010/02/WSDL-first-project-result.png"><img class="aligncenter size-thumbnail wp-image-264" title="Projekt WSDL-first - wynik" src="http://blog.michalmech.pl/wp-content/uploads/2010/02/WSDL-first-project-result-150x42.png" alt="" width="150" height="42" /></a><br />
<em>http://localhost:8080/wsdl-first/service/talk?wsdl</em><br />
<a href="http://blog.michalmech.pl/wp-content/uploads/2010/02/WSDL-first-project-result2.png"><img class="aligncenter size-thumbnail wp-image-265" title="Projekt WSDL-first - wynik (2)" src="http://blog.michalmech.pl/wp-content/uploads/2010/02/WSDL-first-project-result2-150x116.png" alt="" width="150" height="116" /></a>To wszystko co potrzebne było do uruchomienia prostej usługi sieciowej. Przykład jest trywialny i dotyka ledwie czubka góry lodowej zarówno możliwości CXF jak i zastosowań zamych usług sieciowych więc zachęcam do zabawy.</p>
<p>Do pobrania: <a href="http://blog.michalmech.pl/wp-content/uploads/2010/02/wsdl-first.zip">wsdl-first.zip</a></p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/uw8718CqpBE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2010/02/02/uslugi-sieciowe-szybki-efekt-dzieki-cxf/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2010/02/02/uslugi-sieciowe-szybki-efekt-dzieki-cxf/</feedburner:origLink></item>
		<item>
		<title>Spring, JAXB oraz Maven – czyli łatwe i przyjemne budowanie oraz konfigurowanie aplikacji</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/ww7nb489aaM/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/09/30/spring-jaxb-oraz-maven-czyli-latwe-i-przyjemne-budowanie-oraz-konfigurowanie-aplikacji/#comments</comments>
		<pubDate>Tue, 29 Sep 2009 22:19:00 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[JAXB]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XSD]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=183</guid>
		<description><![CDATA[Jakiś czas temu stanąłem przed koniecznością napisania aplikacji, która miała mieć możliwość konfigurowania z zewnętrznego pliku XML. Wybór formatu XML był podyktowany złożoną strukturą informacji, które należało wczytać. Aplikacja była oparta o szkielet Spring a zależnościami i budowaniem zajmował się Maven. Pozostał wybór narzędzia, które przeniesie mi w wygodny sposób dane z pliku XML do [...]]]></description>
			<content:encoded><![CDATA[<p>Jakiś czas temu stanąłem przed koniecznością napisania aplikacji, która miała mieć możliwość konfigurowania z zewnętrznego pliku <abbr title="Extensible Markup Language">XML</abbr>. Wybór formatu <abbr title="Extensible Markup Language">XML</abbr> był podyktowany złożoną strukturą informacji, które należało wczytać. Aplikacja była oparta o szkielet <a title="Spring Framework" href="http://www.springsource.org">Spring</a> a zależnościami i budowaniem zajmował się <a title="Apache Maven" href="http://maven.apache.org">Maven</a>. Pozostał wybór narzędzia, które przeniesie mi w wygodny sposób dane z pliku <abbr title="Extensible Markup Language">XML</abbr> do aplikacji. Wybór padł na <a title="Java Architecture for XML Binding" href="https://jaxb.dev.java.net">JAXB</a> &#8211; Java Architecture for XML Binding. <abbr title="Java Architecture for XML Binding">JAXB</abbr> to technologia pozwalająca wygenerować klasy języka <a title="Java" href="http://java.sun.com">Java</a>, które pomogą nam odwzorować plik <abbr title="Extensible Markup Language">XML</abbr> na obiekty.</p>
<p>Nie będę się skupiał nadto na opisie każdego z wymienionych narzędzi lecz skupię się raczej na pokazaniu jak zaprząc je razem do działania.</p>
<p><span id="more-183"></span></p>
<h3>Przykładowa aplikacja</h3>
<p>Zacznę od przygotowania niewielkiej aplikacji testowej. W tym celu w konsoli wpisujemy:</p>
<pre class="brush: plain; gutter: false;">mvn archetype:generate</pre>
<p>Powyższe polecenie zainicjuje kreator, w którym wybieramy <strong>15</strong> (maven-archetype-quickstart) a później podajemy szczegóły. Ja podałem:</p>
<pre class="brush: plain; gutter: false;">Define value for groupId: : pl.michalmech
Define value for artifactId: : jaxb-example
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  pl.michalmech: :</pre>
<p>Aplikacja testowa jest gotowa a po wykonaniu polecenia:</p>
<pre class="brush: plain; gutter: false;">mvn eclipse:eclipse</pre>
<p>można wygodnie zaimportować ją do <a title="Eclipse IDE" href="http://www.eclipse.org">Eclipse</a>&#8216;a.</p>
<p>Kolejnym krokiem jest konfiguracja zależności aplikacji w pliku <a title="Project Object Model" href="http://maven.apache.org/pom.html">POM</a>. Jedyne czego potrzebujemy to <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> dlatego wyrzuciłem zależność od <a title="JUnit" href="http://www.junit.org">JUnit</a>&#8216;a oraz folder <em>src/test</em>.</p>
<pre class="brush: xml;">&lt;project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;pl.michalmech&lt;/groupId&gt;
    &lt;artifactId&gt;jaxb-example&lt;/artifactId&gt;
    &lt;packaging&gt;jar&lt;/packaging&gt;
    &lt;name&gt;jaxb-example&lt;/name&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring&lt;/artifactId&gt;
            &lt;version&gt;2.5.6.SEC01&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/project&gt;</pre>
<p>Teraz czas na skonfigurowanie i wczytanie kontekstu Springa. Na razie pustego ale niebawem wypełnimy go <a href="http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-definition">ziarnami</a>. Najpierw przygotowujemy plik <em>src/main/resources/context.xml</em>:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&gt;

&lt;/beans&gt;</pre>
<p>Następnie zmieniamy klasę <code>App</code>:</p>
<pre class="brush: java;">public class App {
    public static void main(String[] args) {
        @SuppressWarnings("unused")
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
    }
}</pre>
<p>Należy pamiętać o</p>
<pre class="brush: plain; gutter: false;">mvn eclipse:eclipse</pre>
<p>żeby Eclipse odświeżył biblioteki po zmianie pliku <em>pom.xml</em>. Próba uruchomiania (<a href="http://blog.michalmech.pl/wp-content/uploads/2009/09/Run-as-Java-Application.png"><img class="alignnone size-full wp-image-195" style="border: none; vertical-align: middle;" title="Run as Java Application" src="http://blog.michalmech.pl/wp-content/uploads/2009/09/Run-as-Java-Application.png" alt="Run as Java Application" width="14" height="14" /></a>) aplikacji nie powinna sprawić problemu.</p>
<h3>Schemat <abbr title="Extensible Markup Language">XML</abbr></h3>
<p>Założyłem, że aplikacja ma korzystać z klas wygenerowanych za pomocą <abbr title="Java Architecture for XML Binding">JAXB</abbr>&#8216;a. Potrzebujemy więc schematu <abbr title="Extensible Markup Language">XML</abbr>, na podstawie którego klasy zostaną wygenerowane. Dla przykładu skorzystamy z takiego schematu:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://michalmech.pl/jaxb-example"
    xmlns:tns="http://michalmech.pl/jaxb-example"
    elementFormDefault="qualified"&gt;

    &lt;element name="config"&gt;
        &lt;complexType&gt;
            &lt;sequence&gt;
                &lt;element name="parameters"&gt;
                    &lt;complexType&gt;
                        &lt;sequence minOccurs="0" maxOccurs="unbounded"&gt;
                            &lt;element name="parameter" type="tns:parameter" /&gt;
                        &lt;/sequence&gt;
                    &lt;/complexType&gt;
                &lt;/element&gt;
                &lt;element name="cities"&gt;
                    &lt;complexType&gt;
                        &lt;sequence minOccurs="0" maxOccurs="unbounded"&gt;
                            &lt;element name="city" type="tns:city" /&gt;
                        &lt;/sequence&gt;
                    &lt;/complexType&gt;
                &lt;/element&gt;
            &lt;/sequence&gt;
        &lt;/complexType&gt;
    &lt;/element&gt;

    &lt;complexType name="parameter"&gt;
        &lt;attribute name="name" use="required" type="string" /&gt;
        &lt;attribute name="value" use="required" type="string" /&gt;
    &lt;/complexType&gt;

    &lt;complexType name="city"&gt;
        &lt;attribute name="name" use="required" type="string" /&gt;
        &lt;attribute name="postCode" use="required" type="tns:postCode" /&gt;
    &lt;/complexType&gt;

    &lt;simpleType name="postCode"&gt;
        &lt;restriction base="string"&gt;
            &lt;pattern value="[0-9]{2}-[0-9]{3}" /&gt;
        &lt;/restriction&gt;
    &lt;/simpleType&gt;
&lt;/schema&gt;</pre>
<p>Zapisujemy plik pod nazwą <em>config.xsd</em> w <em>src/main/resources</em>. W dużym skrócie powyższy schemat opisuje plik <abbr title="Extensible Markup Language">XML</abbr>, w którym spodziewamy się węzła zawierającego parametry oraz węzła zawierającego miasta. Parametr to element posiadający atrybut <em>name</em> oraz <em>value</em> natomiast miasto to element posiadający atrybut <em>name</em> oraz <em>postCode</em>. Atrybut <em>postCode</em> jest dodatkowo ograniczony wzorcem wyrażenia regularnego.</p>
<p>Chcielibyśmy aby oczekiwane klasy, opisujące schemat <em>config.xsd</em> zostały wygenerowane w locie podczas budowania aplikacji. Skorzystamy w tym celu z pluginu do Mavena. Zmieniamy plik <em>pom.xml</em> dodając do niego poniższą konfigurację budowania projektu:</p>
<pre class="brush: xml; first-line: 20;">&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
            &lt;configuration&gt;
                &lt;source&gt;1.5&lt;/source&gt;
                &lt;target&gt;1.5&lt;/target&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
            &lt;artifactId&gt;jaxb2-maven-plugin&lt;/artifactId&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;xjc&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
            &lt;configuration&gt;
                &lt;packageName&gt;${project.groupId}.config&lt;/packageName&gt;
                &lt;schemaDirectory&gt;${basedir}/src/main/resources&lt;/schemaDirectory&gt;
                &lt;outputDirectory&gt;${basedir}/src/main/generated-resources&lt;/outputDirectory&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;</pre>
<p><em>jaxb2</em><em>-maven-plugin</em> wyszuka wszystkie schematy plików <abbr title="Extensible Markup Language">XML</abbr> znajdujące się w lokalizacji wskazanej przez <em>schemaDirectory</em> a następnie wygeneruje klasy umieszczając je w paczce <code>pl.michalmech.config</code> oraz zapisze w lokalizacji wskazanej przez <em>outputDirectory</em>.<br />
Użycie pluginu <em>maven-compiler-plugin</em> jest wymagane ponieważ <abbr title="Java Architecture for XML Binding">JAXB</abbr> korzysta z <a title="adnotacje" href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">adnotacji</a> więc kompilacja musi odbyć się w Javie, w wersji nie niższej niż 1.5.</p>
<p>No to do dzieła! Wykonujemy polecenie:</p>
<pre class="brush: plain; gutter: false;">mvn clean compile eclipse:clean eclipse:eclipse</pre>
<p>oraz odświeżamy projekt w <abbr title="Integrated Development Environment">IDE</abbr>. Zawartość projektu powinna prezentować się teraz jak na załączonym poniżej obrazku.</p>
<p style="text-align: center;"><a href="http://blog.michalmech.pl/wp-content/uploads/2009/09/projekt-jaxb-example.png"><img class="size-thumbnail wp-image-223 aligncenter" style="margin-top: 5px; margin-bottom: 5px;" title="projekt jaxb-example" src="http://blog.michalmech.pl/wp-content/uploads/2009/09/projekt-jaxb-example-116x150.png" alt="projekt jaxb-example" width="116" height="150" /></a></p>
<h3>Konfiguracja kontekstu</h3>
<p>Nasza aplikacja kompiluje się i uruchamia, nadal jednak żadnej konfiguracji nie wczytujemy. Do tego przede wszystkim potrzebujemy pliku <abbr title="Extensible Markup Language">XML</abbr> zgodnego z utworzonym wcześniej schematem. Takiego jak ten:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;config xmlns="http://michalmech.pl/jaxb-example"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://michalmech.pl/jaxb-example config.xsd"&gt;

    &lt;parameters&gt;
        &lt;parameter name="jakiś" value="parametr" /&gt;
        &lt;parameter name="inna" value="opcja" /&gt;
    &lt;/parameters&gt;

    &lt;cities&gt;
        &lt;city name="Warszawa" postCode="03-481" /&gt;
        &lt;city name="Łęczna" postCode="21-010" /&gt;
    &lt;/cities&gt;
&lt;/config&gt;</pre>
<p>Umieszczamy go, tak jak pozostałe zasoby, w <em>src/main/resources</em> i nadajemy nazwę <em>config.xml</em>. Aby mieć pewność, że podczas budowania aplikacji dostarczany plik konfiguracyjny jest poprawny dołożymy jeszcze jeden plugin do <abbr title="Project Object Model">POM</abbr>&#8216;a:</p>
<pre class="brush: xml; first-line: 29;">&lt;plugin&gt;
    &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
    &lt;artifactId&gt;xml-maven-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;goals&gt;
                &lt;goal&gt;validate&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;phase&gt;validate&lt;/phase&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
    &lt;configuration&gt;
        &lt;validationSets&gt;
            &lt;validationSet&gt;
                &lt;dir&gt;${basedir}/src/main/resources&lt;/dir&gt;
                &lt;includes&gt;
                    &lt;include&gt;config.xml&lt;/include&gt;
                &lt;/includes&gt;
                &lt;systemId&gt;${basedir}/src/main/resources/config.xsd&lt;/systemId&gt;
                &lt;schemaLanguage&gt;http://www.w3.org/2001/XMLSchema&lt;/schemaLanguage&gt;
                &lt;validating&gt;true&lt;/validating&gt;
            &lt;/validationSet&gt;
        &lt;/validationSets&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</pre>
<p>Plugin ten zweryfikuje czy dostarczany plik <abbr title="Extensible Markup Language">XML</abbr> jest zgodny ze schematem.</p>
<p>Do wczytania konfiguracji pozostało już bardzo niewiele. Posłużymy się narzędziami znajdującymi się w pakiecie <code>org.springframework.oxm</code>. W tym celu poprosimy Mavena o dostarczenie nam wymaganych źródeł dopisując odpowiednie zależności w pliku <em>pom.xml</em>:</p>
<pre class="brush: xml; first-line: 19;">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.ws&lt;/groupId&gt;
    &lt;artifactId&gt;spring-ws&lt;/artifactId&gt;
    &lt;version&gt;1.5.2&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>Teraz zajmiemy się kontekstem aplikacji. Do tej pory wszystko za mnie robiło jakieś narzędzie czy biblioteka. Nie będę burzył tego porządku i inicjacją odpowiednich obiektów oraz wczytaniem zawartości pliku <em>config.xml</em> do aplikacji zajmie się Spring. Aby to zrobił, konieczna jest ingerencja w deskryptor kontekstu <em>context.xml</em>. Zmieniamy jego zawartość na:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&gt;

    &lt;bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"&gt;
        &lt;property name="schema" value="classpath:config.xsd" /&gt;
        &lt;property name="classesToBeBound"&gt;
            &lt;list&gt;
                &lt;value&gt;pl.michalmech.config.Config&lt;/value&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;

    &lt;bean id="config" class="pl.michalmech.config.Config" factory-bean="jaxb2Marshaller" factory-method="unmarshal"&gt;
        &lt;constructor-arg&gt;
            &lt;bean class="javax.xml.transform.stream.StreamSource"&gt;
                &lt;constructor-arg&gt;
                    &lt;bean class="java.io.FileInputStream" factory-bean="configClasspathResource" factory-method="getInputStream" /&gt;
                &lt;/constructor-arg&gt;
            &lt;/bean&gt;
        &lt;/constructor-arg&gt;
    &lt;/bean&gt;

    &lt;bean id="configClasspathResource" class="org.springframework.core.io.ClassPathResource"&gt;
        &lt;constructor-arg value="config.xml" /&gt;
    &lt;/bean&gt;
&lt;/beans&gt;</pre>
<p>Obiektem klasy <code>ClassPathResource</code> posłużymy się jak fabryką po to by wydobyć strumień zawierający zawartość pliku <em>config.xml</em>. Strumień tenże zostanie użyty w obiekcie fabrycznym <code>Jaxb2Marshaller</code> do naniesienia zawartości pliku <em>config.xml</em> na obiekt klasy <code>Config</code>.</p>
<p>Ostatnią czynnością jest pobranie obiektu <code>Config</code> z kontekstu i wyświetlenie przykładowych danych dostarczonych za pomocą pliku <abbr title="Extensible Markup Language">XML</abbr>. Zmodyfikujmy więc aplikację do postaci:</p>
<pre class="brush: java;">public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

        Config config = (Config) context.getBean("config");

        for (Parameter parameter : config.getParameters().getParameter()) {
            System.out.println(parameter.getName() + ":" + parameter.getValue());
        }

        for (City city : config.getCities().getCity()) {
            System.out.println(city.getName() + " - " + city.getPostCode());
        }
    }
}</pre>
<p>Uruchomienie aplikacji (<a href="http://blog.michalmech.pl/wp-content/uploads/2009/09/Run-as-Java-Application.png"><img class="alignnone size-full wp-image-195" style="border: none; vertical-align: middle;" title="Run as Java Application" src="http://blog.michalmech.pl/wp-content/uploads/2009/09/Run-as-Java-Application.png" alt="Run as Java Application" width="14" height="14" /></a>) da następujący wynik w konsoli:</p>
<pre class="brush: plain; gutter: false;">jakiś:parametr
inna:opcja
Warszawa - 03-481
Łęczna - 21-010</pre>
<h3>Podsumowanie</h3>
<p>To wszystko co chciałem przekazać. Nie zagłębiałem się w szczegóły każdego z użytych narzędzi bo wpis musiałby być dużo dłuższy. Zależało mi na tym by podać gotowy przepis na użycie <abbr title="Java Architecture for XML Binding">JAXB</abbr>&#8216;a w projekcie opartym na szkielecie Spring. Poniżej zamieszczam źródła projektu, które przydadzą się do samodzielnego uruchomienia aplikacji.</p>
<p>Do pobrania: <a href="http://blog.michalmech.pl/wp-content/uploads/2009/09/jaxb-example.zip">jaxb-example.zip</a></p>
<p>Po pobraniu najwygodniej jest wykonać:</p>
<pre class="brush: plain; gutter: false;">mvn compile eclipse:eclipse</pre>
<p>oraz zaimportować projekt do <a title="Eclipse IDE" href="http://www.eclipse.org/">Eclipse</a>&#8216;a.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/ww7nb489aaM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/09/30/spring-jaxb-oraz-maven-czyli-latwe-i-przyjemne-budowanie-oraz-konfigurowanie-aplikacji/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/09/30/spring-jaxb-oraz-maven-czyli-latwe-i-przyjemne-budowanie-oraz-konfigurowanie-aplikacji/</feedburner:origLink></item>
		<item>
		<title>Nelli Rokita jest głupia</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/wkTzLbVYxP4/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/06/25/nelli-rokita-jest-glupia/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 10:34:56 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Polityka]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=172</guid>
		<description><![CDATA[Zanim rozwinę swoją myśl zawartą w tytule tego wpisu, chciałbym podać definicję słowa &#8220;głupi&#8220;. Słownik Języka Polskiego definiuje to pojęcie następująco:

ograniczony i naiwny; też: świadczący o takich cechach;
pot. bezwartościowy intelektualnie;
pot. świadczący o czyimś zakłopotaniu;
pot. dający się wykorzystywać;
pot. niemający znaczenia;
pot. kłopotliwy, niezręczny;


Pani Nelli Rokita w programie &#8220;Kropka nad i&#8221; w dniu 24. czerwca 2009r. wypowiadała się [...]]]></description>
			<content:encoded><![CDATA[<p>Zanim rozwinę swoją myśl zawartą w tytule tego wpisu, chciałbym podać definicję słowa &#8220;<a href="http://sjp.pwn.pl/haslo.php?id=2462059">głupi</a>&#8220;. <a href="http://sjp.pwn.pl">Słownik Języka Polskiego</a> definiuje to pojęcie następująco:</p>
<ol>
<li>ograniczony i naiwny; też: świadczący o takich cechach;</li>
<li><em><abbr title="potoczny, potoczne">pot.</abbr></em> bezwartościowy intelektualnie;</li>
<li><em><abbr title="potoczny, potoczne">pot.</abbr></em> świadczący o czyimś zakłopotaniu;</li>
<li><em><abbr title="potoczny, potoczne">pot.</abbr></em> dający się wykorzystywać;</li>
<li><em><abbr title="potoczny, potoczne">pot.</abbr></em> niemający znaczenia;</li>
<li><em><abbr title="potoczny, potoczne">pot.</abbr></em> kłopotliwy, niezręczny;</li>
</ol>
<p><span id="more-172"></span></p>
<p>Pani <a title="Nelly Rokita" href="http://www.sejm.gov.pl/poslowie/posel6/320.htm">Nelli Rokita</a> w programie &#8220;<a title="Kropka nad i" href="http://www.tvn24.pl/kropka_nad_i.html">Kropka nad i</a>&#8221; w dniu 24. czerwca 2009r. wypowiadała się między innymi na temat niepłodności oraz na temat leczenia niepłodności &#8211; metody <a title="in vitro" href="http://pl.wikipedia.org/wiki/Zap%C5%82odnienie_in_vitro">in vitro</a>. Uznała też, że niepłodność nie jest chorobą, czym obraziła niemałą rzeszę Polaków zmagających się z tym problemem.</p>
<blockquote><p>&#8220;Pani redaktor, bezpłodność nie jest chorobą. To jest wymysł najnowszych naukowców, że bezpłodność jest chorobą&#8221;</p></blockquote>
<p>Otóż pani Rokita, prawdopodobnie będąc nieprzygotowaną merytorycznie, pominęła fakt, że niepłodność jest zapisana w <a href="http://pl.wikipedia.org/wiki/ICD-10">Międzynarodowej Statystycznej Klasyfikacji Chorób i Problemów Zdrowotnych ICD-10</a>. Podważyła tym samym, wiele naukowych faktów. W końcu klasyfikacja jasno mówi o niepłodności kobiecej (<a href="http://stary1.portalmed.pl/finn2/klasyfikacje/icd10/info.stm?active_id=N97">N97</a>) oraz męskiej (<a href="http://stary1.portalmed.pl/finn2/klasyfikacje/icd10/info.stm?active_id=N46">N46</a>). Podejrzewam, że bardzo szybko dostrzegła swoją gafę i wycofała się z tego stwierdzenia zamieniając ja na inną, głupią tezę, że niepłodność może i jest chorobą ale występującą w naszych głowach, chorobą psychiczną. Bulwersujące były również insynuacje pani Rokity, że niepłodność to problem kobiet, które poddawały się wcześniej aborcji.</p>
<blockquote><p>&#8220;Nie może być tak, że chcemy prawa do aborcji, a jak już nam to nie pasuje, żądamy in vitro&#8221;</p></blockquote>
<p>Nigdy nie chciałem komentować na blogu wydarzeń politycznych ale czuję się obrażony wypowiedziami pani Rokity. Jest ona posłem na Sejm i pobiera wynagrodzenie za podatki, które płacę. Postanowiłem więc głośno wypowiedzieć się co o niej myślę. Cytując <a href="http://pl.wikipedia.org">Wikipedię</a>:</p>
<blockquote><p>&#8220;Uważa się, że problem dotyczy 1 na 6 par i w 40% jest zależny od kobiety, w 30% od mężczyzny, a za pozostałe odpowiadają oboje, lub nie da się określić przyczyny (niepłodność idiopatyczna)&#8221;</p></blockquote>
<p>Nie może być tak, że osoba, której swoje poparcie udzieliło zaledwie 6367 osób wypowiada się i decyduje w temacie, o którym nie ma zielonego pojęcia. Nie może być tak, że taka osoba decyduje o losie bardzo wielu ludzi w kraju.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/wkTzLbVYxP4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/06/25/nelli-rokita-jest-glupia/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/06/25/nelli-rokita-jest-glupia/</feedburner:origLink></item>
		<item>
		<title>Java Killers #001</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/YfdengTb9CY/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/06/18/java-killers-001/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 22:43:42 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[autoboxing]]></category>
		<category><![CDATA[Java Killers]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=153</guid>
		<description><![CDATA[Na blogu Pawła Szulca (również w wersji polskiej) można czasem znaleźć zagadki związane z Javą. Paweł nazywa je Java Killers.
Bardzo lubię je czytać a teraz sam mam taką zagadkę. Mam nadzieję, że dla Was będzie to choć trochę ciekawostka, ja byłem zdziwiony.
Oto kod:
public class Main {

    public static void main(String[] args) {
 [...]]]></description>
			<content:encoded><![CDATA[<p>Na blogu <a title="Paweł's Szulc Blog" href="http://paulszulc.wordpress.com">Pawła Szulca</a> (również w <a title="Blog Pawła Szulca" href="http://pawelszulc.blogspot.com">wersji polskiej</a>) można czasem znaleźć zagadki związane z <a title="Java" href="http://java.sun.com">Javą</a>. Paweł nazywa je Java Killers.<br />
Bardzo lubię je czytać a teraz sam mam taką zagadkę. Mam nadzieję, że dla Was będzie to choć trochę ciekawostka, ja byłem zdziwiony.</p>
<p>Oto kod:</p>
<pre class="brush: java;">public class Main {

    public static void main(String[] args) {
        Integer i1 = 1000;
        Integer i2 = 1000;

        if (i1 != i2) {
            System.out.println("i1 and i2 are not the same");
        }

        Integer i3 = 10;
        Integer i4 = 10;

        if (i3 == i4) {
            System.out.println("i3 and i4 are the same");
        }
    }
}</pre>
<p>A oto wynik:</p>
<pre class="brush: plain; gutter: false;">i1 and i2 are not the same
i3 and i4 are the same</pre>
<p>Co się takiego stało, że 1000 to nie 1000 ale 10 to już 10?</p>
<p><span id="more-153"></span></p>
<p>Otóż mechanizm z jakim mamy tu do czynienia to <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html">autoboxing</a>, który został wprowadzony w <a title="Java 1.5.0" href="http://java.sun.com/j2se/1.5.0/docs/">Javie 1.5</a>. W skrócie <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html">autoboxing</a> to mechanizm, który pozwala traktować typy proste jak obiekty i na odwrót a konwersja dzieje się automatycznie w zależności od potrzeby (<em>boxing</em> i <em>unboxing</em>). Każdy typ prosty posiada swoją klasę opakowującą (<em>ang.</em> wrapper) go w obiekt zawierający wartość o typie prostym. Dzięki temu obiekty typu <em>Integer</em> możemy traktować jak <em>int</em>. Szerzej o mechanizmie <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html">autoboxing</a> być może jeszcze napiszę w przyszłości teraz wyjaśnię tylko powyższą sytuację.</p>
<p>Deklarujemy obiekty typu <em>Integer</em>. Dwa obiekty są takie same (w sensie <em>==</em>) jeśli to są te same obiekty. Ale nie w przypadku klas opakowujących (<em>ang.</em> wrapper) typy proste. W takim przypadku dwa obiekty są takie same jeśli przechowują takie same typy proste i są jednymi z poniższych:</p>
<ol>
<li><strong>Boolean</strong>;</li>
<li><strong>Byte</strong>;</li>
<li><strong>Character</strong> (znaki od \u0000 do \u007f);</li>
<li><strong>Short</strong> lub <strong>Integer</strong> ale tylko o wartościach od -128 do 127</li>
</ol>
<p>Wartość 1000 przekracza 127 stąd powyższa &#8220;anomalia&#8221;.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/YfdengTb9CY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/06/18/java-killers-001/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/06/18/java-killers-001/</feedburner:origLink></item>
		<item>
		<title>Automatyczne wstrzykiwanie bean’ów w Springu</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/vEtfLIxZw1g/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/06/16/automatyczne-wstrzykiwanie-beanow-w-springu/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 21:13:25 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Autowire]]></category>
		<category><![CDATA[Bean]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Inversion of Control]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=70</guid>
		<description><![CDATA[Jednym z najważniejszych modułów frameworka Spring jest jego kontener odwrócenia sterowania (ang. Inversion of Control, IoC), który dostarcza nam możliwości wstrzykiwania zależności (ang. Dependency Injection, DI). Jest to miejsce gdzie dzieje się magia :-)
Taki kontener należy odpowiednio skonfigurować, aby bean&#8216;y zarządzane przez framework były odpowiednio zainicjowane oraz ze sobą połączone. Nie będę opisywał wszystkich aspektów [...]]]></description>
			<content:encoded><![CDATA[<p>Jednym z najważniejszych modułów frameworka <a title="Spring Framework" href="http://www.springsource.org">Spring</a> jest jego kontener odwrócenia sterowania (<em>ang.</em> Inversion of Control, <abbr title="Inversion of Control">IoC</abbr>), który dostarcza nam możliwości wstrzykiwania zależności (<em>ang.</em> Dependency Injection, <abbr title="Dependency Injection">DI</abbr>). Jest to miejsce gdzie dzieje się magia :-)</p>
<p>Taki kontener należy odpowiednio skonfigurować, aby <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y zarządzane przez framework były odpowiednio zainicjowane oraz ze sobą połączone. Nie będę opisywał wszystkich aspektów konfiguracji kontenera <abbr title="Inversion of Control">IoC</abbr>, gdyż to zadanie na niekrótką książkę. Skupię się tylko na definiowaniu powiązań między <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ami za pomocą automatycznego wstrzykiwania (<em>ang.</em> <a title="autowire" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire"><strong>autowire</strong></a>).</p>
<p><span id="more-70"></span>Tytułem krótkiego wprowadzenia zaimplementujmy dwa bardzo proste <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y:</p>
<pre class="brush: java;">package pl.michalmech.autoexample.bean;

public class Parent {

    private Integer simpleNumber;

    private Property propertyObject;

    public Parent() {}

    /* setters&amp;getters */
}</pre>
<pre class="brush: java;">package pl.michalmech.autoexample.bean;

public class Property {

    private String simpleText;

    public Property() {}

    /* setters&amp;getters */
}</pre>
<p>Jak widać to bardzo niewyszukane byty pozostające w banalnej zależności. Swoją mini aplikację uruchamiam przez przeglądarkę. W związku z tym dołożyłem sobie prosty kontroler:</p>
<pre class="brush: java;">package pl.michalmech.autoexample.web;

public class HelloController implements Controller {

    protected final Log logger = LogFactory.getLog(getClass());

    private Parent parentObject;

    @Override
    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        logger.info(parentObject.getSimpleNumber());
        logger.info(parentObject.getPropertyObject().getSimpleText());

        return new ModelAndView("index.jsp");
    }

    /* setters&amp;getters */
}</pre>
<p>Tytle tytułem wstępu. Czas zabrać się za definicję <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów i ich właściwości w deskryptorze. Oto one:</p>
<pre class="brush: java;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&gt;

    &lt;bean name="/index.html" class="pl.michalmech.autoexample.web.HelloController"/&gt;

    &lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent"&gt;
        &lt;property name="simpleNumber" value="123"/&gt;
    &lt;/bean&gt;

    &lt;bean name="propertyObject" class="pl.michalmech.autoexample.bean.Property"&gt;
        &lt;property name="simpleText" value="Lorem ipsum ..."/&gt;
    &lt;/bean&gt;
&lt;/beans&gt;</pre>
<p>I tu pierwsze pytanie: Co się stanie kiedy uruchomimy teraz kontroler? Oczywiście, dostaniemy po oczach wyjątkiem <a title="NullPointerException" href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/NullPointerException.html">NullPointerException</a> z bardzo prostej przyczyny. Poza definicją <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów należy je jeszcze wstrzyknąć sobie nawzajem czyli określić relację między nimi.</p>
<h3>Automatyczne wstrzykiwanie na podstawie nazwy.</h3>
<p>Powyższy deskryptor wymaga dwóch poprawek. Pierwsza to wstrzyknięcie obiektu klasy <em>Parent</em> do kontrolera <em>HelloController</em>:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="/index.html" class="pl.michalmech.autoexample.web.HelloController"&gt;
    &lt;property name="parentObject" ref="parentObject"/&gt;
&lt;/bean&gt;</pre>
<p>Jest to najczęściej stosowany sposób definiowania zależnościami pomiędzy <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ami. W jawny sposób mówimy, że bean o nazwie <em>parentObject</em> powinien zostać wstrzyknięty w pole kontrolera o tej samej nazwie.<br />
Koleją zależność zdefiniujemy nieco inaczej:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent" autowire="byName"&gt;
    &lt;property name="simpleNumber" value="123"/&gt;
&lt;/bean&gt;</pre>
<p>Obiekt <em>parentObject</em> klasy <em>Parent</em> posiada jedno pole typu prostego i je tutaj pomijam bo nie ma znaczenia przy omawianiu automatycznego wstrzykiwania, które tyczy się tylko obiektów. Zadeklarowanie <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a jako <em>autowire=&#8221;byName&#8221;</em> sprawi, że <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> automatycznie wyszuka <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o nazwie takiej jak nazwa inicjowanego pola. W tej sytuacji w pole <em>propertyObject</em> zostanie wstrzyknięty bean o nazwie <em>propertyObject</em>. Sprawa jest dość prosta i klarowna. Warto zwrócić jednak uwagę na trzy kwestie:</p>
<p><strong>Niezgodność typów</strong>. W przypadku kiedy <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a> o pasującej nazwie próbuje być wstrzyknięty jako wartość pola ale nie jest zgodny z jego typem dostaniemy wyjątek <a title="BeanCreationException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/class-use/BeanCreationException.html">BeanCreationException</a>, spowodowany przez <a title="TypeMismatchException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/TypeMismatchException.html">TypeMismatchException</a>:</p>
<pre class="brush: plain; gutter: false;">Caused by: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [pl.michalmech.autoexample.bean.FakeProperty] to required type [pl.michalmech.autoexample.bean.Property] for property 'propertyObject'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [pl.michalmech.autoexample.bean.FakeProperty] to required type [pl.michalmech.autoexample.bean.Property] for property 'propertyObject': no matching editors or conversion strategy found</pre>
<p><strong>Brak <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o szukanej nazwie</strong>. Jeśli kontener nie znajdzie <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a wymaganej nazwie to, jak łatwo się domyślić, nic nie wstrzyknie. Pole nadal będzie miało wartość <em>null</em>;</p>
<p><strong>Niejednoznaczność nazwy </strong><strong><a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a></strong><strong>&#8216;a</strong>. To problem, który może wystąpić i który nie jest związany bezpośrednio z automatycznym wstrzykiwaniem. Dwa <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y o tej samej nazwie to prosty błąd konfiguracji, który sprowadza się do <a title="BeanDefinitionParsingException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/parsing/BeanDefinitionParsingException.html">BeanDefinitionParsingException</a>.</p>
<h3>Automatyczne wstrzykiwanie po typie.</h3>
<p>Kontener <abbr title="Inversion of Control">IoC</abbr> pozwala nam automatycznie wstrzyknąć zależności nie tylko bazując na nazwach <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów ale również na podstawie ich typów. Zmodyfikujmy konfigurację automatycznego wstrzykiwania dla <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a <em>parentObject</em> następująco:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent" autowire="byType"&gt;
    &lt;property name="simpleNumber" value="123"/&gt;
&lt;/bean&gt;</pre>
<p>Zmienił się typ automatycznego wstrzykiwania zależności. W obecnej sytuacji <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> natrafiając na pole <em>propertyObject</em> <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a <em>parentObject</em> będzie starał się wstrzyknąć <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o typie <em>Property</em>. W moim prostym przykładzie mamy oczywiście takiego <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a więc wszystko uda się bez problemu.</p>
<p>W przypadku wstrzykiwania po typie nie musimy kompletnie martwić się o nazwę <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a. Podobnie nie musimy się martwić jeśli <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a> o żądanym typie nie zostanie odnaleziony. Po prostu nic nie zostanie wstrzyknięte.</p>
<p>Niestety całkowicie wbrew powiedzeniu <em>&#8220;Od przybytku głowa nie boli&#8221;</em> musimy się martwić o nadmiar <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów o typie zgodnym z typem pola do którego <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> będzie chciał wstrzyknąć zależności.<br />
Załóżmy, że mam dwa <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y o tym samym typie:</p>
<pre class="brush: xml; first-line: 13;">    &lt;bean name="propertyObject" class="pl.michalmech.autoexample.bean.Property"&gt;
        &lt;property name="simpleText" value="Lorem ipsum ..."/&gt;
    &lt;/bean&gt;

    &lt;bean name="secondPropertyObject" class="pl.michalmech.autoexample.bean.Property"&gt;
        &lt;property name="simpleText" value="... muspi meroL"/&gt;
    &lt;/bean&gt;</pre>
<p>Próba uruchomienia tak skonfigurowanej aplikacji skończy się na <a title="BeanCreationException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/class-use/BeanCreationException.html">BeanCreationException</a> spowodowanym przez <a title="UnsatisfiedDependencyException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/UnsatisfiedDependencyException.html">UnsatisfiedDependencyException</a>:</p>
<pre class="brush: plain; gutter: false;">Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'parentObject' defined in ServletContext resource [/WEB-INF/AutoExample-servlet.xml]: Unsatisfied dependency expressed through bean property 'propertyObject': : No unique bean of type [pl.michalmech.autoexample.bean.Property] is defined: expected single matching bean but found 2: [propertyObject, secondPropertyObject]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [pl.michalmech.autoexample.bean.Property] is defined: expected single matching bean but found 2: [propertyObject, secondPropertyObject]</pre>
<p>Pomimo tego, że streszczenie wyjątku jest w jednej, długiej linii to dostarcza wielu informacji. <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> podpowiada, że znalazł aż dwa <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y pasujące typem do pola oraz podaje ich nazwy co pozwala na szybkie wytropienie błędu.</p>
<h3>Automatyczne wstrzykiwanie za pomocą konstruktora.</h3>
<p>Kolejnym sposobem na automatyczne wstrzyknięcie zależności do <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a jest użycie konstruktora. Zmodyfikujmy klasę <em>Parent</em> w następujący sposób:</p>
<pre class="brush: java;">package pl.michalmech.autoexample.bean;

public class Parent {

    protected final Log logger = LogFactory.getLog(getClass());

    private Integer simpleNumber;

    private Property propertyObject;

    public Parent(Property propertyObject) {
        this.propertyObject = propertyObject;

        logger.info("propertyObject field set by constructor");
    }

    public Property getPropertyObject() {
        return propertyObject;
    }

    public void setPropertyObject(Property propertyObject) {
        this.propertyObject = propertyObject;

        logger.info("propertyObject field set by method");
    }

    /* setter&amp;getter for simpleNumber */
}</pre>
<p>W stosunku do oryginału zmieniły się dwie rzeczy:</p>
<ol>
<li>Usunięty został domyślny konstruktor;</li>
<li>Dodany został konstruktor inicjujący pole <em>propertyObject</em>;</li>
</ol>
<p>Zmieńmy jeszcze sposób automatycznego wstrzykiwania. Zmiana deskryptora wygląda następująco:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent" autowire="constructor"&gt;
    &lt;property name="simpleNumber" value="123"/&gt;
&lt;/bean&gt;</pre>
<p>Próba uruchomienia aplikacji zakończy się sukcesem a w konsoli ujrzymy następujący napis:</p>
<pre class="brush: plain; gutter: false;">propertyObject field set by constructor</pre>
<p>Na podstawie tego przykładu widać doskonale, że automatyczne wstrzykiwanie za pomocą konstruktora niewiele różni się od wstrzykiwania na podstawie typu. Również w tym przypadku kontener wyszukuje <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o odpowiednim typie lecz zamiast odpowiedniej metody do wstrzyknięcia używa konstruktora.</p>
<p>Sposób ten w odróżnieniu od <em>byType</em> niesie ze sobą więcej potencjalnych problemów. Pierwszym z nich jest sytuacja kiedy konstruktor posiada więcej argumentów. Załóżmy więc, że konstruktor przyjmuje nie tylko jeden argument o typie zgodnym z polem do którego będzie wstrzyknięta wartość (w tym przypadku <em>Property</em>) lecz posiada jeszcze jeden:</p>
<pre class="brush: java; first-line: 14">    public Parent(Integer simpleNumber, Property propertyObject) {
        this.simpleNumber = simpleNumber;
        this.propertyObject = propertyObject;
    }</pre>
<p>W takiej sytuacji próba uruchomienia aplikacji zakończy się wyrzuceniem znanego już wyjątku <a title="UnsatisfiedDependencyException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/UnsatisfiedDependencyException.html">UnsatisfiedDependencyException</a> z komunikatem podobnym do:</p>
<pre class="brush: plain; gutter: false;">Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [java.lang.Integer] is defined: Unsatisfied dependency of type [java.lang.Integer]: expected at least 1 matching bean</pre>
<p>Oznacza to, że aby kontener <abbr title="Inversion of Control">IoC</abbr> mógł skorzystać z naszego konstruktora potrzebuje wszystkich argumentów. Co zresztą wcale nie dziwi. W związku z tym, że nie mamy <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o typie <em>Integer</em>, dostajemy wyjątek.<br />
Podobnie stałoby się gdybyśmy potrzebowali wstrzyknąć dwa lub więcej obiekty a żaden z konstruktorów nie posiadałby ich pełnej listy w swoich argumentach.</p>
<p>Jak już wcześniej się okazało przybytek nie zawsze jest dobry. Co się stanie w sytuacji kiedy będziemy mieli więcej konstruktorów, z których <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> mógłby skorzystać do wstrzykiwania zależności? Załóżmy więc taką sytuację:</p>
<pre class="brush: java; first-line: 14;">    public Parent(Integer simpleNumber, Property propertyObject) {
        this.simpleNumber = simpleNumber;
        this.propertyObject = propertyObject;
    }

    public Parent(String fakeString, Property propertyObject) {
        this.propertyObject = propertyObject;
    }</pre>
<p>i</p>
<pre class="brush: xml; first-line: 11;">    &lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent" autowire="constructor"&gt;
        &lt;property name="simpleNumber" value="123"/&gt;
    &lt;/bean&gt;

    &lt;bean name="someInt" class="java.lang.Integer"&gt;
        &lt;constructor-arg value="123"/&gt;
    &lt;/bean&gt;

    &lt;bean name="someString" class="java.lang.String"&gt;
        &lt;constructor-arg value="Lorem ipsum ..."/&gt;
    &lt;/bean&gt;

    &lt;bean name="propertyObject" class="pl.michalmech.autoexample.bean.Property"&gt;
        &lt;property name="simpleText" value="Lorem ipsum ..."/&gt;
    &lt;/bean&gt;</pre>
<p>Uruchomienie aplikacji na takich warunkach uda się bez problemu a do wstrzyknięcia zależności użyty zostanie pierwszy konstruktor. Dlaczego? No coż, nie mam pewności ale z moich obserwacji wynika, że użyty zostanie pierwszy pasujący konstruktor.</p>
<h3>Automatyczny wybór sposobu wstrzykiwania.</h3>
<p>Poza trzema omówionymi strategiami automatycznego wstrzykiwania zależności jest jeszcze jedna, polegająca na autodetekcji:</p>
<pre class="brush: xml; gutter: false;">    &lt;bean name="parentObject" class="pl.michalmech.autoexample.bean.Parent" autowire="autodetect"&gt;
        &lt;property name="simpleNumber" value="123"/&gt;
    &lt;/bean&gt;</pre>
<p>Autodetekcja polega na tym, że kontener wybierze sam pomiędzy <em>constructor</em> a <em>byType</em>. Kryterium wyboru to obecność domyślnego konstruktora. Jeśli kontener <abbr title="Inversion of Control">IoC</abbr> go znajdzie, to skorzysta ze wstrzykiwania na podstawie typu, jeśli nie, to spróbuje wstrzyknąć zależności za pomocą konstruktora.</p>
<h3>Kolekcje a automatyczne wstrzykiwanie.</h3>
<p>Zbliżając się ku końcowi wrócę jeszcze do tego przybytku od, którego głowa bolała. Mechanizm <a title="autowire" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire">autowire</a> radzi sobie bardzo dobrze z kolekcjami.</p>
<p>Kiedy wstrzykiwaliśmy na podstawie typu (<em>autowire=&#8221;byType&#8221;</em>) a <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów o poszukiwanym typie było więcej niż jeden, framework raczył nas wyjątkiem <a title="UnsatisfiedDependencyException" href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/UnsatisfiedDependencyException.html">UnsatisfiedDependencyException</a>. Nie działoby się tak jeśli mielibyśmy do czynienia z tablicą, kolekcją (<a title="Collection" href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html">Collection</a>) lub mapą:</p>
<pre class="brush: java;">package pl.michalmech.autoexample.bean;

    public class Parent {

    private Integer simpleNumber;

    private Set&lt;Property&gt; propertyObjects;

    public Set&lt;Property&gt; getPropertyObjects() {
        return propertyObjects;
    }

    public void setPropertyObjects(Set&lt;Property&gt; propertyObjects) {
        this.propertyObjects = propertyObjects;
    }

    /* setter&amp;getter for simpleNumber */
}</pre>
<p>W takiej sytuacji kontener wrzuci do kolekcji wszystkie znalezione <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;y o pasującym typie. W powyższym przykładzie jest zbiór ale mechanizm zadziała również z tablicą oraz dowolną inną kolekcją (<a title="Collection" href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html">Collection</a>). W przypadku mapy ważne jest by jej kluczem były obiekty typu <em>String</em> ponieważ to nazw <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów <a title="Spring Framework" href="http://www.springsource.org/">Spring</a> używa do wypełnienia mapy. W przeciwnym wypadku framework po prostu nic do niej nie wstrzyknie.</p>
<h3>Kandydaci do wstrzyknięcia.</h3>
<p>Użycie kolekcji zamiast pojedynczego <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a nie zawsze jest rozwiązaniem pozwalającym ominąć problem nadmiarowej ilości <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów. Co w sytuacji kiedy po prostu chcemy wstrzyknąć jednego <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a i bardzo chcemy użyć automatycznego wstrzykiwania na podstawie typu? Otóż są jeszcze dwa rozwiązania.<br />
Pierwsze z nich to wykluczenie części <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów z kandydatury na bycie wstrzykniętym. Oto jak to się robi:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="propertyObject" class="pl.michalmech.autoexample.bean.Property" autowire-candidate="false"&gt;
    &lt;property name="simpleText" value="Lorem ipsum ..."/&gt;
&lt;/bean&gt;</pre>
<p>Tak skonfigurowany bean nie będzie nam przeszkadzał w automatycznym wstrzykiwaniu, ponieważ nie będzie wzięty pod uwagę.<br />
Innym sposobem jest określenie głównego <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;a o danym typie:</p>
<pre class="brush: xml; gutter: false;">&lt;bean name="propertyObject" class="pl.michalmech.autoexample.bean.Property" primary="true"&gt;
    &lt;property name="simpleText" value="Lorem ipsum ..."/&gt;
&lt;/bean&gt;</pre>
<p>Jeśli jestkilka <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ów o danym typie i tylko jeden z nich jest <em>primary</em> to on zostanie wstrzyknięty.</p>
<h3>Podsumowanie.</h3>
<p>Jak widać automatyczne wstrzykiwanie zależności to trochę jak pudełko czekoladek, nigdy nie wiadomo co się trafi (tak mawiał <a title="Forrest Gump" href="http://pl.wikipedia.org/wiki/Forrest_Gump">Forrest Gump</a>). Nawet dokumentacja zaznacza, że należy się zastanowić czy warto stosować mechanizm <a title="autowire" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire">autowire</a> przy dużych wdrożeniach, ponieważ nie jest łatwo wtedy utrzymać całkowitą jednoznaczność i kontrolę nad <a title="Bean" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-definition">bean</a>&#8216;ami. Mi się jednak ten echanizm podoba. Zobaczymy jak w przyszłości.</p>
<h3>P.S.</h3>
<p>Mechanizmem automatycznego wstrzykiwania zależności można również sterować za pomocą <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">adnotacji</a> dostępnych w <a title="Java" href="http://java.sun.com">Javie</a> od wersji 1.5. Postanowiłem jednak pominąć je w tym wpisie ponieważ urósłby on do zbyt dużych rozmiarów.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/vEtfLIxZw1g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/06/16/automatyczne-wstrzykiwanie-beanow-w-springu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/06/16/automatyczne-wstrzykiwanie-beanow-w-springu/</feedburner:origLink></item>
		<item>
		<title>Bye bye Blogger</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/kVSxo4_2r8M/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/06/09/bye-bye-blogger/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 19:58:41 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Blogowanie]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://blog.michalmech.pl/?p=67</guid>
		<description><![CDATA[Drogi czytelniku jeśli jesteś tutaj n-ty raz zauważyłeś zapewne, że zmieniła się szata graficzna.
Postanowiłem podziękować za współpracę platformie Blogger&#8216;a na rzecz własnej instalacji Wordpress&#8216;a. Początkowo był to Blogger ponieważ chciałem po prostu pisać i nie przejmować się aplikacja, instalacją, e.t.c. Z czasem okazało się, że Blogger to zbyt uboga platforma i nie spełnia moich oczekiwań. [...]]]></description>
			<content:encoded><![CDATA[<p>Drogi czytelniku jeśli jesteś tutaj <em>n</em>-ty raz zauważyłeś zapewne, że zmieniła się szata graficzna.</p>
<p>Postanowiłem podziękować za współpracę platformie <a title="Blogger" href="http://www.blogger.com">Blogger</a>&#8216;a na rzecz własnej instalacji <a title="Wordpress" href="http://wordpress.org">Wordpress</a>&#8216;a. Początkowo był to <a title="Blogger" href="http://www.blogger.com">Blogger</a> ponieważ chciałem po prostu pisać i nie przejmować się aplikacja, instalacją, e.t.c. Z czasem okazało się, że <a title="Blogger" href="http://www.blogger.com/">Blogger</a> to zbyt uboga platforma i nie spełnia moich oczekiwań. Na przykład kuleje możliwości wklejania listingów, których jest sporo w moich wpisach.<br />
<a title="Wordpress" href="http://wordpress.org">Wordpress</a> daje nieporównywalnie dużo więcej możliwości, chociażby z tego powodu, że instalacja stoi na &#8220;moim&#8221; serwerze i mogą z nią robić co chcę.</p>
<p>Jak widać udało mi się bez większego bólu zaimportować treści, które były opublikowane jeszcze za <a title="Blogger" href="http://www.blogger.com">Blogger</a>&#8216;a.</p>
<p>Starałem się zachować stan bloga tak aby migracja była niezauważalna dla osób, które subskrybują kanał <abbr title="Really Simple Syndication">RSS</abbr> lub mają mój adres zapisany w zakładkach. Nie mniej jednak kilka linków zmieniło adresy. Za utrudnienia najmocniej przepraszam. Proszę informować mnie o problemach, postaram się je naprawić. Takie są koszty lenistwa i pójścia na łatwiznę, czym był wybór <a title="Blogger" href="http://www.blogger.com">Blogger</a>&#8216;a.</p>
<p>P.S.<br />
Po przenosinach oraz po wielu innych wydarzeniach, które się ostatnio działy w moim życiu mogę znów zabrać się do nauki, a co z tym się wiąże, do publikowania kolejnych wpisów.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/kVSxo4_2r8M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/06/09/bye-bye-blogger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/06/09/bye-bye-blogger/</feedburner:origLink></item>
		<item>
		<title>Budowanie aplikacji za pomocą Mavena</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/n_vZ0XoPrLU/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/04/08/budowanie-aplikacji-za-pomoca-mavena/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 19:19:00 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Ant]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring IDE]]></category>

		<guid isPermaLink="false">http://blog.michalme.ayz.pl/?p=9</guid>
		<description><![CDATA[Kiedy pisałem o instalacji Seama wspomniałem, o instalacji narzędzia Maven, które może mi się przydać w przyszłości. I oto nadeszła ta chwila. Czytając jakiś czas temu poradnik Developing a Spring Framework MVC application pomyślałem, że fajnie byłoby zamienić narzędzie do budowania projektu z Anta na Mavena, który zajmie się przy okazji zależnościami.
Korzystam z Eclipse&#8216;a jako [...]]]></description>
			<content:encoded><![CDATA[<p>Kiedy pisałem o instalacji Seama wspomniałem, o instalacji narzędzia Maven, które może mi się przydać w przyszłości. I oto nadeszła ta chwila. Czytając jakiś czas temu poradnik <a href="http://static.springframework.org/docs/Spring-MVC-step-by-step">Developing a Spring Framework MVC application</a> pomyślałem, że fajnie byłoby zamienić narzędzie do budowania projektu z <a title="Apache Ant" href="http://ant.apache.org">Anta</a> na <a href="http://maven.apache.org">Mavena</a>, który zajmie się przy okazji zależnościami.</p>
<p>Korzystam z <a href="http://www.eclipse.org">Eclipse</a>&#8216;a jako <abbr title="Integrated Development Environment">IDE</abbr> więc do zabawy przydadzą mi się dwa pluginy:</p>
<ol>
<li><a href="http://springide.org">Spring IDE</a> &#8211; Przyda się do utworzenia <em>Hello World</em> oraz na przyszłość;</li>
<li><a href="http://m2eclipse.codehaus.org">Maven Integration for Eclipse</a> &#8211; Zautomatyzuje nam to trochę czynności oraz dostaniemy bardzo ładny edytor plików <a href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html">POM</a>.</li>
</ol>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/new-spring-project-3.jpg"><img class="alignleft size-thumbnail wp-image-38" style="margin: 5px;" title="New Spring Project (3)" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/new-spring-project-3-146x150.jpg" alt="New Spring Project (3)" width="146" height="150" /></a>Po zainstalowaniu powyższych tworzymy zalążek projektu w Eclipse. Wybieramy <em>File  &gt; New  &gt; Other</em> a później <em>Spring Project</em>. Podajemy nazwę projektu, niech to <em>jExample</em> oraz zmieniamy lokalizację <em>Source Folder Name</em> z <em>src</em> na <em>src/main/java</em> a <em>Output Folder Name</em> z <em>bin</em> na <em>target/classes</em>. Zmiany te wynikają z domyślnych ustawień pluginów Mavena, z których będziemy korzystać.</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/create-new-pom.jpg"><img class="alignright size-thumbnail wp-image-39" style="margin: 5px;" title="Create new POM" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/create-new-pom-150x139.jpg" alt="Create new POM" width="150" height="139" /></a>W następnej kolejności aktywujemy zarządzanie projektem za pomocą Mavena. W tym celu wybieramy <em>Maven  Enable Dependency Managment</em> po uprzednim kliknięciu prawym klawiszem myszy na projekcie.</p>
<p>Kluczowym elementem pracy z Mavenem jest plik POM, który stanowi konfigurację zawierającą informacje o projekcie, jego zależnościach, e.t.c. Kreator tworzenia pliku POM uruchomi się zaraz po aktywacji Mavena. Jedyną zmianą jakiej dokonujemy to zamiana pakowania projektu z <em>jar</em> na <em>war</em>. Oto plik, który będzie wynikiem:</p>
<pre class="brush: xml;">&lt;project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/maven-v4_0_0.xsd"&gt;

    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;jExample&lt;/groupId&gt;
    &lt;artifactId&gt;jExample&lt;/artifactId&gt;
    &lt;packaging&gt;war&lt;/packaging&gt;
    &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
&lt;/project&gt;</pre>
<p>Utwórzmy teraz naprawdę bardzo prostą aplikację internetową. Niech jej jedyną funkcją będzie przywitanie nas słowami &#8230; <em>Hello World</em>. W pierwszej kolejności tworzymy deskryptory.</p>
<p><span style="font-style: italic;">src/main/webapp/WEB-INF/web.xml</span>:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;

    &lt;servlet&gt;
        &lt;servlet-name&gt;jExample&lt;/servlet-name&gt;
        &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
        &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
    &lt;/servlet&gt;

    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;jExample&lt;/servlet-name&gt;
        &lt;url-pattern&gt;*.html&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;

    &lt;welcome-file-list&gt;
        &lt;welcome-file&gt;index.html&lt;/welcome-file&gt;
    &lt;/welcome-file-list&gt;
&lt;/web-app&gt;</pre>
<p><em>src/main/webapp/WEB-INF/jExample-servlet.xml</em>:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&gt;

    &lt;bean name="/index.html" class="pl.michalmech.jexample.web.HelloController"/&gt;
&lt;/beans&gt;</pre>
<p>Oraz <em>src/main/webapp/WEB-INF/applicationContext.xml</em></p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans

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

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

http://www.springframework.org/schema/aop/spring-aop-2.0.xsd

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

        http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"&gt;
&lt;/beans&gt;</pre>
<p>Dodajemy jeszcze szybko widok (<em>src/main/webapp/index.jsp</em>):</p>
<pre class="brush: xml;">&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;jExample&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;jExample :: Hello World&lt;/h1&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Oraz na koniec niewielki kontroler:</p>
<pre class="brush: java;">import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class HelloController implements Controller {

    protected final Log logger = LogFactory.getLog(getClass());

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        logger.info("Returninag hello view");

        return new ModelAndView("index.jsp");
    }
}</pre>
<p>Niestety jedyne co ma dla nas Eclipse to błędy wynikające z braku klas, których potrzebujemy:</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/hellocontroller.jpg"><img class="aligncenter size-medium wp-image-40" title="HelloController" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/hellocontroller-300x267.jpg" alt="HelloController" width="300" height="267" /></a></p>
<p>Jest to okazja do wykorzystania wreszcie Mavena, który dostarczy nam zależności, których potrzebujemy. Chcielibyśmy przede wszystkim skorzystać ze Spring MVC (niech to będzie najnowsza wersja) oraz <abbr title="Application Programming Interface">API</abbr> związanego z sewletami. Dodajemy do pliku POM następujący wpis (możemy oczywiście w tym celu użyć edytora plików POM):</p>
<pre class="brush: xml;">&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework&lt;/groupId&gt;
        &lt;artifactId&gt;spring-webmvc&lt;/artifactId&gt;
        &lt;version&gt;2.5.6&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;javax.servlet&lt;/groupId&gt;
        &lt;artifactId&gt;servlet-api&lt;/artifactId&gt;
        &lt;version&gt;2.5&lt;/version&gt;
        &lt;scope&gt;provided&lt;/scope&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</pre>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/spring-project-dependencies.jpg"><img class="alignright size-thumbnail wp-image-42" style="margin: 5px;" title="Spring Project (dependencies)" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/spring-project-dependencies-82x150.jpg" alt="Spring Project (dependencies)" width="82" height="150" /></a><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/pom-editor-dependencies.jpg"><img class="size-thumbnail wp-image-41 alignleft" style="margin: 5px;" title="POM Editor (dependencies_" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/pom-editor-dependencies-150x97.jpg" alt="POM Editor (dependencies_" width="150" height="97" /></a>Zapisanie pliku sprawi, że Maven pobierze ze swojego lokalnego repozytorium wymagane zależności i dostarczy do projektu. W przypadku braku wymaganych paczek, zostaną one wcześniej pobrane z sieci (<a href="http://repo2.maven.org/maven2">http://repo2.maven.org/maven2</a>) oraz zainstalowane w repozytorium lokalnym Mavena. Warto zaznaczyć, że Maven dostarczył nam również inne wymagane pośrednio zależności: <em>commons-logging</em>, <em>spring-core</em>, e.t.c. My nie musimy się niczym martwić. Projekt już nie świeci się na czerwono od błędów.</p>
<p>W związku z tym, że dążymy do ujrzenia naszej aplikacji działającej przydałoby sie teraz utworzyć plik <abbr title="Web Application Archive">WAR</abbr>. W tym celu wykonujemy w konsoli (będąc w loklizacji, w której znajduje się nasz projekt) polecenie:</p>
<pre class="brush: xml; gutter: false;">mvn clean package</pre>
<p>Wynikiem wykonania tego polecenia powinno być coś takiego:</p>
<pre class="brush: plain; gutter: false;">F:\workspace\jExample&gt;mvn clean package
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Unnamed - jExample:jExample:war:0.0.1-SNAPSHOT
[INFO]    task-segment: [clean, package]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean]
[INFO] Deleting directory F:\workspace\jExample\target
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to F:\workspace\jExample\target\classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] No sources to compile
[INFO] [surefire:test]
[INFO] No tests to run.
[INFO] [war:war]
[INFO] Packaging webapp
[INFO] Assembling webapp[jExample] in [F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT]
[INFO] Processing war project
[INFO] Webapp assembled in[171 msecs]
[INFO] Building war: F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Wed Apr 08 23:51:16 CEST 2009
[INFO] Final Memory: 11M/20M
[INFO] ------------------------------------------------------------------------</pre>
<p>Teraz krótkie wyjaśnienie. Maven w pierwszej kolejności wyczyścił wszystko to co mogło być do tej pory skompilowane i umieszczone w folderze <em>target</em>. Po to było polecenie <em>clean</em>. W dalszej części <em>Maven</em> zajmuje się pakowaniem projektu (polecenie <em>package</em>). Plan tej czynności zakłada wykonanie kilku czynności wcześniej. Jest to przede wszystkim kompilacja źródeł, zebranie zasobów, wykonanie testów jednostkowych oraz wreszcie zebranie wszystkiego do kupy w <abbr title="Web Application Archive">WAR</abbr> Pomimo tego, że w tym przypadku niewiele faktycznie jest do zrobienia, Maven informuje nas o każdej czynności i wynikach jej wykonania.<br />
Każda z czynności jest realizowana przez oddzielny <a href="http://maven.apache.org/plugins/index.html">plugin Mavena</a>, który możemy w szczególności skonfigurować wedle naszych życzeń.</p>
<p>Do <em>Hello World</em> krzyczącego do nas z okna przeglądarki zostało bardzo niewiele. Podobnie jak w tutorialu, o którym wspomniałem na początku, my również skorzystamy z kontenera aplikacji <a title="Apache Tomcat" href="http://tomcat.apache.org">Apache Tomcat</a> (instalacja jest niezwykle prosta więc pominę jej opis).</p>
<p>Przy tej okazji chciałbym zwrócić uwagę na konfigurację zależności <em>servlet-api</em>. Przestrzeń (ang. scope) jest zdefiniowana jako <em>provided</em>. Dzieje się tak ponieważ Tomcat dostarcza już tą paczkę wśród swoich bibliotek więc aplikacja, która jest rozmieszczana (ang. deploy) na serwerze nie musi jej zawierać.</p>
<p>W folderze domowym instalacji Mavena, w folderze <em>conf</em> znajduje się plik z globalną konfiguracją: <em>settings.xml</em>. W bloku zawierającym definicje serwerów <em>servers/servers</em> dodajmy opis lokalnego Tomcata:</p>
<pre class="brush: xml;">&lt;server&gt;
    &lt;id&gt;tomcat.local&lt;/id&gt;
    &lt;username&gt;admin&lt;/username&gt;
    &lt;password&gt;&lt;/password&gt;
&lt;/server&gt;</pre>
<p>Identyfikator serwera jest dowolny natomiast login oraz hasło (a dokładniej jego brak) wynika z domyślnych wartości dla standardowej instalacji Tomcataa. Aby umieścić naszą aplikację na serwer skorzystamy z pluginu <a href="http://mojo.codehaus.org/tomcat-maven-plugin/plugin-info.html">Tomcat Maven Plugin</a>. Aby wykonać całą robotę, czyli kompilację, spakowanie oraz rozmieszczenie (ang. deploy) projektu na serwer wystarczy wykonać polecenie:</p>
<pre class="brush: plain; gutter: false;">mvn clean package tomcat:deploy</pre>
<p>W zasadzie to wystarczy ponieważ Maven pobierze ze swojego repozytorium i zainstaluje wspomniany plugin jak tylko będzie go potrzebował. Podczas wykonywania polecenia zobaczymy to w konsoli:</p>
<pre class="brush: plain; gutter: false;">[INFO] Searching repository for plugin with prefix: 'tomcat'.
[INFO] org.codehaus.mojo: checking for updates from central
[INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central
Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/tomcat-maven-plugin/1.0-beta-1/tomcat-maven-plugin-1.0-beta-1.pom
5K downloaded
Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/mojo-parent/20/mojo-parent-20.pom
18K downloaded
Downloading: http://repo1.maven.org/maven2/org/codehaus/mojo/tomcat-maven-plugin/1.0-beta-1/tomcat-maven-plugin-1.0-beta-1.jar
48K downloaded</pre>
<p>Niemniej jednak gdybyśmy chcieli wskazać jakieś inne repozytorium, które Maven ma przeszukiwać w chwili kiedy czegoś potrzebuje, możemy je zdefiniować w pliku POM:</p>
<pre class="brush: xml;">&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;mojo&lt;/id&gt;
        &lt;name&gt;Mojo Project&lt;/name&gt;
        &lt;url&gt;http://repository.codehaus.org&lt;/url&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;</pre>
<p>Podobnie ma się rzecz z uruchomieniem plugin. Użyta będzie domyślna konfiguracja. Aby ją zmienić powinniśmy odpowiednio zmodyfikować POM. Oto przykład jak jawnie podać nazwę serwera, na którym umieszczamy (ang. deploy) aplikację:</p>
<pre class="brush: xml;">&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupid&gt;org.codehaus.mojo&lt;/groupid&gt;
            &lt;artifactid&gt;tomcat-maven-plugin&lt;/artifactid&gt;
            &lt;configuration&gt;
                &lt;server&gt;tomcat.local&lt;/server&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;</pre>
<p>Konfiguracja oczywiście będzie będzie wzięta z ustawień globalnych Mavena.</p>
<p>W zasadzie to wszystko. Wykonanie wspomnianego polecenia (<em>mvn clean package tomcat:deploy</em>) powinno dać następujący wynik:</p>
<pre class="brush: plain; gutter: false;">...
[INFO] Building war: F:\workspace\jExample\target\jExample-0.0.1-SNAPSHOT.war
[INFO] [tomcat:deploy]
[INFO] Deploying war to http://localhost:8080/jExample
[INFO] OK - Deployed application at context path /jExample
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------</pre>
<p>Uruchomienie w przeglądarce adresu <em>http://localhost:8080/jExample/index.html</em> pozwoli nam upewniść się, że aplikacja działa.</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/04/jexample-hello-world.jpg"><img class="aligncenter size-medium wp-image-43" title="jExample Hello  World" src="http://blog.michalmech.pl/wp-content/uploads/2009/04/jexample-hello-world-300x203.jpg" alt="jExample Hello  World" width="300" height="203" /></a></p>
<p>To co opisałem, to zaledwie kropla w morzu możliwości Mavena, który posiada ich oczywiście dużo więcej, dzięki różnorodnym pluginom. Możemy dzięki niemu nie tylko zarządzać budowaniem projektu i zależnościami ale również <a href="http://maven.apache.org/plugins/maven-javadoc-plugin">generować dokumentację</a> czy nawet sprawdzać <a href="http://maven.apache.org/plugins/maven-checkstyle-plugin">styl kodowania</a>.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/n_vZ0XoPrLU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/04/08/budowanie-aplikacji-za-pomoca-mavena/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/04/08/budowanie-aplikacji-za-pomoca-mavena/</feedburner:origLink></item>
		<item>
		<title>Reguły nawigacji w deskryptorze stron Seam’a</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/hZgkAgd6VUw/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/03/01/reguly-nawigacji-w-deskryptorze-stron-seama/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 13:41:00 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[JBoss Seam]]></category>

		<guid isPermaLink="false">http://blog.michalme.ayz.pl/?p=8</guid>
		<description><![CDATA[We wprowadzeniu do dokumentacji frameworka JBoss Seam twórcy podkreślają, że uciekają jak tylko się da od konfiguracji za pomocą plików XML na rzecz przekazywania informacji do kontenera za pomocą adnotacji. Nie mniej jednak każdy projekt napisany z pomocą Seam&#8217;a zawiera kilka plików konfiguracyjnych, jednym z nich jest deskryptor stron: pages.xml.
W pliku deskryptora (znajduje się on [...]]]></description>
			<content:encoded><![CDATA[<p>We <a href="http://docs.jboss.com/seam/latest/reference/en-US/html/Book-Preface.html">wprowadzeniu</a> do dokumentacji frameworka <a href="http://www.seamframework.org">JBoss Seam</a> twórcy podkreślają, że uciekają jak tylko się da od konfiguracji za pomocą plików <abbr title="Extensible Markup Language">XML</abbr> na rzecz przekazywania informacji do kontenera za pomocą <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">adnotacji</a>. Nie mniej jednak każdy projekt napisany z pomocą Seam&#8217;a zawiera kilka plików konfiguracyjnych, jednym z nich jest deskryptor stron: <em>pages.xml</em>.</p>
<p>W pliku deskryptora (znajduje się on wewnątrz folderu <em>WEB-INF</em>) mamy możliwość definiowania <a href="http://docs.jboss.com/seam/latest/reference/en-US/html/conversations.html#d0e6182">naturalnych konwersacji</a> (ang. natural conversation), <a href="http://docs.jboss.com/seam/latest/reference/en-US/html/events.html#d0e5611">stron błędów dla wyjątków</a> (ang. exception handling) oraz zasad nawigacji dla stron (ang. page navigation). Ja skupię się na nawigacji.</p>
<p>Pusty deskryptor (zawierający jedynie węzeł główny) wygląda następująco:</p>
<pre class="brush: xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;pages xmlns="http://jboss.com/products/seam/pages"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.com/products/seam/pages
        http://jboss.com/products/seam/pages-2.1.xsd"&gt;
&lt;/pages&gt;</pre>
<p>W deskryptorze możemy umieścić dowolną ilość węzów &lt;page&gt;, które stanowią definicję stron. Podstawowa definicja strony to podanie jej identyfikatora. Definicja taka wiele nie wnosi więc podam od razu przykład jak zdefiniować akcję dla strony (ang. page action):</p>
<pre class="brush: xml; gutter: false;">&lt;page view-id="/testPage.xhtml" action="#{testComponent.sampleAction}"/&gt;</pre>
<p>Tak podana definicja spowoduje wykonanie akcji <em>sampleAction</em> komponentu <em>testComponent</em> tuż przed wyrenderowaniem strony <em>testPage</em>. Oczywiście zawsze istnieje możliwość wykonania kilku akcji (także z różnych komponentów) na okoliczność żądania strony <em>samplePage.xhtml</em>:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml"&gt;
    &lt;action execute="#{testComponent.sampleAction}"/&gt;
    &lt;action execute="#{testComponent.sayHello}"/&gt;
&lt;/page&gt;</pre>
<p>Wykonanie akcji możemy obwarować warunkiem logicznym (zapisanym oczywiście za pomocą języka <a href="http://www.seamframework.org/Documentation/WhatIsAnExpressionLanguageEL">EL</a>). Służy do tego opcjonalny atrybut <em>if</em>, na przykład:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml"&gt;
    &lt;action execute="#{testComponent.sampleAction}"/&gt;
    &lt;action if="#{identity.isLoggedIn}" execute="#{testComponent.sayHello}"/&gt;
&lt;/page&gt;</pre>
<p>Akcje wykonywane są w kolejności zapisania ich w pliku. Ważne jest to by pamiętać o tym, że po każdej akcji realizowane są reguły nawigacji dla strony, co oznacza, że koniec końców nie każda akcja może mieć szanse uruchomienia. A wspomniane reguły definiuje się następująco:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml"&gt;
    &lt;action execute="#{testComponent.sayHello}"/&gt;
    &lt;action execute="#{testComponent.sayHi}"/&gt;

    &lt;navigation&gt;
        &lt;rule if-outcome="hello"&gt;
            &lt;render view-id="/home.xhtml"/&gt;
        &lt;/rule&gt;
        &lt;rule if-outcome="hi"&gt;
            &lt;redirect view-id="/login.xhtml"/&gt;
        &lt;/rule&gt;
    &lt;/navigation&gt;
&lt;/page&gt;</pre>
<p>Każda akcja może zwrócić wartość, wynik (ang. outcome). To właśnie ta wartość posłuży to testowania zasad nawigacji dla strony. Niech komponent <em>testComponent</em>, do którego odwołania występują w przykładach wygląda tak:</p>
<pre class="brush: java;">@Name("testComponent")
public class TestComponent {
    @Logger private Log log;

    public String sayHello() {
        log.info("akcja sayHello zwraca outcome hello");
        return "hello";
    }

    public String sayHi() {
        log.info("akcja sayHi zwraca outcome hi");
        return "hi";
    }
}</pre>
<p>Prześledźmy sytuację. Jeśli zażądamy strony <em>testPage.xhtml</em>, wykonana zostanie akcja <em>sayHello()</em>, której outcome to <em>hello</em>. W tej sytuacji wyrenderowana zostanie strona <em>home.xhtml</em>, co zmieni podmiot odwołania i akcja <em>sayHi()</em> nie będzie miała okazji się uruchomić. Wystarczy jednak zmienić kolejność akcji w pliku aby nastąpiło przekierowanie na stronę logowania &#8211; <em>login.xhtml</em>. Osiągniemy to jeśli najpierw wykona się <em>sayHi()</em>:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml"&gt;
    &lt;action execute="#{testComponent.sayHi}"/&gt;
    &lt;action execute="#{testComponent.sayHello}"/&gt;

    &lt;!-- ... -- &gt;
&lt;/page&gt;</pre>
<p>Podobnie jak w przypadku akcji, reguły nawigacji możemy również obwarować kilkoma obostrzeniami. Przede wszystkim możemy uzależnić wszystkie reguły nawigacji od tego czy to konkretna akcje została wykonana:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml"&gt;
    &lt;!-- ... -- &gt;

    &lt;navigation from-action="#{testComponent.sayHi}"&gt;
        &lt;rule if-outcome="hello"&gt;
            &lt;render view-id="/home.xhtml"/&gt;
        &lt;/rule&gt;
        &lt;rule if-outcome="hi"&gt;
            &lt;redirect view-id="/login.xhtml"/&gt;
        &lt;/rule&gt;
    &lt;/navigation&gt;
&lt;/page&gt;</pre>
<p>Powyższy zapis sprawi, że reguły nawigacji zostaną uwzględnione tylko po wykonaniu akcji <em>sayHi()</em>. To pozwala na zdefiniowanie kilku bloków nawigacji, zależnych od wykonywanych akcji. Dodatkowo możemy w atrybucie <em>evaluate</em> dla elementu <em>navigation</em> umieścić dowolne wyrażenie (<a href="http://www.seamframework.org/Documentation/WhatIsAnExpressionLanguageEL">EL</a>), które ma być wykonane.</p>
<p>Do każdej z zasad nawigacji możemy dodać warunek logiczny, który zostanie sprawdzony tuż obok sprawdzania <em>outcome</em>. Na przykład:</p>
<pre class="brush: xml;">&lt;rule if="#{identity.isLoggedIn}" if-outcome="hello"&gt;
    &lt;render view-id="/home.xhtml"/&gt;
&lt;/rule&gt;</pre>
<p>Deskryptor <em>pages.xml</em> ma również szereg innych możliwości. Jedną z nich jest możliwość nakładania restrykcji na strony. Możemy żądać bycia zalogowanym oraz dodać metodę sprawdzającą dowolną inną rzecz, zdefiniowaną w zewnętrznym komponencie:</p>
<pre class="brush: xml;">&lt;page view-id="/testPage.xhtml" login-required="false"&gt;
    &lt;restrict&gt;#{testComponent.checkMe()}&lt;/restrict&gt;
&lt;/page&gt;</pre>
<p>W przypadku niespełnienia jednego z tych warunków zostanie wyrzucony wyjątek <em>org.jboss.seam.security.NotLoggedInException</em>.</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/03/untitled-2.png"><img class="alignright size-medium wp-image-35" style="margin: 5px;" title="Untitled" src="http://blog.michalmech.pl/wp-content/uploads/2009/03/untitled-2-300x200.png" alt="Untitled" width="300" height="200" /></a>W zasadzie to wszystko co dotyczy nawigacji. Na początku wspomniałem, że pominę konwersacje i skupię się na samym aspekcie nawigacji należy jednak dodać, że pomijając definiowanie naturalnych konwersacji deskryptor daje nam spore możliwości manipulowania konwersacjami wewnątrz mechanizmu nawigacji. Możemy rozpoczynać konwersacje, kończyć je, łączyć z innymi i nie tylko. Możemy również określać parametry stron, reguły ich przekazywania oraz zgłaszać wyjątki czy rozpoczynać lub kończyć zadania w ramach <a href="http://www.jboss.com/products/jbpm">jBPM</a>. Dostępnych jest szereg możliwości, o których na pewno poinformuje nas <a href="http://www.eclipse.org">Eclipse</a> a które ja po zgłębieniu być może opiszę :-)</p>
<p>Na koniec mała podpowiedź, którą pokazuje zamieszczony powyżej zrzut ekranu. Duży projekt, zwierający wiele stron i znaczną ilość definicji bardzo rozepchałby deskryptor stron. Aby zwiększyć czytelność i przejrzystość konfiguracji mamy możliwość zdefiniowana dla każdej strony oddzielnego pliku o nazwie <em>*.page.xml</em>, gdzie <em>*</em> oznacza  identyfikator strony. W przykładach posługiwałem się stroną <em>testPage</em>, plik dla tej strony nazwyałby się <em>testPage.page.xml</em></p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/hZgkAgd6VUw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/03/01/reguly-nawigacji-w-deskryptorze-stron-seama/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/03/01/reguly-nawigacji-w-deskryptorze-stron-seama/</feedburner:origLink></item>
		<item>
		<title>Wstrzykiwanie zależności – serce Seam’a</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/AalzR0qCdkc/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/01/25/wstrzykiwanie-zaleznosci-serce-seama/#comments</comments>
		<pubDate>Sun, 25 Jan 2009 14:49:00 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[JBoss Seam]]></category>

		<guid isPermaLink="false">http://blog.michalme.ayz.pl/?p=7</guid>
		<description><![CDATA[We wstępie do dokumentacji autorzy frameworka JBoss Seam piszą, że jednym ze wzorców, którym hołdowali budując Seam&#8217;a jest wstrzykiwanie zależności (ang. Dependency Injection, DI). Wzorzec DI został nie tylko zastosowany w Seam&#8217;ie ale również rozszerzony i nazwany Bijection.
Bijection od DI różnią trzy cechy:

contextual &#8211; wstrzykiwane do komponentów zależności są wybierane z odpowiedniego kontekstu w jakim [...]]]></description>
			<content:encoded><![CDATA[<p>We <a href="http://docs.jboss.com/seam/latest/reference/en-US/html/Book-Preface.html">wstępie do dokumentacji</a> autorzy frameworka <a title="JBoss Seam" href="http://www.seamframework.org">JBoss Seam</a> piszą, że jednym ze wzorców, którym hołdowali budując Seam&#8217;a jest wstrzykiwanie zależności (ang. Dependency Injection, <abbr title="Dependency Injection">DI</abbr>). Wzorzec <abbr title="Dependency Injection">DI</abbr> został nie tylko zastosowany w Seam&#8217;ie ale również rozszerzony i nazwany Bijection.</p>
<p>Bijection od <abbr title="Dependency Injection">DI</abbr> różnią trzy cechy:</p>
<ol>
<li><em>contextual</em> &#8211; wstrzykiwane do komponentów zależności są wybierane z odpowiedniego <a href="http://docs.jboss.com/seam/latest/reference/en-US/html/concepts.html">kontekstu</a> w jakim występują. Seam posiada kilka kontekstów i zanim wstrzyknie zależność do komponentu szuka jej w odpowiednim miejscu;</li>
<li><em>bidirectional</em> &#8211; mechanizm Bijection pozwala nie tylko na wstrzykiwanie zależności do komponentów ale również na wystrzeliwanie ich na zewnątrz do dowolnego kontekstu;</li>
<li><em>dynamic</em> &#8211; twórcy Seam&#8217;a gwarantują, że mechanizm Bijection jest bardziej elastyczny.</li>
</ol>
<p>Autorzy Seam&#8217;a wyżej cenią <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">adnotacje</a> niż konfigurację za pomocą <abbr title="Extensible Markup Language">XML</abbr>&#8216;a, stąd właśnie one posłużą nam informowaniu kontenera o zależnościach między komponentami i jak powinny być one wstrzykiwane i wystrzeliwane.</p>
<p>Za mechanizm bijection odpowiedzialne są dwie adnotacje: <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/In.html">@In</a> i <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Out.html">@Out</a>. Lecz, żeby dobrze je zrozumieć zacznijmy od prostej adnotacji <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Name.html">@Name</a>. Za pomocą <em>@Name</em> możemy nadać nazwę dowolnemu komponentowi w aplikacji. Nazwa musi być unikalna dla całej aplikacji. Krótki przykład zastosowania:</p>
<pre class="brush: java;">@Entity
@Name("article")
public class Article implements Serializable {

    private long id;

    private String title;

    ...
}</pre>
<p>Jeśli jakiś komponent (lub nawet <a title="Java ServerFaces" href="http://java.sun.com/javaee/javaserverfaces">JSF</a>) odwoła się do obiektu o nazwie <em>article</em>, Seam przeszuka obowiązujący kontekst i dostarczy zależność. W powyższym przykładzie mamy jeszcze adnotację <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Entity.html">@Entity</a>, która w opisywanym zagadnieniu nie gra większej roli. Wskazuje ona, że klasa jest encją reprezentującą trwały obiekt w bazie danych.</p>
<p>Przejdźmy teraz do wstrzykiwania i wystrzeliwania zależności. Oto komponent sesyjny (ang. <a href="http://java.sun.com/j2ee/1.4/docs/tutorial/doc/EJBConcepts3.html">Session Bean</a>), który wykona dla nas trochę logiki biznesowej:</p>
<pre class="brush: java;">@Stateless
@Name("paper")
public class PaperAction implements Paper {
    @In @Out
    private Article article;

    @Out
    private List lt;Articlegt; articles;

    @PersistenceContext
    private EntityManager em;

    public String addArticle () {
        em.persist (article);
        article = new Article ();

        articles = em.createQuery("select a from Article a")
            .getResultList();

        return null;
    }
}</pre>
<p>Adnotacja <a href="http://java.sun.com/javaee/5/docs/api/javax/ejb/Stateless.html">@Stateless</a> informuje nas, że komponent jest bezstanowy co oznacza, że będzie tworzony od nowa za każdym razem kiedy kontener zostanie poproszony o jego dostarczenie. Nazwą komponentu (określoną przez adnotację <em>@Name</em>) jest <em>paper</em>.</p>
<p>Skupmy się teraz na zależnościach. Widzimy przy polu <em>article</em> adnotację <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/In.html">@In</a>. Oznacza to, że zanim zostanie wykonana jakakolwiek metoda komponentu, kontener ma wstrzyknąć do tego pola zależność o nazwie <em>article</em>. Jeśli chcemy do pola <em>article</em> wstrzyknąć zależność o innej nazwie niż pole powinniśmy do adnotacji dodać parametr <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/In.html#value%28%29">value</a>, np.: <em>@In(value=&#8221;favoriteArticle&#8221;)</em> (Adnotacja <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/In.html">@In</a> oraz <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Out.html">@Out</a> posiada kilka innych prostych parametrów. Polecam zapoznanie się z nimi.) Oczywiście komponent może zawierać dowolną ilość elementów z adnotacją <em>@In</em>. Pamiętać należy o tym, że za każdym razem będą one wstrzykiwane.</p>
<p>W dalszej kolejności widzimy adnotacje <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Out.html">@Out</a>, opisujące pola <em>article</em> oraz <em>articles</em>. Oznaczają one, że po zakończeniu pracy komponentu kontener powinien pobrać zawartość tych oraz umieścić w odpowiednich kontekstach. Obiekty te, będą teraz dostępne dla innych komponentów. Zostaną wystrzelone na zewnątrz komponentu.</p>
<p>Komponent <em>paper</em> zawiera jeszcze jedną adnotację: <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/PersistenceContext.html">@PersistenceContext</a>. Informuje ona, że do opisanego za jej pomocą pola kontener ma wstrzyknąć <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html">managera encji</a>. Podobnie jak w przypadku <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Entity.html">@Entity</a> nie jest to w tej chwili meritum sprawy.</p>
<p>Jedyna metoda komponentu <em>addArticle()</em> ma za zadanie zapisać artykuł znajdujący się polu <em>article</em> do bazy danych a później pobrać wszystkie artykuły i zapisać je w polu <em>articles</em>.</p>
<p>Na samym końcu zerknijmy na fragment widoku (<a title="Java ServerFaces" href="http://java.sun.com/javaee/javaserverfaces">JSF</a>), który mógłby służyć do podania tytułu artykułu oraz miałby za zadanie wyświetlić wszystkie inne tytuły artykułów:</p>
<pre class="brush: xml;">&lt;h:form&gt;
    Podaj tytuł artykułu:
    &lt;h:inputText value="#{article.title}"/&gt;
    &lt;h:commandButton type="submit" value="Zapisz" action="#{paper.addArticle}" /&gt;
&lt;/h:form&gt;

&lt;h:dataTable value="#{articles}" var="article"&gt;
    &lt;h:column&gt;
        &lt;h:outputText value="#{article.title}"/&gt;
    &lt;/h:column&gt;
&lt;/h:dataTable&gt;</pre>
<p>A teraz co się stanie kiedy klikniemy <em>Zapisz</em>:</p>
<ol>
<li>Seam postara się odnaleźć dwa komponenty: <em>article</em> oraz <em>paper</em>. Pierwszy jest wymagany ponieważ do komponentu o tej nazwie, a dokładniej do jego pola <em>title</em>, ma być zapisany tytuł wpisany w pole tekstowe. Drugi komponent jest poszukiwany aby wykonać jego metodę <em>addArticle()</em>;</li>
<li>Oba komponenty zostaną utworzone ponieważ nie ma ich w żadnym kontekście. Article jest encją, w której zapiszemy dane z formularza a <em>paper</em> jest komponentem bezstanowym, który wykona trochę logiki;</li>
<li>Zostanie wykonana akcja a po jej zakończeniu pola oznaczone za pomocą <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Out.html">@Out</a> zostaną wystrzelone do kontenera, dzięki czemu będą dostępne dla innych komponentów oraz dla widoku.</li>
</ol>
<p>Zastosowana w widoku notacja <em>#{&#8230;}</em> to <a title="Expression Language" href="http://www.seamframework.org/Documentation/WhatIsAnExpressionLanguageEL">Expression Language</a> (<abbr title="Expression Language">EL</abbr>), na który polecam zwrócić uwagę ponieważ jest wykorzystywany w Seam&#8217;ie niemal wszędzie gdzie się da.</p>
<p>Na koniec dodatkowa, ważna informacja. Za pomocą <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/In.html">@In</a> oraz <a href="http://docs.jboss.com/seam/2.1.1.GA/api/org/jboss/seam/annotations/Out.html">@Out</a> możemy adnotować również metody aby osiągnąć identyczny efekt jak w powyższym, przykładowym komponencie. Oto przykład jak wyglądałby komponent <em>paper</em>, gdybym adnotacji użył do opisania metod:</p>
<pre class="brush: java;">@Stateless
@Name("paper")
public class PaperAction {
    private Article article;

    private List lt;Articlegt; articles;

    @PersistenceContext
    private EntityManager em;

    public String addArticle () {
        em.persist (article);
        article = new Article ();

        articles = em.createQuery("select a from Article a")
            .getResultList();

        return null;
    }

    @In
    public function void setArticle(Article article) {
        this.article = article;
    }

    @Out
    public function Article getArticle() {
        return article;
    }

    @Out
    public function List lt;Articlegt; getArticles() {
        return articles;
    }
}</pre>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/AalzR0qCdkc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/01/25/wstrzykiwanie-zaleznosci-serce-seama/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/01/25/wstrzykiwanie-zaleznosci-serce-seama/</feedburner:origLink></item>
		<item>
		<title>JBoss Tools – wsparcie dla Seam’a w Eclipse</title>
		<link>http://feedproxy.google.com/~r/MichalMech-WStroneJ2EE/~3/R6TxUHdqjNg/</link>
		<comments>http://blog.michalmech.pl/index.php/2009/01/23/jboss-tools-wsparcie-dla-seama-w-eclipse/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 18:47:00 +0000</pubDate>
		<dc:creator>Michał Mech</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[JBoss Seam]]></category>
		<category><![CDATA[JBoss Toos]]></category>
		<category><![CDATA[seam-gen]]></category>

		<guid isPermaLink="false">http://blog.michalme.ayz.pl/?p=6</guid>
		<description><![CDATA[W poprzednim poście utworzyłem pierwszy projekt (HelloWorld) za pomocą seam-gen. Spróbujmy teraz skonfigurować sobie środowisko dla tego oraz innych projektów Seam&#8216;owych.
Firma JBoss przyszła nam z pomocą i stworzyła JBoss Tools, czyli zestaw narzędzi dla Eclipse, które wspomagają pracę z frameworkiem JBoss Seam. Najszybszy sposób instalacji narzędzi wiedzie nas przez Update Manager&#8217;a, gdzie podajemy odpowiedni link [...]]]></description>
			<content:encoded><![CDATA[<p>W poprzednim poście utworzyłem pierwszy projekt (<em>HelloWorld</em>) za pomocą <a href="http://docs.jboss.org/seam/latest/reference/en-US/html/gettingstarted.html">seam-gen</a>. Spróbujmy teraz skonfigurować sobie środowisko dla tego oraz innych projektów <a title="JBoss Seam" href="http://www.seamframework.org/">Seam</a>&#8216;owych.</p>
<p>Firma <a title="JBoss" href="http://jboss.com">JBoss</a> przyszła nam z pomocą i stworzyła <a title="JBoss Tools" href="http://www.jboss.org/tools">JBoss Tools</a>, czyli zestaw narzędzi dla <a title="Eclipse" href="http://www.eclipse.org">Eclipse</a>, które wspomagają pracę z frameworkiem JBoss Seam. Najszybszy sposób instalacji narzędzi wiedzie nas przez Update Manager&#8217;a, gdzie podajemy odpowiedni link i instalujemy wybrane narzędzia. Zestaw JBoss Tools poza wsparcie dla Seam&#8217;a zawiera narzędzia pomocne przy pracy między innymi z <a href="http://www.jboss.org/jbossjbpm">jBPM</a>, <a title="Hibernate" href="http://www.hibernate.org">Hibernate</a>, <a title="Apache Struts" href="http://struts.apache.org">Struts</a>. Jeśli mamy już zainstalowany pakiet JBoss Tools, zabieramy się do pracy.</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/01/helloworld_in_packageexplorer.gif"><img class="size-medium wp-image-28 alignright" style="margin: 5px;" title="HelloWorld in Package Explorer" src="http://blog.michalmech.pl/wp-content/uploads/2009/01/helloworld_in_packageexplorer-129x300.gif" alt="HelloWorld in Package Explorer" width="129" height="300" /></a>W pierwszej kolejności importujemy projekt do Eclipse&#8217;a. Wybieramy <em>File  &gt; Import  &gt; Existing Projects into Workspace</em> i szukamy projektu. Po poprawnym imporcie projekt <em>HelloWorld</em> powinien pojawić się w naszym eksploratorze paczek (ang. <em>Package Explorer</em>).</p>
<p>Następnie przełączamy perspektywę na <em>Seam</em> i przechodzimy do konfiguracji projektu. W sekcji <em>Seam Settings</em> w pierwszej kolejności zaznaczamy <em>Seam support</em> dalej przechodzimy do konfiguracji środowiska uruchomieniowego JBoss Seam &#8211; <em>Seam runtime</em>. W tym celu klikamy <em>Add</em> i w oknie, które się pojawi podajemy folder domowy Seam&#8217;a (<em>C:\Program Files\JBoss-seam-2.1.1.GA</em>), nazwę konfiguracji (np.: <em>Seam runtime</em>) oraz wersję frameworka (<em>2.0</em>).</p>
<p>W dalszej kolejności dodajemy i konfigurujemy połączenie z bazą danych projektu (<em>Connection profile</em>). Klikamy <em>New&#8230;</em> i w okienku podajemy wszystkie wymagane dane takie jak nazwę połączenia (np.: <em>hello database</em>) typ bazy, dane do połączenia, ścieżkę do sterownika, e.t.c. Poniżej prezentuję zrzut ekranu ukazujący ustawienia dla mojego projektu.</p>
<p><a href="http://blog.michalmech.pl/wp-content/uploads/2009/01/helloworld_settings.gif"><img class="aligncenter size-medium wp-image-29" title="HelloWorld settings" src="http://blog.michalmech.pl/wp-content/uploads/2009/01/helloworld_settings-263x300.gif" alt="HelloWorld settings" width="263" height="300" /></a></p>
<p>Pakiet narzędzi JBoss Tools pozwala również na utworzenie projektu bez korzystania z <em>seam-gen</em>&#8216;a. Wybieramy <em>File  &gt; New  &gt; Seam Web Project</em>. Kreator przeprowadzi nas przez proces konfiguracji projektu podczas, którego możemy utworzyć konfigurację serwera, połączenia do bazy danych i środowiska uruchomieniowego.</p>
<p>Dzięki JBoss Tools mamy możliwość szybkiego tworzenia encji, akcji, konwersacji, e.t.c. Narzędzie to jest między innymi nakładką na seam-gen&#8217;a. Ponadto dostajemy kilka dodatkowych edytorów (np.: dla <a href="https://facelets.dev.java.net">facelets</a>) oraz ładne widoki deskryptorów. Postaram się dostarczać więcej informacji wraz z poznawaniem JBoss Tools&#8217;ów.</p>
<img src="http://feeds.feedburner.com/~r/MichalMech-WStroneJ2EE/~4/R6TxUHdqjNg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.michalmech.pl/index.php/2009/01/23/jboss-tools-wsparcie-dla-seama-w-eclipse/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.michalmech.pl/index.php/2009/01/23/jboss-tools-wsparcie-dla-seama-w-eclipse/</feedburner:origLink></item>
	</channel>
</rss>
