<?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>Information Centre &#187; spring</title>
	<atom:link href="http://my.center-of.info/tag/spring/feed/" rel="self" type="application/rss+xml" />
	<link>http://my.center-of.info</link>
	<description>“Wenn etwas schon da war, wie kann man es dann patentieren?” D.E.Knuth, 2002</description>
	<lastBuildDate>Sat, 22 Oct 2011 11:09:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>JPA: Dynamic Datasource Routing</title>
		<link>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/</link>
		<comments>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 20:15:54 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[DB]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=158</guid>
		<description><![CDATA[Man stelle sich vor, in einer (Web-)Anwendung müssen verschiedene Datasources verwendet werden. Ob bei den unterschiedlichen Datasourcen es sich immer um die andere/gleiche Datenbank handelt, sei mal dahingestellt. Die Datasourcen unterscheiden sich mind. in einer Eigenschaft, z.B. User. Im Spring-Kontext gilt folgendes: In JPA braucht man pro EntityManagerFactory eine Datasource. Der EMF ist einen TransactionManager [...]]]></description>
			<content:encoded><![CDATA[<p>Man stelle sich vor, in einer (Web-)Anwendung müssen verschiedene Datasources verwendet werden. Ob bei den unterschiedlichen Datasourcen es sich immer um die andere/gleiche Datenbank handelt, sei mal dahingestellt. Die Datasourcen unterscheiden sich mind. in einer Eigenschaft, z.B. User.</p>
<p><span id="more-158"></span></p>
<p>Im Spring-Kontext gilt folgendes: In JPA braucht man pro EntityManagerFactory eine Datasource. Der EMF ist einen TransactionManager zugeordnet.</p>
<p>Man könnte alle Datasource, EMF, TX-Manager und PUs in Spring konfigurieren. Man hat jedoch ein Problem, wenn man n verschiedene Datasourcen hat, die zur Laufzeit ausgewählt werden müssen.</p>
<ul>
<li>Die Konfiguration ist umfangreich und unübersichtlich
<ul>
<li>Pro Datasource ist ein Persistence-Unit notwendig, denn für die Ermittlung des richtigen EntityManager kann @<a title="JEE 5 API: PersistenceContext" href="http://download.oracle.com/javaee/5/api/javax/persistence/PersistenceContext.html" target="_blank">PersistenceContext</a>(unitName = &#8220;PU_NAME&#8221;) verwendet werden</li>
<li>Pro Datasource einen EntityManagerFactory mit der Verknüpfung zur PersistenceUnit</li>
<li>Pro EntityManagerFactory einen TransactionManager, ggf. mit <a title="Spring 3 Reference Doc: Qualifier" href="http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-autowired-annotation-qualifiers" target="_blank">Qualifier</a>.</li>
</ul>
</li>
<li>Die Wartung ist entsprechend nicht optimal. Pro neue Datasource müssen 3 Stellen angepasst werden</li>
<li>Das Transaction-Handling wird kompliziert. @<a title="Spring 3 API: Transactional" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/transaction/annotation/Transactional.html" target="_blank">Transactional</a> muss nun immer den richtigen TransactionManager nutzen. Die Entscheidung soll natürlich zur Laufzeit passieren. @Transactional(&#8220;TX_MANAGER_NAME&#8221;) reicht nicht aus, da es eine statische Kopplung verursacht.</li>
</ul>
<p>Eine andere Lösungsvariante wäre, statt einen <a title="JEE 5 API: EntityManager" href="http://download.oracle.com/javaee/5/api/javax/persistence/EntityManager.html">EntityManager</a> durch @PersitenceContext eher direkt den <a title="JEE 5 API: EntityManagerFactory" href="http://download.oracle.com/javaee/5/api/javax/persistence/EntityManagerFactory.html">EntityManagerFactory</a> durch @<a title="JEE 5 API: PersistenceUnit" href="http://download.oracle.com/javaee/5/api/javax/persistence/PersistenceUnit.html">PersistenceUnit</a> zu bekommen. Hier modifiziert man die EntityManager-Erstellung soweit, dass man den EntityManager mit der gewünschten Datasource bekommt. Falls sich bei den Datasourcen nur die User unterscheiden und <a title="Eclipselink JPA" href="http://www.eclipse.org/eclipselink/jpa.php" target="_blank">Eclipselink</a> verwendet wird, siehe u.a. [1].</p>
<p>Perfekt wäre jedoch eine Lösung, in der nur EntityManagerFactory, ein TransactionManager und ein PersistenceUnit verwendet wird. Zur Laufzeit soll dann der vorhandene EntityManagerFactory für die gewünschte Datasource einen EntityManager erstellen.</p>
<p>Das funktioniert. Der EntityManagerFactory erwartet eine Referenz auf die <a title="Java 5 API: DataSource" href="http://download.oracle.com/javase/1.5.0/docs/api/javax/sql/DataSource.html" target="_blank">DataSource</a>. Hier könnte man eine eigene Implementierung dieses Interface anbieten, welches die Unterscheidung bzgl. der verschiedenen Datasourcen durchführt. DataSource.getConnection() muss dann abhängig von fest definierten Eigenschaften die Connection von der richtigen Datasource zurückgeben. Um die Eigenschaften in der eigenen DataSource-Implementierung abzufragen, ist die Nutzung von <a title="Java 5 API: ThreadLocal" href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ThreadLocal.html" target="_blank">ThreadLocal</a> bzw. <a title="Java 5 API: InheritableThreadLocal" href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/InheritableThreadLocal.html" target="_blank">InheritableThreadLocal</a> möglich.</p>
<p>Eine Spring-spezifische Lösung die in diese Richtung geht, ist mittels <a title="Spring 3 API: AbstractRoutingDataSource" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.html" target="_blank">AbstractRoutingDatasource</a> möglich [2]. Hier muss die abstrakte Methode determineCurrentLookupKey() implementiert werden. In dieser Methode muss die Logik verpackt werden, damit anhand des resultierenden Keys die richtige Datasource verwendet werden kann. Das Mapping zwischen Key und Datasource wird in AbstractRoutingDatasources#<a title="Spring 3 API: AbstractRoutingDataSource.setTargetDataSources()" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.html#setTargetDataSources(java.util.Map)" target="_blank">targetDataSources</a> gehalten. Wird kein Key zurückgeliefert, wird die vorher definierte Standard-Datasource verwendet.</p>
<p>Eine Beispiel-Implementierung, welches mit Spring 3.x und jeweils mit Eclipselink und Hibernate funktioniert, sieht wie folgt aus:</p>
<p>Die relevante Spring-Konfiguration:</p>
<pre class="brush: xml">
&lt;bean id=&quot;baseDataSource&quot; abstract=&quot;true&quot;&gt;
&lt;property name=&quot;driverClassName&quot; value=&quot;${db.driverClassName}&quot;/&gt;
&lt;property name=&quot;url&quot; value=&quot;${db.url}&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;dataSource1&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.1.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.1.pw}&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;dataSource2&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.2.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.2.pw}&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;dataSource3&quot; parent=&quot;baseDataSource&quot;&gt;
&lt;property name=&quot;user&quot; value=&quot;${db.3.user}&quot;/&gt;
&lt;property name=&quot;password&quot; value=&quot;${db.3.pw}&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;dynamicDatasource&quot; class=&quot;info.center-of.spring.jpa.DynamicDataSourceRouting&quot;&gt;
&lt;property name=&quot;targetDataSources&quot;&gt;
&lt;entry key=&quot;${db.1.user}&quot; value-ref=&quot;dataSource1&quot;/&gt;
&lt;entry key=&quot;${db.2.user}&quot; value-ref=&quot;dataSource2&quot;/&gt;
&lt;entry key=&quot;${db.3.user}&quot; value-ref=&quot;dataSource3&quot;/&gt;
&lt;/property&gt;
&lt;property name=&quot;defaultTargetDataSource&quot; ref=&quot;dataSource1&quot;/&gt;
&lt;/bean&gt;

&lt;bean id=&quot;entityManagerFactory&quot; class=&quot;org.springframework.orm.jpa.LocalEntityManagerFactoryBean&quot;&gt;
&lt;property name=&quot;datasource&quot; ref=&quot;dynamicDatasource&quot; /&gt;
&lt;property name=&quot;jpaVendorAdapter&quot;&gt;
&lt;!-- Fuer Hibernate --&gt;
&lt;bean class=&quot;org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter&quot; p:showSql=&quot;true&quot; generateDdl=&quot;true&quot; /&gt;
&lt;!-- Fuer Eclipselink
&lt;bean class=&quot;org.springframework.orm.jpa.vendor.EclipselinkJpaVendorAdapter&quot; p:showSql=&quot;true&quot; generateDdl=&quot;true&quot; /&gt;
--&gt;
&lt;/property&gt;
&lt;/bean&gt;

&lt;bean class=&quot;org.springframework.orm.jpa.JpaTransactionManager&quot;&gt;
&lt;property name=&quot;entityManagerFactory&quot; ref=&quot;entityManagerFactory&quot; /&gt;
&lt;/bean&gt;

&lt;tx:annotation-driven /&gt;
</pre>
<p>Die Klasse <em>DynamicDataSourceRouting</em> überschreibt die Methode zur Ermittlung des Keys. In unserem Fall ist dies immer der aktuelle/gewünschte DB-User:</p>
<pre class="brush: java">
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class CustomerRoutingDataSource extends AbstractRoutingDataSource {

@Override
protected Object determineCurrentLookupKey() {
return DBUserContextHolder.getDBUser();
}
}
</pre>
<p><em>DBUserContextHolder</em> ist eine Klasse mit einer ThreadLocal-Variable, die in dem aktuellen Thread den DB-User hält</p>
<pre class="brush: java">
public class DBUserContextHolder {

private static final InheritableThreadLocal&lt;String&gt; contextHolder = new InheritableThreadLocal&lt;String&gt;();

public static void setDBUser(final String dbUser) {
contextHolder.set(dbUser);
}

public static String getDBUser() {
return (String) contextHolder.get();
}

public static void clear() {
contextHolder.remove();
}
}
</pre>
<p>Bevor der EntityManager nun erstellt wird, muss</p>
<pre class="brush: java">
DBUserContextHolder.setDBUser(&amp;quot;dbUser1&amp;quot;);
</pre>
<p>aufgerufen werden.</p>
<p>Mit dieser Lösung hat man &#8220;nur&#8221; eine enge Kopplung mit Spring. Die Lösung funktioniert mit verschiedenen ORMs.</p>
<p>&nbsp;</p>
<p>[1]: <a title="Wikibook JPA: Java Persistence/Auditing and Security - Provide each application user with a database user id" href="http://en.wikibooks.org/wiki/Java_Persistence/Auditing_and_Security" target="_blank">Wikibook JPA: Provide each application user with a database user id</a></p>
<p>[2]: <a title="Spring Blog: Dynamic DataSource Routing" href="http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/" target="_blank">Spring Blog: Dynamic DataSource Routing</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2011/03/04/jpa-dynamic-datasource-routing/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Spring AOP &amp; Ehcache</title>
		<link>http://my.center-of.info/2009/09/25/spring-aop-ehcache/</link>
		<comments>http://my.center-of.info/2009/09/25/spring-aop-ehcache/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 14:27:59 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[JEE]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[aop]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=145</guid>
		<description><![CDATA[Caching ist ja bekanntlich eine Querschnitts-Anforderung (cross cutting concern), was man eigentlich nicht direkt in die Business-Logik integrieren möchte/sollte. Hier bietet es sich an, die Cache-Funktionalität mittels AOP (Aspektorientierte Programmierung) zu realisieren. Dieser Beitrag erklärt das exemplarisch realisieren der Cache-Funktionalität mittels Spring AOP und Ehcache. Einführung Vorweg. Es gibt natürlich bei den springmodules ein Cache-Modul. [...]]]></description>
			<content:encoded><![CDATA[<p>Caching ist ja bekanntlich eine Querschnitts-Anforderung (cross cutting concern), was man eigentlich nicht direkt in die Business-Logik integrieren möchte/sollte.<br />
Hier bietet es sich an, die Cache-Funktionalität mittels AOP (Aspektorientierte Programmierung) zu realisieren.<br />
Dieser Beitrag erklärt das exemplarisch realisieren der Cache-Funktionalität mittels <a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop-api.html" target="_blank" title="Spring 2.5.x Reference Doc: Spring AOP">Spring AOP</a> und <a href="http://ehcache.org/" target="_blank" title="Ehcache">Ehcache</a>.<br />
<span id="more-145"></span><br />
<strong>Einführung</strong><br />
Vorweg. Es gibt natürlich bei den <a href="https://springmodules.dev.java.net/" target="_blank" title="Springmodules">springmodules</a> ein <a href="https://springmodules.dev.java.net/docs/reference/0.9/html/cache.html" target="_blank" title="Springmodules: Cache">Cache-Modul</a>. Dieses wird, wenn überhaupt, nur sehr langsam weiterentwickelt. Das neue <a href="http://www.springsource.org/extensions" target="_blank" title="Spring Source: Spring Extensions">Spring Extensions Projekt</a> beinhaltet leider kein Cache-Modul. Hinzu kommen noch fehlende Funktionalitäten wie z.B. das Löschen von nur einem Objekt aus dem Cache.<br />
Falls man jedoch doch Springmodules Cache nutzen will, kann man sich mein altes <a href="http://my.center-of.info/2009/04/07/cache-method-results-with-ehcache-and-spring/" target="_blank" title="Centre of information: Cache method results with Ehcache and Spring">Beispiel</a> anschauen.</p>
<p><strong>Technologie</strong><br />
In der Lösung wird nur Spring AOP und Ehcache direkt verwendet. Bei der AOP Implementierung wird nicht <a href="http://www.eclipse.org/aspectj/" target="_blank" title="Eclipse: AspectJ Project">AspectJ</a> verwendet um die Anzahl der abhängigen Bibliotheken gering zu halten. Dies ist auch möglich, da die benötigte Funktionalität durch <a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop-api.html" target="_blank" title="Spring 2.5.x Reference Doc: Spring AOP">Spring AOP</a> bereitgestellt wird.<br />
Mittels der Spring-Klasse <a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.html" target="_blank" title="Spring 2.5.x API: EhCacheManagerFactoryBean">EhCacheManagerFactoryBean</a> wird der Ehcache integriert.</p>
<p><strong>Bibliotheken</strong><br />
In diesem Fall braucht man mindestens (und die entsprechende Abhängigkeiten):</p>
<ul>
<li>spring 2.5.6</li>
<li>ehcache</li>
</ul>
<p><strong>XML Konfiguration</strong><br />
Die XML Konfiguration für Spring sieht wie folgt aus:</p>
<pre class="brush: xml">
 &lt;!-- ...some other spring configuration... --&gt;

 &lt;!-- Ehcache bean which gets the path the ehcache.xml config file --&gt;
 &lt;bean id=&quot;cacheManager&quot; class=&quot;org.springframework.cache.ehcache.EhCacheManagerFactoryBean&quot;&gt;
        &lt;property name=&quot;configLocation&quot; value=&quot;classpath:ehcache.xml&quot; /&gt;
    &lt;/bean&gt;

 &lt;!-- Interceptor which handels the cross cutting concerns (here: caching) --&gt;
 &lt;bean id=&quot;coInterceptor&quot; class=&quot;de.ic.jee.aop.COCacheInterceptor&quot;&gt;
		&lt;constructor-arg index=&quot;0&quot; ref=&quot;cacheManager&quot; /&gt;
  		&lt;!-- Set the name of the cache which will be used from the cache manager --&gt;
		&lt;constructor-arg index=&quot;1&quot; value=&quot;coCache&quot; /&gt;
	&lt;/bean&gt;

  &lt;!-- Advisor for the relevant methods --&gt;
    &lt;bean id=&quot;coAdvisor&quot; class=&quot;org.springframework.aop.support.RegexpMethodPointcutAdvisor&quot;&gt;
		&lt;property name=&quot;advice&quot;&gt;
        	&lt;ref local=&quot;coInterceptor&quot;/&gt;
		&lt;/property&gt;
		&lt;property name=&quot;patterns&quot;&gt;
                  &lt;!-- only the get and update methods --&gt;
        	  &lt;list&gt;
        		&lt;value&gt;.*update.*&lt;/value&gt;
        		&lt;value&gt;.*get.*&lt;/value&gt;
        	  &lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

  &lt;!-- Proxy factory for aop proxy  --&gt;
	&lt;bean id=&quot;coServiceProxy&quot; class=&quot;org.springframework.aop.framework.ProxyFactoryBean&quot;&gt;
		&lt;property name=&quot;target&quot;&gt;
                        &lt;!-- The target bean object --&gt;
			&lt;ref bean=&quot;coService&quot;/&gt;
		&lt;/property&gt;
		&lt;property name=&quot;interceptorNames&quot;&gt;
			&lt;list&gt;
				&lt;value&gt;coAdvisor&lt;/value&gt;
			&lt;/list&gt;
		&lt;/property&gt;
                &lt;!-- Name of this new generated proxy, to identify this object
                       in the autowired process.
                --&gt;
		&lt;qualifier value=&quot;coServiceProxy&quot;/&gt;
	&lt;/bean&gt;
</pre>
<p>Spring AOP ist <a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-introduction-proxies" target="_blank" title="Spring 2.5.x Reference Doc: 6.1.3. AOP Proxies">proxy-basiert</a>. Hierfür wird deswegen ein <a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/framework/ProxyFactoryBean.html" target="_blank" title="Spring 2.5.x API: ProxyFactoryBean">ProxyFactoryBean</a> definiert, was den Advisor (<code>coAdvisor</code>) auf ein bestimmtes Bean einsetzt, somit entsteht dann eine neue Proxy-Klasse (<code>coServiceProxy</code>).</p>
<p>Mit <a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/support/RegexpMethodPointcutAdvisor.html" target="_blank" title="Spring 2.5.x API: RegexpMethodPointcutAdvisor">RegexpMethodPointcutAdvisor</a> kann definiert werden, welche Methoden beobachtet werden. In unserem Fall alle <code>update</code> und <code>get</code> Methoden.</p>
<p>Der Advice bzw. Interceptor (<code>coInterceptor</code>), welcher die Querschnitts-Funktionalität beinhaltet, kriegt eine Referenz auf den CacheManager (hier: <code>cacheManager</code>). Mit dieser Referenz kann beim Methoden-Aufruf vorher im Cache geprüft werden, ob die Antwort schon bekannt ist, wenn nicht, wird die Methode weiter ausgeführt und das Ergebnis (Rückgabewert) dann im Cache gespeichert.</p>
<pre class="brush: java">
public class COCacheInterceptor implements MethodInterceptor {

    private final CacheManager cacheManager;
    public COCacheInterceptor(final CacheManager cm, final String cn) {
		this.cacheManager = cm;
		this.cacheName = cn;
	}

     public Object invoke(final MethodInvocation methodInvocation) throws Throwable {

          /*
           * Cache cache = cacheManager.getCache(this.cacheName);
           * String cacheKey = .... generate cache key, maybe the arguments of the method invocation
           * get element from the cache
           * Element e = cache.get(cacheKey);
           * If element found:
           * - return e.getObjectValue()
           * otherwise:
           * - proceed the method, methodResult = methodInvocation.proceed()
           * - put the result in the cache, cache.put(new Element(cacheKey, methodResult));
           * - return methodResult;
           */

     } // invoke()
}
</pre>
<p>Mit wenig Konfiguration und Programmierung kann man sehr einfach Cache-Funktionalität einfügen, ohne die Business Logik zu verändern.</p>
<p>Links:<br />
- Spring AOP: <a href="http://static.springsource.org/spring/docs/2.5.x/reference/aop-api.html" target="_blank">http://static.springsource.org/spring/docs/2.5.x/reference/aop-api.html</a><br />
- Ehcache: <a href="http://ehcache.org/" target="_blank">http://ehcache.org/</a><br />
- Spring 2.5.x API: <a href="http://static.springsource.org/spring/docs/2.5.x/api/index.html" target="_blank">http://static.springsource.org/spring/docs/2.5.x/api/index.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2009/09/25/spring-aop-ehcache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cache method results with Ehcache and Spring</title>
		<link>http://my.center-of.info/2009/04/07/cache-method-results-with-ehcache-and-spring/</link>
		<comments>http://my.center-of.info/2009/04/07/cache-method-results-with-ehcache-and-spring/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 11:25:03 +0000</pubDate>
		<dc:creator>Haf</dc:creator>
				<category><![CDATA[JEE]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://my.center-of.info/?p=121</guid>
		<description><![CDATA[Caching ist eins der Aspekte welches man nicht unbedingt direkt in der Businesslogik verankern möchte. Hierzu empfehlt es sich eine AOP-Lösung. Mit AOP kann die Funktionalität einer Cache-Realisierung genutzt werden. Eins der populärsten Cache-Provider ist Ehcache. In dem Umfeld von Spring kann man Ehcache folgendermaßen integrieren: Man nutzt das aus dem nicht mehr gewarteten spring-modules-Projekt [...]]]></description>
			<content:encoded><![CDATA[<p>Caching ist eins der Aspekte welches man nicht unbedingt direkt in der Businesslogik verankern möchte. Hierzu empfehlt es sich eine AOP-Lösung. Mit AOP kann die Funktionalität einer Cache-Realisierung genutzt werden. Eins der populärsten Cache-Provider ist <a title="Ehcache" href="http://ehcache.sourceforge.net/" target="_blank">Ehcache</a>.</p>
<p>In dem Umfeld von <a title="SpringSource: Spring Framework" href="http://www.springsource.org/" target="_blank">Spring</a> kann man Ehcache folgendermaßen integrieren:</p>
<p><span id="more-121"></span>Man nutzt das aus dem nicht mehr gewarteten <a title="Spring-Modules" href="https://springmodules.dev.java.net/" target="_blank">spring-modules</a>-Projekt das <a title="Spring-Modules: Cache" href="https://springmodules.dev.java.net/docs/reference/0.8/html/cache.html" target="_blank">cache</a>-Modul. Ja, spring-modules wird durch Spring-Extensions abgelöst, jedoch werden nicht alle Projekte übernommen. D.h. manche Unterprojekte (wohl auch Cache) werden nicht nach <a title="Spring: Extensions" href="http://www.springsource.org/extensions" target="_blank">Spring-Extensions</a> übernommen. Wo da der Sinn liegt, ist wohl nur den Betreibern klar.</p>
<p>Die aktuelle Version 0.9 findet man auch schon seit Monaten in keinem Maven Repository. Da bleibt nichts anderes übrig, als sich die Bibliothek (spring-modules-cache.jar) selbst in das lokale Repository zu installieren [1]</p>
<p>Für die Abhängigkeit: spring-modules-cache benötigt <a title="Maven Repository Browser: oro" href="http://mvnrepository.com/artifact/oro/oro" target="_blank">oro-2.0.8</a>.</p>
<p>Um ein Bean mit Cache-Funktionalität zu erweitern, stellt spring-modules-cache z.B. CacheProxyFactoryBean zur Verfügung um Advices für das Hinzufügen von Objekten (<a title="Doc Spring-Modules: Caching Advice" href="https://springmodules.dev.java.net/docs/reference/0.8/html/cache.html#cachingAdvice" target="_blank">caching advice</a>) und Löschen von Objekte (<a title="Doc Spring-Modules: Flushing Advice" href="https://springmodules.dev.java.net/docs/reference/0.8/html/cache.html#flushingAdvice" target="_blank">flushing advice</a>) aus dem Cache bereitzustellen.</p>
<pre class="brush: xml">
&lt;bean id=&quot;cacheProviderFacade&quot; class=&quot;org.springmodules.cache.provider.ehcache.EhCacheFacade&quot;&gt;
        &lt;property name=&quot;cacheManager&quot; ref=&quot;cacheManager&quot; /&gt;
    &lt;/bean&gt;

    &lt;bean id=&quot;cacheManager&quot; class=&quot;org.springframework.cache.ehcache.EhCacheManagerFactoryBean&quot;&gt;
        &lt;property name=&quot;configLocation&quot; value=&quot;classpath:ehcache.xml&quot; /&gt;
    &lt;/bean&gt;

    &lt;bean id=&quot;fCacheableService&quot; class=&quot;org.springmodules.cache.interceptor.proxy.CacheProxyFactoryBean&quot;&gt;
      &lt;property name=&quot;cacheProviderFacade&quot; ref=&quot;cacheProviderFacade&quot; /&gt;
      &lt;property name=&quot;cachingModels&quot;&gt;
        &lt;props&gt;
          &lt;prop key=&quot;getCodes*&quot;&gt;cacheName=fCache&lt;/prop&gt;
        &lt;/props&gt;
      &lt;/property&gt;
      &lt;property name=&quot;target&quot; ref=&quot;fService&quot; /&gt;

      &lt;!-- Set a qualifier to distinguish between the available FServices --&gt;
      &lt;qualifier value=&quot;fMain&quot;/&gt;
    &lt;/bean&gt;
</pre>
<p>Wie man in der Konfiguration sehen kann, werden nur die Methoden <strong>getCodes*</strong> in dem Bean<strong> fService</strong> ge-cached. Mit dem Qualifier <strong>fMain</strong> kann man beim <a title="Spring Reference: Autowired" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation" target="_blank">Autowiring</a> nun das richtige Bean injizieren, denn durch den CacheProxyFactoryBean gibt es zwei Beans vom gleichen Typ.</p>
<p>Mit wenig Konfiguration hat man jetzt in Spring Caching eingeführt. Dabei wurde der Source-Code gar nicht angefasst &#8211; wenn man vom dem nun notwendigen <a title="Spring Reference: Fine tuning Autowired" href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation-qualifiers" target="_blank">@Qualifier</a> absieht.</p>
<p>Links:<br />
[1] Maven FAQ: <a title="Maven FAQ: Install 3th party library" href="http://maven.apache.org/general.html#importing-jars" target="_blank">Install 3th party library</a><br />
[2] Spring-Modules: <a title="Doc Spring-Modules: Cache" href="https://springmodules.dev.java.net/docs/reference/0.8/html/cache.html" target="_blank">Cache</a></p>
]]></content:encoded>
			<wfw:commentRss>http://my.center-of.info/2009/04/07/cache-method-results-with-ehcache-and-spring/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

