<?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/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Spring &#8211; Jiří Kratochvíl</title>
	<atom:link href="https://jiri.kratochvil.eu/tag/spring/feed/" rel="self" type="application/rss+xml" />
	<link>https://jiri.kratochvil.eu</link>
	<description>Kráťovo občasník</description>
	<lastBuildDate>Tue, 29 Mar 2011 19:03:46 +0000</lastBuildDate>
	<language>cs</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.1</generator>

<image>
	<url>https://jiri.kratochvil.eu/wp-content/uploads/2018/10/kratochvil-logo-100x100.png</url>
	<title>Spring &#8211; Jiří Kratochvíl</title>
	<link>https://jiri.kratochvil.eu</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">10187198</site>	<item>
		<title>Testování JMS v unit testech</title>
		<link>https://jiri.kratochvil.eu/testovani-jms-v-unit-testech/</link>
					<comments>https://jiri.kratochvil.eu/testovani-jms-v-unit-testech/#respond</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Tue, 29 Mar 2011 19:03:46 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Návody]]></category>
		<category><![CDATA[Programování]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[JMS]]></category>
		<category><![CDATA[JNDI]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Messaging]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Tipy]]></category>
		<category><![CDATA[Transaction Manager]]></category>
		<category><![CDATA[Unit test]]></category>
		<category><![CDATA[Weblogic]]></category>
		<guid isPermaLink="false">http://jiri.kratochvil.eu/?p=389</guid>

					<description><![CDATA[Dnes jsem strávil skoro celý den tím, že jsem potřeboval vyřešit následující problém. Mám aplikaci, která poměrně sofistikovaně využívá několik JMS front pro asynchronní zpracování [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Dnes jsem strávil skoro celý den tím, že jsem potřeboval vyřešit následující problém. Mám aplikaci, která poměrně sofistikovaně využívá několik JMS front pro asynchronní zpracování požadavků z klientských aplikací. Celé je to postavené nad serverem Weblogic a aplikace využívá frameworku Spring. Další komplikací je, že veškeré fronty jsou v aplikačním kontextu získávány z JNDI, včetně konektivity do databáze. Na následujících řádcích zkusím popsat, jak jsem se s tímto problémem popasoval. Budu rád za jakékoliv reakce, co jsem měl udělat lépe a co jsem udělal špatně.<br />
<span id="more-389"></span><br />
Abych se vyhnul polemice, co je a co není unit testování a jestli nemám špatně navrženou aplikaci, když musím řešit JMS, JNDI apod., pak vězte, že implementaci jsem nepsal a implementaci jsem nesměl refaktorovat, protože se jednalo o celkem zásadní funkcionalitu, která se nachází těsně před ostrým nasazením a můj projektový vedoucí se obával toho, že kdybych provedl nějaký větší refactoring, mohlo by to způsobit v této fázi projektu více škody nežli užitku. </p>
<p>Ale i přesto bylo potřeba do této implementace doimplementovat několik požadavků. Rozhodl jsem se nejprve stávající implementaci pokrýt testy tak, abych tím, co tam doplním nerozbil to, co již funguje. A zde jsem trochu narazil. Implementace tohoto modulu je velice těsně spjata s JMS implementací Weblogicu a navíc tak, že se jedná o několik front, které jsou vzájemně propojeny a zpráva zkrze ně postupně &#8222;propadává&#8220; podle definovaných pravidel. </p>
<p>Abych to celé byl tedy schopen spustit jako unit test, musel jsem vyřešit pár &#8222;drobností&#8220;, a to poskytovatele <strong>JNDI kontextu</strong>, <strong>transaction manager</strong> a vlastní implementaci <strong>JMS</strong>. Pro JNDI kontextu jsem jednoduše využil prostředků Springu. Pro transakční manager jsem využil <a href="http://docs.codehaus.org/display/BTM/Home">Bitronix Transaction Manager</a> a pro messagingové služby padlo rozhodnutí na <a href="http://activemq.apache.org/">Apache ActiveMQ</a>.</p>
<h2>JNDI kontext</h2>
<p>Vytvoření vlastního JNDI kontextu je ve Springu triviální úloha. Já jsem si pro to napsal jednoduchou utilitku, která mi ji ještě více zjednodušuje:</p>
<pre lang="java">
package eu.kratochvil.utils.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;

import java.util.HashMap;
import java.util.Map;

/**
 * Simple implementation of JNDI context that should be used in unit-tests
 * within Spring context.
 * <p/>
 * Basic usage is simple:
 * 
 * &lt;bean id="jndiContext" class="cz.isvs.reg.ros.ws.repository.util.MockSpringJndiContext"&gt;
 *   &lt;property name="jndiContext"&gt;
 *      &lt;map&gt;
 *          &lt;entry key="ros.VstupniFronta" value-ref="destinationVstupniFronta"/&gt;
 *          &lt;entry key="ros.VystupniFronta" value-ref="destinationVystupniFronta"/&gt;
 *          &lt;entry key="weblogic.jms.XAConnectionFactory" value-ref="activeMQConnectionFactory"/&gt;
 *      &lt;/map&gt;
 *   &lt;/property&gt;
 * &lt;/bean&gt;
 *
 * There isn't needet to use something like <code>jndi.properties</code> because jndi context is define
 * directly inside spring context. 
 *
 * @author Jiri Kratochvil (jiri.kratochvil@jetminds.com)
 */
public class MockSpringJndiContext implements InitializingBean {

    public static final Logger logger = LoggerFactory.getLogger(MockSpringJndiContext.class);

    Map<String, Object> jndiContext = new HashMap<String, Object>();

    public void setJndiContext(Map<String, Object> jndiContext) {
        this.jndiContext = jndiContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        logger.info("Initializing JNDI context");
        SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
        for (Map.Entry entry : jndiContext.entrySet()) {
            logger.debug("Binding {} in JNDI context", entry.getKey().toString());
            builder.bind(entry.getKey().toString(), entry.getValue());
        }
    }
}
</pre>
<p>Použití je pak naprosto triviální:</p>
<pre lang="xml">
    <bean id="jndiContext" class="cz.isvs.reg.ros.ws.repository.util.MockSpringJndiContext">
        <property name="jndiContext">
            <map>
                <entry key="jms.queue1" value-ref="destinationQueue1"/>
                <entry key="jms.queue2" value-ref="destinationQueue2"/>
                <entry key="weblogic.jms.XAConnectionFactory" value-ref="connectionFactory"/>
            </map>
        </property>
    </bean>
</pre>
<p>Inicializací tohoto springového beanu se vytvoří JNDI kontext, který obsahuje dvě JMS fronty a ještě connection factory, o které budu mluvit dále. Pokud použijete Spring není potřeba dále definovat jak se k JNDI kontextu připojit, což se běžně dělá pomocí property souboru <code>jndi.properties</code> umístěném na classpath.</p>
<h2>JMS server</h2>
<p>Dále tedy potřebujeme vytvořit instanci embedovaného JMS serveru. Pro mé účely jsem zvolil <a href="http://activemq.apache.org/">Apache ActiveMQ</a>, který jde snadno inicializovat pomocí Springu, kde to vypadá následovně:</p>
<pre lang="xml">
   <!-- Definice message brokeru -->
    <amq:broker useJmx="false" persistent="false">
        <amq:transportConnectors>
            <amq:transportConnector uri="tcp://localhost:8888"/>
        </amq:transportConnectors>
    </amq:broker>

    <!-- Connection Factory pro message broker -->
    <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:8888"/>
    </bean>

    <!-- Vlastni definice front -->
    <amq:queue id="destinationQueue1" physicalName="jms.queue1"/>
    <amq:queue id="destinationQueue2" physicalName="jms.queue2"/>

    <!-- listener pro zachytavani vyjimek z JMS (implemetnace rozhrani javax.jms.ExceptionListener) -->
    <bean id="jmsExceptionListener" class="eu.kratochvil.blog.ukazky.JmsExceptionListenerImpl" />

    <!-- Springova implementace connection factory, ktera bude vyuzita pro registraci listeneru a pro 
            posilani zprav prostrednictvim springove JmsTemplate -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <constructor-arg ref="activeMQConnectionFactory"/>
        <property name="exceptionListener" ref="jmsExceptionListener"/>
        <property name="sessionCacheSize" value="100"/>
    </bean>
</pre>
<p>Popis co a proč je použito v předchozím listingu jsou přímo v něm, tedy ve stručnosti. Vytvořili jsme si instanci message brokeru, který nám nahrazuje vlastní JMS server v aplikačním serveru, následně jsme zadefinovali jednotlivé fronty, které jsou použity ve vlastní implementaci business logiky a konečně connection factory, která nám umožní napojení vlastních listenerů JMS front a zároveň přes ni budeme posílat testovací zprávy z našit unit testů. </p>
<p>Nyní bych se ještě vrátil k tomu, proč jsem do JNDI kontextu umístil <code>weblogic.jms.XAConnectionFactory</code>. Důvod je takový, že aplikace, které využívají JMS ve Weblogiku by měli referenci na connection factory získávat právě z JNDI. </p>
<h2>Transaction Manager</h2>
<p>Poslední věc, kterou musíme vyřešit bez aplikačního serveru je transaction manager &#8211; tedy &#8222;něco&#8220;, co nám bude řídit vlastní transakce. Na to jsem použil <a href="http://docs.codehaus.org/display/BTM/Home">Bitronix Transaction Manager</a> což je celkem mocná implementace transakčního manažeru. Pro naše účely bude použití triviální:</p>
<pre lang="xml">
      <!--  Bitronix Transaction Manager embedded configuration -->
    <bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices">
        <property name="serverId" value="spring-btm" />
        <property name="journal" value="null" />
    </bean>

    <!-- create BTM transaction manager -->
    <bean id="bitronixTransactionManager" factory-method="getTransactionManager"
        class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig,dataSource"
        destroy-method="shutdown" />

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="bitronixTransactionManager" />
        <property name="userTransaction" ref="bitronixTransactionManager" />
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>
</pre>
<h2>Závěrem</h2>
<p>Kouzlo tohoto použití je v tom, že nyní stačí spustit unit test, který inicializuje springový kontext a zároveň načte definici kontextu vlastní aplikace, která právě využívá JNDI pro získání referencí na fronty a vše by mělo fungovat stejně, jako kdybychom tuto implementaci měli deployovanou přímo na aplikačním serveru. Pro úplnost dodávám ukázku definice kontextu přímo v aplikaci:</p>
<pre lang="xml">
    <!-- ===================== JNDI =========================================== -->
    <jee:jndi-lookup id="jmsConnectionFactory" jndi-name="weblogic.jms.XAConnectionFactory"/>
    <jee:jndi-lookup id="vstupniFronta" jndi-name="jms.queue1"/>
    <jee:jndi-lookup id="vystupniFronta" jndi-name="jms.queue2"/>

    <!-- JTA transakce -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- ===================== FRONTY ========================================= -->
    <bean id="jmsTemplate" class="corg.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="jmsConnectionFactory"/>
        <property name="messageConverter" ref="simpleMessageConverter"/>
    </bean>

    <bean id="simpleMessageConverter" class="org.springframework.jms.support.converter.SimpleMessageConverter"/>

    <bean id="destinationResolver" class="org.springframework.jms.support.destination.BeanFactoryDestinationResolver"/>

    <jms:listener-container connection-factory="jmsConnectionFactory" transaction-manager="transactionManager"
                            destination-resolver="destinationResolver"
                            message-converter="simpleMessageConverter">
        <jms:listener destination="destinationQueue1" ref="messageBroker" method="processVstupni"
                      selector="MessageType='test1'"/>
        <jms:listener destination="destinationQueue2" ref="messageBroker" method="processVystupni"
                      selector="MessageType='test2'"/>
    </jms:listener-container>

    <bean id="messageBroker" class="eu.kratochvil.blog.ukazky.MyMessageBroker" />
</pre>
<p>Na celém tomto cvičení je pěkné to, že jednoduchou springovou konfigurací jsme schopni rozchodit určitou část aplikace, která za normálních okolností nelze bez aplikačního serveru spustit, a my si tak můžeme napsat testy, které lze snadno spouštět bez neustálého a otravného redeploymentu na aplikační server.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/testovani-jms-v-unit-testech/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">389</post-id>	</item>
		<item>
		<title>Zajímavá utilitka ve Springu</title>
		<link>https://jiri.kratochvil.eu/zajimava-utilita-ve-springu-stopwatch/</link>
					<comments>https://jiri.kratochvil.eu/zajimava-utilita-ve-springu-stopwatch/#comments</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Tue, 10 Nov 2009 02:41:37 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programování]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Návody]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Tipy]]></category>
		<guid isPermaLink="false">http://jiri.kratochvil.eu/?p=186</guid>

					<description><![CDATA[Nejednou jsem si všiml, že spousta vývojářů má tendenci stále dokola vymýšlet kolo, místo toho, aby využili již hotových funkčností. Rozhodl jsem se tedy, že [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Nejednou jsem si všiml, že spousta vývojářů má tendenci stále dokola vymýšlet kolo, místo toho, aby využili již hotových funkčností. Rozhodl jsem se tedy, že vám čas od času předvedu některé zajímavé utilitky, které se nacházejí v často používaních frameworcích a knihovnách. Dnes si vezmu na paškál Spring framework a jejich package Utils.<br />
<span id="more-186"></span><br />
Package Utils ve Springu obsahuje spoustu zajímavých utilitek. V následujícím textu představím utilitu StopWatch. Třída org.springframework.util.StopWatch je jednoduchou utilitou, která pracuje jako stopky a nahrazuje konstrukce, které nejsou zcela nejčistší, jako je například tento pattern:</p>
<pre lang="java">long startTimeMillis = System.currentTimeMillis();

// do something ...

long endTimeMillis = System.currentTimeMillis();
log.debug("Volani trvalo: " + (endTimeMillis - startTimeMillis) + " ms");</pre>
<p>Ve springu tedy existují již zmíněné &#8222;stopky&#8220;. Výhodou jejich použití je zejména zvýšení čitelnosti kódu. Jen upozornění &#8211; StopWatch <strong>není thread safe</strong> (což znamená, že je nutné pro každé měření použít novou instanci této třídy).</p>
<p>Příklad použití:</p>
<pre lang="java">StopWatch stopWatch = new StopWatch("PrikladPouziti");
try {
    try {
        stopWatch.start("Krok1");
        // do something ...
    } finally {
        stopWatch.stop();
    }
    try {
        stopWatch.start("Krok2");
        // do something else ...
    } finally {
        stopWatch.stop();
    }
} finally {
    log.info(stopWatch.toString());
}</pre>
<p>Ten nejzákladnější výstup pak bude následující:</p>
<pre lang="ini">INFO StopWatchTest:34 - StopWatch 'PrikladPouziti': running time (millis) = 437;
                                        [Krok1] took 250 = 57%;
                                        [Krok2] took 187 = 43%</pre>
<p>Jenže tahle utilitka umí mnohem více, ale to už nechám na objevení každého z vás.</p>
<p>Vím, že podobná funkčnost je i v balíku Apache Commons Lang, ale tohle je článek o Springu <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>[poll id=&#8220;1&#8243; type=&#8220;result&#8220;]</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/zajimava-utilita-ve-springu-stopwatch/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">186</post-id>	</item>
		<item>
		<title>JNDI kontext bez aplikačního serveru?</title>
		<link>https://jiri.kratochvil.eu/jndi-kontext-bez-aplikacniho-serveru/</link>
					<comments>https://jiri.kratochvil.eu/jndi-kontext-bez-aplikacniho-serveru/#comments</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Tue, 10 Nov 2009 00:31:19 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Návody]]></category>
		<category><![CDATA[Programování]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Tipy]]></category>
		<guid isPermaLink="false">http://jiri.kratochvil.eu/?p=195</guid>

					<description><![CDATA[V praxi jsem se setkal se situaci, kdy potřebuji spouštět unit testy mimo aplikační server. Na tom není nic zvláštního, dělá to každý. Pro testy [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>V praxi jsem se setkal se situaci, kdy potřebuji spouštět unit testy mimo aplikační server. Na tom není nic zvláštního, dělá to každý. Pro testy si vytvořím vlastní konfigurace, které JNDI nepotřebují a je to. Jenže to by nebylo dostatečně zajímavé a hlavně je nutné udržovat dvě konfigurace, což je při vrozené lenosti programátora prostor pro inovaci.<br />
<span id="more-195"></span><br />
Představme si situaci, kdy používáme databázi, která je konfigurována přímo v aplikačním serveru pomocí JNDI. Ve Springu ji pak používáme nějak takto:</p>
<pre lang="xml">
 <jee:jndi-lookup id="analyticDataSource" jndi-name="jdbc/Analytic" 
                       resource-ref="false"/>
</pre>
<p>Jak pak v unit testech toto vyřešit? Ideální by bylo, vytvořit si nějakým způsobem vlastní JNDI kontext, který pak bude naše aplikace využívat. Spring nám k tomu nabízí rozumné prostředky. Pojďme se tedy podívat, jak na to.</p>
<pre lang="java">/**
 * InitialContext factory for test purposes - it simulates JNDI context.
 */
public class TestInitialContextFactory implements InitialContextFactory {
    /**
     * Creates an Initial Context for beginning name resolution.
     * Special requirements of this context are supplied
     * using <code>environment</code>.
     *

     * The environment parameter is owned by the caller.
     * The implementation will not modify the object or keep a reference
     * to it, although it may keep a reference to a clone or copy.
     *
     * @param environment The possibly null environment
     *                    specifying information to be used in the creation
     *                    of the initial context.
     * @return A non-null initial context object that implements the Context
     *         interface.
     * @throws javax.naming.NamingException If cannot create an initial context.
     */
    public Context getInitialContext(Hashtable environment) throws NamingException {

        // Vytvorime si datasource, ktery chceme publikovat v JNDI
        DriverManagerDataSource ds = new DriverManagerDataSource(
                "oracle.jdbc.driver.OracleDriver",
                "jdbc:oracle:thin:@localhost:1521:TES_DB",
                "test",
                "password");

        try {
            // Tady zacneme tvorit vlastni kontext
            SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();

            // Pridame nas datasource do kontextu
            builder.bind("jdbc/MyDataSource", ds);

            builder.activate();
            return builder.createInitialContextFactory(null).getInitialContext(null);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
}</pre>
<p>Nyní už jen zbývá si v aplikaci nastavit, jak se má kontext vytvářet. To zajistíme konfigurací v souboru jndi.properties:</p>
<pre lang="ini">java.naming.factory.initial=eu.kratochvil.blog.ukazky.TestInitialContextFactory</pre>
<p>Jak tuto problematiku řešíte na svých projektech? Budu rád, když mi odpovíte prostřednictvím komentáře.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/jndi-kontext-bez-aplikacniho-serveru/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">195</post-id>	</item>
		<item>
		<title>Nepříjemný bug v Mavenu</title>
		<link>https://jiri.kratochvil.eu/neprijemny-bug-v-mavenu/</link>
					<comments>https://jiri.kratochvil.eu/neprijemny-bug-v-mavenu/#comments</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Wed, 04 Nov 2009 00:23:46 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Programování]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://blog.kratochvil.eu/?p=133</guid>

					<description><![CDATA[Na projektu používáme pro build nástroj Maven ve verzi 2.0.9. Jedná se o perfektní nástroj do doby, kdy pracuje tak, jak má. Ve chvíli, kdy [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Na projektu používáme pro build nástroj Maven ve verzi 2.0.9. Jedná se o perfektní nástroj do doby, kdy pracuje tak, jak má. Ve chvíli, kdy se začne chovat &#8222;tak nějak divně&#8220; se chyby hledají docela těžko.<br />
<span id="more-133"></span><br />
Co se vlastně stalo? Začalo to tím, že testy začaly vyhazovat následující výjimky:</p>
<pre lang="ini">
org.apache.commons.dbcp.SQLNestedException: Cannot create JDBC driver of class 'oracle.jdbc.driver.OracleDriver' for connect URL 'http://maven.apache.org'
	at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1150)
	at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
	at org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider.getConnection(InjectedDataSourceConnectionProvider.java:46)
	at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
</pre>
<p>To nejdivnější bylo to, že se aplikace snažila připojovat na URL: &#8218;http://maven.apache.org&#8216; místo toho, aby se připojovala na URL, která byla v konfiguraci. </p>
<p>Dalším pátráním jsem zjistil, že se v &#8222;targetu&#8220;, tedy místě, kam se ukládají zkompilované zdrojáky, vyskytuje soubor, definující springový kontext, a v něm se vyskytovalo následující (v property <strong>url</strong>):</p>
<pre lang="xml">
    <bean id="microsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="${jdbc.driverClassName}"/>
       <property name="url" value="http://maven.apache.org"/>
       <property name="username" value="${jdbc.username}"/>
       <property name="password" value="${jdbc.password}"/>
    </bean>
</pre>
<p>Jak se tam to mohlo dostat, když ve zdrojáku je něco úplně jiného:</p>
<pre lang="xml">
    <bean id="microsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
       <property name="driverClassName" value="${jdbc.driverClassName}"/>
       <property name="url" value="${jdbc.url}"/>
       <property name="username" value="${jdbc.username}"/>
       <property name="password" value="${jdbc.password}"/>
    </bean>
</pre>
<p>Začali jsme tedy pátrat, jak se tam mohl tento řetězec dostat, a měla to na svědomí tahle konstelace:<br />
V POMu projektu byla definováno něco takového:</p>
<pre lang="xml">
<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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cz.csas.clf</groupId>
    <artifactId>clf-micros-product-configurator</artifactId>
    <packaging>war</packaging>
    <version>${version.micros}</version>
    <name>clf-micros-product-configurator</name>
    <url>http://maven.apache.org</url> 
       ...
    <build>
        <resources>
           ...
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
          ...
</pre>
<p>Co je na předchozím POMu zajímavých několik věcí. Je nastaveno filtrování resourců pro adresář, kde je uložen soubor s konfigurací a v projektu byl definován parametr url.</p>
<p>Díky chybě v mavenu došlo k nahrazení placeholderu ${jdbc.url} za property url, která navíc nebyla property <img src="https://s.w.org/images/core/emoji/15.0.3/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
<p>Naštěstí pomohl upgrade na nejnovější verzi mevenu (2.2.1), kde se chyba už nevyskytla. Zvláštní je, že jsem v žádných release notes nebo něčem podobným nenašel o tomto problému žádnou zmínku.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/neprijemny-bug-v-mavenu/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">133</post-id>	</item>
		<item>
		<title>Logovani ve Springu</title>
		<link>https://jiri.kratochvil.eu/logovani-ve-springu/</link>
					<comments>https://jiri.kratochvil.eu/logovani-ve-springu/#respond</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Fri, 30 Oct 2009 19:42:11 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://blog.kratochvil.eu/?p=8</guid>

					<description><![CDATA[Jak udělat podrobné logování ve Springu tak, aby se nemusel procházet kód a ručně vkládat něco jako log.debug(....);? Spring framework má pro tyto úcěly vynikající [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Jak udělat podrobné logování ve Springu tak, aby se nemusel procházet kód a ručně vkládat něco jako <code lang="java">log.debug(....);</code>? Spring framework má pro tyto úcěly vynikající podporu, jejíž použití je naprosto jednoduché.<br />
<span id="more-8"></span></p>
<p>Tomu řešení se říká AOP a Spring má vestavěno několik zajímavých aspektů.</p>
<p>Začněme příkladem použití:</p>
<pre lang="xml">
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<property name="proxyTargetClass" value="true"/>
	<property name="beanNames" value="*BusinessService,*Bean"/>
	<property name="interceptorNames" value="loggingAdvice"/>
</bean>

<bean id="loggingAdvice" class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
	<property name="useDynamicLogger" value="true"/>
	<property name="hideProxyClassNames" value="true"/>
	<property name="enterMessage" value="Entering method '$[methodName]' of class [$[targetClassShortName]], args: $[arguments]"/>
	<property name="exitMessage" value="Exiting method '$[methodName]' of class [$[targetClassShortName]], returned: $[returnValue], execution time: $[invocationTime]"/>
	<property name="exceptionMessage" value="Exception $[exception] thrown in method '$[methodName]' of class [$[targetClassShortName]]"/>
</bean>
</pre>
<p>Výše uvedená konfigurace zajistí to, že všechny beany, které jsou ve stejném aplikačním kontextu  a jejichž názvy končí řetězci &#8222;BusinessService&#8220; a nebo &#8222;Bean&#8220; (parametr <code>beanNames</code> u <code>BeanNameAutoProxyCreator</code>) budou automaticky obaleny dynamickou proxy, která bude aplikovat CustomizableTraceInterceptor. &#8220;&#8217;Tento interceptor zajistí&#8220;&#8216;, že:<br />
* bude zalogováno volání jakékoliv public metody beany včetně vstupních argumentů<br />
* bude zalogována výstupní hodnota včetně času, které vykonání metody<br />
* v případě ukončení volání vyjímkou, bude tato vyjímka také zalogována<br />
* logování bude na TRACE levelu a pokud je nastaveno logování pouze na vyšší úrovni, nebude volání metod v podstatě nijak výrazně zpomaleno<br />
* zalogované záznamy budou aplikovat původní název třídy jako název použitého loggeru (tzn. ignorují se názvy proxy class i interceptoru)</p>
<p>Zajímavých interceptorů připravených rovnou k použití poskytuje Spring více:</p>
<ul>
<li><code>ConcurrencyThrottleInterceptor</code> &#8211; omezuje paralelní volání metod dané instance</li>
<li><code>PerformanceMonitorInterceptor</code> &#8211; umožňuje jednoduché logování výkonnostních otisků (tzn. jak dlouho trval běh konkrétního volání metody instance)</li>
<li><code>DebugInterceptor</code> &#8211; jednoduché (fixní) logování metod dané instance</li>
<li><code>CustomizableTraceInterceptor</code> &#8211; umožňuje customizovatelné transparentní logování volání metod dané instance</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/logovani-ve-springu/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8</post-id>	</item>
		<item>
		<title>Použití EJB ve Springu</title>
		<link>https://jiri.kratochvil.eu/pouziti-ejb-ve-springu/</link>
					<comments>https://jiri.kratochvil.eu/pouziti-ejb-ve-springu/#respond</comments>
		
		<dc:creator><![CDATA[Jiří Kratochvíl]]></dc:creator>
		<pubDate>Fri, 30 Oct 2009 19:40:10 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[EJB]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[linkedin]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://blog.kratochvil.eu/?p=6</guid>

					<description><![CDATA[Před časem jsem na projektu řešil, jak použít dependency injection Springu pro použití EJB. V podstatě mi šlo o to, abych nemusel řešit různé lookupy [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Před časem jsem na projektu řešil, jak použít dependency injection Springu pro použití EJB. V podstatě mi šlo o to, abych nemusel řešit různé lookupy na EJB v kódu, ale aby to vše fungovalo tak nějak &#8222;samo&#8220;.<br />
<span id="more-469"></span><br />
V případě EJB 2, je to snadné. Spring poskytuje celkem snadné prostředky:</p>
<pre lang="xml" line="1">
<bean id="myEjb" class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
   <property name="jndiName" value="java:comp/env/ejb/MyEjb" />
   <property name="businessInterface" value="cz.myapp.MyEjb" />
</bean>
</pre>
<p>Jednoduché natolik, že LocalStatelessSessionProxyFactoryBean ví, jak vytvořit instanci Beanu, přes Home rozhraní, na které ukazuje JNDI. Existuje několik různých proxy factory, pro různé druhy EJBček.</p>
<p>V EJB3 je situace jiná, protože vůbec nemusíte implementovat Home rozhraní. Důsledkem je, že nemůžete používat LocalStatelessSessionProxyFactoryBean. Namísto toho, používáte standardní JndiObjectFactoryBean:</p>
<pre lang="xml" line="1">
<bean id="myEjb" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName" value="java:comp/env/ejb/MyEjb" />
   <property name="expectedType" value="net.twasink.ejb.MyEjb" />
</bean>
</pre>
<p>Princip je jednoduchý: najde EJB v JNDI, zaregistruje se jako spring Bean, a pak se přes autowiring předá tato reference do jiného beanu. To zní dobře.</p>
<p>Má to jeden zásadní problém: musíte definovat EJBčka v XML. Jednou z obrovských výhod EJB 3 je to, že nemusíte řešit žádné XML soubory (známe XML hell z EJB 2.x). A to se mi nechce měnit.</p>
<p>Naštěstí je tu řešení: BeanPostProcessors. BeanPostProcessors vám umožňuje dělat věci, nad jednotlivými beany po jeho vytvoření. A to třeba vyhledání metod, anotací apod. Například anotace @EJB</p>
<p>Zde je kód:</p>
<pre lang="java" line="1">
/** Look for EJB3-style annotations, and provide the corresponding values from the container. */
public class EjbBeanPostProcessor implements BeanPostProcessor {

  public Object postProcessAfterInitialization(Object bean, String beanName)
  throws BeansException {
    // do nothing; the EJBs are configured before initialization.
    return bean;
  }

  public Object postProcessBeforeInitialization(Object bean, String beanName)
  throws BeansException {
    Class beanClazz = bean.getClass();
    for (Method method : beanClazz.getMethods()) {
      if (method.isAnnotationPresent(EJB.class)) {
        setEjbRef(bean, method);
      }
    }
    return bean;
  }
  
  private <T> void setEjbRef(T bean, Method setter) {
    Class ejbClass = determineBeanClass(setter);
    Object ejbBean = lookupBean(ejbClass, determineJndiName(ejbClass, setter), bean);
    invoke(bean, setter, ejbBean);
  }
  
  /**
   * Determine the JNDI name for the EJB. By default, we assume that it is the simple class
   * name, but we allow the setter method to override this, using the 'mappedName' attribute.
   */
  private String determineJndiName(Class ejbClass, Method setter) {   
    EJB ejbAnnotation = setter.getAnnotation(EJB.class);
    if (ejbAnnotation.mappedName().equals("")) {
      return ejbClass.getSimpleName();
    }
    return ejbAnnotation.mappedName();
  }

  private Object lookupBean(Class ejbClass, String beanName, Object bean) throws BeansException {
    try {
      return new InitialContext().lookup("java:comp/env/ejb/" + beanName);
    } catch (NamingException e) {
      throw new EjbBeansException(bean, "Could not resolve EJB " + beanName, e);
    }
  }

  /**
   * Determine the type of the EJB. This is used to determine the JNDI name to look up. This
   * would normally be the type of the argument to the setter, but the EJB spec allows this
   * to be overriden (presumably to a subclass)
   */
  private Class determineBeanClass(Method setter) {
    EJB ejbRefAnnotation = setter.getAnnotation(EJB.class);
    if (ejbRefAnnotation.beanInterface() != null && 
        Object.class.equals(ejbRefAnnotation.beanInterface()) == false) {
      return ejbRefAnnotation.beanInterface();
    }
    Class otherBeanClass = setter.getParameterTypes()[0];
    return otherBeanClass;
  }

  private <T> void invoke(T bean, Method method, Object ... args) {
    try {
      method.invoke(bean, args);
    } catch (IllegalArgumentException e) {
      throw new EjbBeansException(bean, "Could not set EJB", e);
    } catch (IllegalAccessException e) {
      throw new EjbBeansException(bean, "Could not set EJB", e);
    } catch (InvocationTargetException e) {
      throw new EjbBeansException(bean, "error setting EJB reference", e.getCause());
    }
  }

  /** Simple exception detailing the type of problem that occured. */
  private static class EjbBeansException extends BeansException {
    public EjbBeansException(Object bean, String message, Throwable cause) {
      super(message + " [bean class: " + bean.getClass().getName() + "]", cause);
    }
  }
}
</pre>
<p>Tento krásný BeanPostProcessor ve Springu ho aktivujeme celkem snadno:
<prelang="xml">
<bean class="cz.myapp.EjbBeanPostProcessor" /><br />
</source></p>
<p>Teď si prostě přidáte anotaci @EJB odkazy do svého Spring beanu, a on se kouzelně naplní. Do žádného XML není potřeba nic definovat. Jak krásné.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jiri.kratochvil.eu/pouziti-ejb-ve-springu/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">469</post-id>	</item>
	</channel>
</rss>
