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

<channel>
	<title>blog.smart-java.nl &#187; Michel.Schudel</title>
	<atom:link href="http://blog.smart-java.nl/blog/index.php/author/michelschudel/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.smart-java.nl/blog</link>
	<description>Ordina J-Technologies - Java Blog</description>
	<lastBuildDate>Wed, 05 May 2010 20:06:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>DefaultMessageListenerContainer troubles in Websphere</title>
		<link>http://blog.smart-java.nl/blog/index.php/2010/02/03/defaultmessagelistenercontainer-troubles-in-websphere/</link>
		<comments>http://blog.smart-java.nl/blog/index.php/2010/02/03/defaultmessagelistenercontainer-troubles-in-websphere/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 14:19:57 +0000</pubDate>
		<dc:creator>Michel.Schudel</dc:creator>
				<category><![CDATA[Algemeen]]></category>
		<category><![CDATA[jms]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[Websphere]]></category>

		<guid isPermaLink="false">http://blog.smart-java.nl/blog/?p=859</guid>
		<description><![CDATA[Using the Spring DefaultMessageListenerContainer makes it easy for you to connect to a jms resource like a Queue so you can pick up messages from that queue.
Using this container in Websphere (6.0, 6.1, 7) some problems occur when you want to do the following:

You use a resource environment reference for your destination, specified in the [...]]]></description>
			<content:encoded><![CDATA[<p>Using the Spring <code>DefaultMessageListenerContainer</code> makes it easy for you to connect to a jms resource like a Queue so you can pick up messages from that queue.</p>
<p>Using this container in Websphere (6.0, 6.1, 7) some problems occur when you want to do the following:</p>
<ul>
<li>You use a resource environment reference for your destination, specified in the web.xml, for the Destination.</li>
<li>You use the property <code>destinationName</code> on the <code>DefaultMessageListenerContainer</code> in combination with a <code>JndiDestinationResolver</code> to look up your resource environment reference like this: <code>java:comp/env/jms/(your destination)</code></li>
</ul>
<p><strong>problem</strong><br />
When you try to start the application, you will get an exception like this: <code>javax.naming.NameNotFoundException: Name "comp/env/jms/(your destination)" not found in context "java:".</code>, although you are sure that your resource environment reference is defined correctly.</p>
<p><strong>cause</strong><br />
The cause of this problem lies in the fact that the lookup occurs in a Thread started by the <code>DefaultMessageListenerContainer</code>, which is unmanaged by Websphere. This thread will not have the jndi queue bindings in its <code>InitialContext</code>.</p>
<p><strong>solution</strong><br />
You can either:</p>
<ol>
<li>Specifiy the jndi object beforehand with a <code>JndiObjectFactoryBean</code>, or a <code><br />
  &lt;jee:jndi-lookup id="myqueue" jndi-name="java:comp/env/jms/(your destination)"/&gt;</code>, and then<br />
  setting the <code>destination</code> property of the <code>DefaultMessageListenerContainer</code> to the ref <code>myqueue</code>, so no actual lookup occurs within the thread of the listener itself.</li>
<li>
  Delegate the listener&#8217;s thread to Websphere with the help of the Spring class <code>WorkManagerTaskExecutor</code>. You can then set the property <code>taskExecutor</code> on the message listener container to reference this class. See the <a href="http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html">IBM article here </a> for details on how to do this.
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.smart-java.nl/blog/index.php/2010/02/03/defaultmessagelistenercontainer-troubles-in-websphere/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Annotation based value injection in Spring 2.5</title>
		<link>http://blog.smart-java.nl/blog/index.php/2009/07/14/annotation-based-value-injection-in-spring-25/</link>
		<comments>http://blog.smart-java.nl/blog/index.php/2009/07/14/annotation-based-value-injection-in-spring-25/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 08:47:04 +0000</pubDate>
		<dc:creator>Michel.Schudel</dc:creator>
				<category><![CDATA[Algemeen]]></category>

		<guid isPermaLink="false">http://blog.smart-java.nl/blog/?p=484</guid>
		<description><![CDATA[De &#60;component-scan&#62; Spring configuratie geeft je de mogelijkheid om je java beans te annoteren met @Component, @Service, @Repository, etc. Als Spring wordt opgestart zullen deze beans automatisch door Spring worden opgetuigd. Je hoeft dan geen beandefinitie meer in je applicationContext op te nemen. Zie ook hier voor meer informatie.
Alles goed en wel, maar wat nu [...]]]></description>
			<content:encoded><![CDATA[<p>De <code>&lt;component-scan&gt;</code> Spring configuratie geeft je de mogelijkheid om je java beans te annoteren met <code>@Component</code>, <code>@Service</code>, <code>@Repository</code>, etc. Als Spring wordt opgestart zullen deze beans automatisch door Spring worden opgetuigd. Je hoeft dan geen beandefinitie meer in je applicationContext op te nemen. Zie ook <a href="http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning">hier</a> voor meer informatie.</p>
<p>Alles goed en wel, maar wat nu als je component, behalve referenties naar andere beans, ook simpele String en Integer values nodig heeft? De enige mogelijkheid die tot nu toe had is de beandefinitie alsnog in je applicationContext op te nemen.</p>
<p>Spring 3.0 krijgt gelukkig de annotatie <code>@Value</code> waarmee je dit kan bereiken. Je kan dan je method als volgt annoteren:<br />
<code><br />
@Value("#{my.property}")<br />
public void setDezeProperty(String myProperty)  {<br />
  ...<br />
}<br />
</code></p>
<p>In Spring 2.5 bestaat deze voorziening nog niet, maar <a href="http://stackoverflow.com/questions/317687/inject-property-value-into-spring-bean/577266#577266">Op StackOverflow</a> heeft iemand een <code>PropertyAnnotationPlaceholderConfigurer</code> geschreven die precies hetzelfde doet.</p>
<p>In Spring 2.5 kan je dan je method als volgt annoteren:<br />
<code><br />
@Property(value="my.property")<br />
public void setDezeProperty(String myProperty)  {<br />
  ...<br />
}<br />
</code></p>
<p>Waarbij <code>my.property</code> dan de naam van een property is die uit een property file komt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.smart-java.nl/blog/index.php/2009/07/14/annotation-based-value-injection-in-spring-25/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Activering van je Spring beans configurabel maken</title>
		<link>http://blog.smart-java.nl/blog/index.php/2008/06/27/activering-van-je-spring-beans-configurabel-maken/</link>
		<comments>http://blog.smart-java.nl/blog/index.php/2008/06/27/activering-van-je-spring-beans-configurabel-maken/#comments</comments>
		<pubDate>Fri, 27 Jun 2008 12:16:56 +0000</pubDate>
		<dc:creator>Michel.Schudel</dc:creator>
				<category><![CDATA[Algemeen]]></category>
		<category><![CDATA[Tools/Frameworks]]></category>
		<category><![CDATA[jms]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://blog.smart-java.nl/?p=37</guid>
		<description><![CDATA[Op een huidig project werken we aan een routeringscomponent waarin een aantal JMS listeners en endpoints hangen. Er komen berichten op de listeners binnen, die gerouteerd moeten worden naar een endpoint. Nu kan je voor ESB-achtige oplossingen beter terecht bij opensource producten als Mule of ServiceMix, maar daar wil ik het niet over hebben.
De listeners [...]]]></description>
			<content:encoded><![CDATA[<p>Op een huidig project werken we aan een routeringscomponent waarin een aantal JMS listeners en endpoints hangen. Er komen berichten op de listeners binnen, die gerouteerd moeten worden naar een endpoint. Nu kan je voor ESB-achtige oplossingen beter terecht bij opensource producten als <a href="http://mule.mulesource.org/">Mule</a> of <a href="http://servicemix.apache.org/">ServiceMix</a>, maar daar wil ik het niet over hebben.</p>
<p>De listeners zijn geimplementeerd met Spring <code>MessageListenerContainer</code> types, en staan gewired in de Spring applicatie context:</p>
<pre class="java">
  &lt;bean id="myMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
  ...properties..
&lt;/bean&gt;
</pre>
<p>Het issue is nu dat de JMS listeners dienen in bepaalde omgevingen (zoals een aantal acceptatie en productie omgevingen) geactiveerd dienen te worden, en in andere omgevingen niet. Dit moet op zo&#8217;n manier kunnen dat het voor een beheer organisatie gemakkelijk is deze componenten aan en uit te zetten.</p>
<p>Je kan een Spring component natuurlijk uitcommentarieren in de applicationContext, maar je wilt een beheerclub eigenlijk niet opzadelen met zo&#8217;n taak, omdat deze taak vrij technisch is en behoorlijk foutgevoelig. Bovendien wil je niet dat beheer in je applicatie wiring wijzigingen gaat zitten maken. Import / configuratie van verschillende applicationContexts in verschillende omgevingen levert ook teveel overhead op.</p>
<p>Hoe maken we dit nu toch beheersbaar?</p>
<p>Een mogelijkheid zou zijn om het <code>lazy-init</code> attribuut van een Spring bean te wijzigen. Voor een bean als een <code>MessageListenerContainer</code> zou dit betekenen dat in het geval van <code>lazy-init="true"</code> de bean nooit wordt opgetuigd, aangezien er geen andere beans zijn die een referentie naar deze bean hebben.</p>
<pre class="java">
  &lt;bean id="myMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" lazy-init="true"&gt;
  ...properties..
&lt;/bean&gt;
</pre>
<p>Echter levert dit nog steeds geen configurabel component voor beheer op, in het bovenstaande voorbeeld wordt de bean nooit gestart. Je zou geneigd zijn om te zeggen: los het met een externe property op:</p>
<pre class="java">
  &lt;bean id="myMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" lazy-init="${myListener.enabled}"&gt;
  ...properties..
&lt;/bean&gt;
</pre>
<p>De <code>PropertyPlaceholderConfigurer</code> postprocessor kan dit echter niet aan, aangezien deze wel in kan grijpen na de constructie van het object maar niet ervoor. Er is ook geen mogelijkheid om via een eigen geschreven postprocessor het aanroepen van een <code>init</code> methode op een bean (wat in het geval van een <code>MessageListenerContainer</code> daadwerkelijk de JMS connnectie opzet) te onderdrukken.</p>
<p>Om toch het issue te kunnen oplossen heb ik een <code>ConditionalInstantiationBean</code> geschreven, die op basis van een <code>beanName</code> string property en een <code>instantiate</code> boolean een Spring bean uit de context ophaalt, waardoor deze geconstrueerd en geinitializeerd wordt:</p>
<pre class="java">
package nl.project.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;

/**
 * A Spring bean-factory-aware bean that will onyl instantiate the bean with
 * name beanName if the property instantiate is set to true. Use this bean for
 * being able to control instantiation of beans depending on a true|false value
 * that is imported as a property from an external property file.
 *
 * It is not possible to do this with the "lazy-init" because you cannot switch
 * this value with an external property.
 *
 */
public class ConditionalInstantiationBean implements BeanFactoryAware,
        InitializingBean {

    /** Logger available to subclasses */
    protected final Log logger = LogFactory.getLog(getClass());

    private BeanFactory beanFactory;

    private String beanName;

    private boolean instantiate;

    /**
     * Will instantiate the target bean defined by beanName if instantiate is
     * set to true.
     */
    public void afterPropertiesSet() throws Exception {
        if (instantiate) {
            if (logger.isDebugEnabled()) {
                logger.debug("Instantiating bean with name '" + beanName + "'");
            }
            //keeping result is not necessary since we only want to instantiate
            // the bean.
            beanFactory.getBean(beanName);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("Skipping instantiation of bean with name '"
                        + beanName + "'");
            }

        }
    }

    /*
     * (non-Javadoc)
     *
     * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
     */
    public void setBeanFactory(BeanFactory bf) throws BeansException {
        this.beanFactory = bf;
    }

    /**
     * @param beanName
     *            The beanName to set.
     */
    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    /**
     * @param instantiate
     *            The instantiate to set.
     */
    public void setInstantiate(boolean instantiate) {
        this.instantiate = instantiate;
    }
}
</pre>
<p>En hieronder de Spring configuratie:</p>
<pre class="java">
  &lt;bean id="conditionalInstantiationBean" class="nl.project.util.ConditionalInstantiationBean"&gt;
    &lt;property name="beanName" value="myMessageListenerContainer"/&gt;
    &lt;property name="instantiate" value="${listener.enabled}"/&gt;
&lt;/bean&gt;
</pre>
<p>Hierbij de volgende toelichting:</p>
<ul>
<li>De property <code>beanName</code> is een <b>String</b> en geen referentie naar de listener. Een referentie zou immers betekenen dat de listener bean automatisch wordt opgetuigd! </li>
<li>De property <code>instantiate</code> kan nu met een <code>PropertyPlaceholderConfigurer</code> geexternaliseerd worden, bijvoorbeeld in een property file. In de property file komt dan een <code>listener.enabled</code> property die door een beheerclub aan-en uitgezet kan worden!</li>
<li>Het <code>lazy-init</code> attribuut van de listener dient wel op <i>true</i> te worden gezet, om automatische activering van de bean te voorkomen:</li>
<pre class="java">
  &lt;bean id="myMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" lazy-init="true"&gt;
  ...properties..
&lt;/bean&gt;
</pre>
</ul>
<p>Verbeteringen zouden nog zijn: testen of de target bean wel &#8220;lazy&#8221; geinitialiseerd wordt, aangezien anders de <code>ConditionalInstantiationBean</code> natuurlijk niets te doen heeft.<br />
Ik kan me ook voorstellen dat iemand een mooie AOP oplossing voor dit issue heeft. Als dat zo is, hoor ik het graag!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.smart-java.nl/blog/index.php/2008/06/27/activering-van-je-spring-beans-configurabel-maken/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Manage je Digesters met Spring</title>
		<link>http://blog.smart-java.nl/blog/index.php/2008/02/21/manage-je-digesters-met-spring/</link>
		<comments>http://blog.smart-java.nl/blog/index.php/2008/02/21/manage-je-digesters-met-spring/#comments</comments>
		<pubDate>Thu, 21 Feb 2008 13:03:30 +0000</pubDate>
		<dc:creator>Michel.Schudel</dc:creator>
				<category><![CDATA[Tools/Frameworks]]></category>

		<guid isPermaLink="false">http://blog.smart-java.nl/?p=15</guid>
		<description><![CDATA[Iedereen heeft wel eens een Java bean die op startup time van je applicatie geconfigureerd dient te worden. Het Spring framework biedt je uiteraard die mogelijkheid in de vorm van de IoC container, waarmee je met behulp van &#60;bean&#62; declaraties beans eenvoudig kan optuigen. Zelfs als de beanconfiguratie iets complexer wordt, kan je met &#60;list&#62;, [...]]]></description>
			<content:encoded><![CDATA[<p>Iedereen heeft wel eens een Java bean die op startup time van je applicatie geconfigureerd dient te worden. Het Spring framework biedt je uiteraard die mogelijkheid in de vorm van de IoC container, waarmee je met behulp van <strong>&lt;bean&gt;</strong> declaraties beans eenvoudig kan optuigen. Zelfs als de beanconfiguratie iets complexer wordt, kan je met <strong>&lt;list&gt;</strong>, <strong>&lt;map&gt;</strong>, <strong>&lt;set&gt;</strong> en geneste <strong>&lt;bean&gt;</strong> tags een aardig &#8220;boompje&#8221; opbouwen.</p>
<p>Wat lastiger wordt het als je meer xml-to-object achtige configuraties wil gaan toepassen waarbij de mapping van xml naar object(en) niet altijd triviaal of 1-op-1 is. Nu biedt Apache daar een prima oplossing voor in de vorm van <a href="http://commons.apache.org/digester/">Commons Digester</a>, een component die een xml configuratie, aan de hand van een set van <em>rules</em>, je java objecten gaat instantieren. Voor de precieze werking van Digester kan je terecht bij de betreffende Apache site.</p>
<p>De logica om de Digester te initializeren zie ik nog steeds vaak in de code zelf staan. In dit artikeltje gaan we de initialisatie van Digesters en het parsen van input xmls geheel aan Spring uitbesteden.</p>
<p>We pakken een voorbeeldje waarin vanuit een xml structuur met films een java bean genaamd <code>FilmCollectie</code> wordt gemaakt met daarin een lijst van <code>Film</code> beans. Uiteraard zou dit eenvoudige voorbeeld ook met normale Spring bean configuratie kunnen, maar gaat gaat even om het idee dat we een Digester willen gebruiken.</p>
<p>In code wordt vaak onderstaande structuur gebruikt om een Digester te initialiseren en xml te parsen:</p>
<pre class="java">
InputStream is = getClass().getResourceAsStream("movies.xml");<br/>
Digester digester = new Digester();<br/>
digester.addObjectCreate("mijnFilms", FilmCollectie.class);<br/>
digester.addObjectCreate("mijnFilms/film", Film.class);<br/>
digester.addBeanPropertySetter("mijnFilms/film/titel", "titel");<br/>
digester.addSetNext("mijnFilms/film", "addFilm");<br/>
FilmCollectie mijnCollectie = (FilmCollectie) digester.parse(is.getInputStream());<br/>
</pre>
<p>Het enige wat ik als developer wil gebruiken is de uiteindelijke <code>FilmCollectie</code> (die op de laatste regel beschikbaar komt). We willen nu Spring verantwoordelijk maken voor het initialiseren van de Digester en het parsen van de input xml.</p>
<p>In het voorbeeld definieren we eerst, voor de volledigheid, een client die gebruik gaat maken van de objecttree met films:</p>
<pre class="java">
<font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"movieManager" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"MovieManager"</font><font size="2" color="#008080">&gt;</font></font>
&nbsp;&nbsp;<font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">property </font><font size="2" color="#7f007f">name</font><font size="2">=</font><font size="2" color="#2a00ff">"movies" </font><font size="2" color="#7f007f">ref</font><font size="2">=</font><font size="2" color="#2a00ff">"movies"</font><font size="2" color="#008080">/&gt;</font></font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font></font></font>
<br/><br/>
</pre>
<p>We willen graag zowel de Digester rules als de input van het file system trekken. De input data zou er als volgt uit kunnen zien:</p>
<pre class="java">
&lt;mijnFilms&gt;<br/>
&lt;film&gt;<br/>
&lt;titel&gt;Persepolis&lt;/titel&gt;<br/>
&lt;/film&gt;<br/>
&lt;film&gt; <br/>
&lt;titel&gt;American Gangster&lt;/titel&gt;<br/>
&lt;/film&gt;<br/>
&lt;/mijnFilms&gt;<br/>
</pre>
<p>En de digester rules als volgt:</p>
<pre class="java">
&lt;digester-rules&gt;<br/>
&nbsp;&nbsp;&lt;object-create-rule pattern="mijnFilms" classname="FilmCollectien"/&gt;<br/>
&nbsp;&nbsp;&lt;object-create-rule pattern="mijnFilms/film" classname="Film"/&gt;<br/>
&nbsp;&nbsp;&lt;property-setter-rule pattern="mijnFilms/film/titel" name="titel"/&gt;<br/>
&nbsp;&nbsp;&lt;add-set-next-rule pattern="mijnFilms/film method="addFilm"/&gt;<br/>
&lt;/digester-rules&gt;<br/>
</pre>
<p>Nu heeft de Digester component een <code>DigesterLoader</code> factory aan boord die je in staat stelt met een factory method je gewenste bean plus onderliggende beans op te leveren:<code><strong>static</strong> Object load(URL digesterRules, ClassLoader classLoader, InputStream input)</code><br />
Deze factory willen we graag gebruiken in Spring op de objecttree op te leveren.<br />
Nu dient de Digester opgetuigd te worden. Omdat de <code>DigesterLoader</code> een factory is, dienen we die ook zo in Spring te configureren. Voor het gemak vullen we even een <code>null</code> is voor het tweede argument (de classloader).</p>
<pre class="java">
<font size="2" color="#008080">&lt;<font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"movies" </font><font size="2" color="#7f007f">factory-method</font><font size="2">=</font><font size="2" color="#2a00ff">"load" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.apache.commons.digester.xmlrules.DigesterLoader"</font><font size="2" color="#008080">&gt;</font></font>
<font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">ref</font><font size="2">=</font><font size="2" color="#2a00ff">"...een url..."</font><font size="2" color="#008080">/&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg</font><font size="2" color="#008080">&gt;&lt;</font><font size="2" color="#3f7f7f">null</font><font size="2" color="#008080">/&gt;&lt;/</font><font size="2" color="#3f7f7f">constructor-arg</font><font size="2" color="#008080">&gt;</font> </font></font>
<font size="2"><font size="2">  &lt;</font></font><font size="2"><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">ref</font><font size="2">=</font><font size="2" color="#2a00ff">"...een inputStream..."</font><font size="2" color="#008080">/&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font></font>
<br/><br/>
</pre>
<p>Het probleem is nu: de <code>load</code> method verwacht een <code>URL</code> en een <code>InputStream</code> als constructor arguments van de factory method. Spring geeft je wel de mogelijkheid om Resources te definieren, die een eenduidige manier van omgaan met low-level resources implementeren.</p>
<p>We definieren twee resources voor de digester-rules en de xml input. De xml bestanden worden in dit voorbeeld van het classpath geladen.</p>
<pre class="java">
<font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"digesterRulesResource" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.springframework.core.io.ClassPathResource"</font><font size="2" color="#008080">&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"digester-rules.xml"</font><font size="2" color="#008080">/&gt;</font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"xmlInputResource" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.springframework.core.io.ClassPathResource"</font><font size="2" color="#008080">&gt;</font></font></font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"movies.xml"</font><font size="2" color="#008080">/&gt;</font></font></font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font></font></font></font></font>
<br/><br/>
</pre>
<p>We hebben nu twee Resources die de digester rules en input xml bestanden representeren. Hoe komen we nu aan een InputStream en een URL die voor de DigesterLoader nodig is?</p>
<p>Spring heeft een bean genaamd <code>PropertyPathFactoryBean</code> waarmee je een bean kan optuigen die eigenlijk een property van een andere bean is. Omdat een <code>Resource </code>de methods <code><strong>getURL()</strong></code> en <code><strong>getInputStream()</strong></code> heeft, kunnen we met behulp van deze Spring bean de URL en InputStream uit de Resources halen.</p>
<pre class="java">
<font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"xmlInputStream" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.springframework.beans.factory.config.PropertyPathFactoryBean"</font><font size="2" color="#008080">&gt;</font></font>
<font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">property </font><font size="2" color="#7f007f">name</font><font size="2">=</font><font size="2" color="#2a00ff">"targetBeanName" </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"xmlInputResource"</font><font size="2" color="#008080">/&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">property </font><font size="2" color="#7f007f">name</font><font size="2">=</font><font size="2" color="#2a00ff">"propertyPath" </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"inputStream"</font><font size="2" color="#008080">/&gt;</font></font></font>
<font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#3f7f7f">&lt;bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"digesterRulesURL" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.springframework.beans.factory.config.PropertyPathFactoryBean"</font><font size="2" color="#008080">&gt;</font></font></font>
<font size="2"><font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">property </font><font size="2" color="#7f007f">name</font><font size="2">=</font><font size="2" color="#2a00ff">"targetBeanName" </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"digesterResource"</font><font size="2" color="#008080">/&gt;</font></font></font>
<font size="2"><font size="2"><font size="2"><font size="2" color="#008080">&lt;</font><font size="2" color="#3f7f7f">property </font><font size="2" color="#7f007f">name</font><font size="2">=</font><font size="2" color="#2a00ff">"propertyPath" </font><font size="2" color="#7f007f">value</font><font size="2">=</font><font size="2" color="#2a00ff">"URL"</font><font size="2" color="#008080">/&gt;</font></font></font></font>
<font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font><font size="2" color="#008080"> <font size="2" color="#008080"> </font></font><font size="2" color="#008080"><font size="2" color="#008080"> </font></font></font>
<br/><br/>
</pre>
<p>Het resultaat van bovenstaande declaratie is een bean met naam <code><strong>xmlInputStream</strong></code> van type <code><strong>InputStream</strong></code> en een bean met naam <code><strong>digesterURL</strong></code> met type <code><strong>URL</strong></code>. Deze beans kunnen nu geinjecteerd worden in de <code>movies</code> bean.</p>
<pre class="java">
<font size="2" color="#008080">&lt;<font size="2" color="#3f7f7f">bean </font><font size="2" color="#7f007f">id</font><font size="2">=</font><font size="2" color="#2a00ff">"movies" </font><font size="2" color="#7f007f">factory-method</font><font size="2">=</font><font size="2" color="#2a00ff">"load" </font><font size="2" color="#7f007f">class</font><font size="2">=</font><font size="2" color="#2a00ff">"org.apache.commons.digester.xmlrules.DigesterLoader"</font><font size="2" color="#008080">&gt;</font></font>
<font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">ref</font><font size="2">=</font><font size="2" color="#2a00ff">"digesterRulesURL"</font><font size="2" color="#008080">/&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">  &lt;</font><font size="2" color="#3f7f7f">constructor-arg</font><font size="2" color="#008080">&gt;&lt;</font><font size="2" color="#3f7f7f">null</font><font size="2" color="#008080">/&gt;&lt;/</font><font size="2" color="#3f7f7f">constructor-arg</font><font size="2" color="#008080">&gt;</font> </font></font>
<font size="2"><font size="2">  &lt;</font></font><font size="2"><font size="2" color="#3f7f7f">constructor-arg </font><font size="2" color="#7f007f">ref</font><font size="2">=</font><font size="2" color="#2a00ff">"xmlInputStream"</font><font size="2" color="#008080">/&gt;</font></font>
<font size="2"><font size="2"><font size="2" color="#008080">&lt;/</font><font size="2" color="#3f7f7f">bean</font><font size="2" color="#008080">&gt;</font></font></font>
<br/><br/>
</pre>
<p>Het resultaat hiervan is een <code>MovieManager</code> die een property <code>movies</code> heeft van het type <code>FilmCollectie</code>. Dit object is gemaakt met behulp van de Digester zonder een letter Java code te schrijven voor het optuigen van de digester en het parsen van een input bestand. Met behulp van de <code>PropertyPathFactoryBean</code> kunnen we de InputStream en URL van elke willekeurige resource halen. De digester rules en input xml kunnen bijvoorbeeld ook in de applicationContext zelf worden opgenomen.</p>
<p>Verder zijn er natuurlijk mogelijkheden tot verkorte schrijfwijze van de PropertyFactoryBean waarvoor ik verwijs naar de <a href="http://static.springframework.org/spring/docs/2.0.x/reference/xsd-config.html">Spring Appendix</a>.</p>
<p></font></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.smart-java.nl/blog/index.php/2008/02/21/manage-je-digesters-met-spring/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
