Posts tagged ‘spring’

Problem description

Another approach to the memoization topic mentioned previously came to me quite recently based on a problem with webservice call.

Imagine you have a webservice request/response exchange that’s taking a long time not only due to network latency but also due to the fact that your ws-logic performs a complicated ldap query.

So there are at least 3 reasons that might cause you a headache:

  1. slow internet connection
  2. slow ldap search
  3. big number of results that need to downloaded

In order to improve this situation results of method call might be cached inside ws-client’s code using ehacache. Cached entries will be identified based on method’s signature and passed arguments. The arguments should implement Serializable interface but this is already fulfilled since objects are passed through webservice calls.

Caching should be transparent to the caller – which should not know whether results he got were fetched from remote server or local cache. Additionally it should be configurable which methods calls should be cached or not and last but not least – since cached entries are identified by some key – it should be possible to define custom key-generator that would give the user freedom in defning key algorithm.

All the above requirements are summarized below:

  • webservice client api defined as interface
  • webservice client implementation that performs call to server
  • methods are chosen based on annotations
  • wraper defined as dynamic proxy so calls to client api are transparently may be cached and user is not aware if results come from cache or real call

Solution description

The solution will be spring-specific since Spring supports ehacache out-of-the-box.

Existing solutions

There exists already at least 3 solutions:

and somehow all of them combined fill the picture of what I’d expect from such a library:

Requirements
  1. Easy configuration with possibly as little xml as possible – smth like <context:component-scan> element with reasonable defaults
  2. Defining one annotation that enables method caching
  3. Including/Excluding methods from caching using annotation
Solution description

The approach descried in this post is realised by providing 3 main elements:

  1. Custom namespace handler implementing NamespaceHandlerSupport
  2. Custom bean definition parser extending AbstractSingleBeanDefinitionParser
  3. Custom BeanPostProcessor implmenting BeanFactoryAware interface
  4. Custom xsd

All points above respond to the requrements:

Points 1 and 2 let you declare usage of method cache with just one line of xml (after defining memoize namesapace) and creates EhCacheManagerFactoryBean and EhCacheFactoryBean behind-the-scenes freeing you from writing these explicitly inside you xml application context.

<memoize:use-method-cache
   config-location="classpath:ehcache.xml"
   cache-name="pl.bedkowski.code.memoize.sample.METHOD_CACHE" />

Point 3 finds classes annotated with Memoize annotation inside current context and wraps them inside Memoizer proxy, as well as fetches EhCacheFactoryBean instance created in the previous step.

@Component("wsClient")
@Memoize
public class WebServiceClientImpl implements WebServiceClient {

The Memoize annotation contains 2 properties:

  • keyGenerator – key generator class (must implement KeyGeneratorinterface)
  • type – one of Type.INCLUDE_ALL/Type.EXCLUDE_ALL

I think the last one needs some further explanation – it lets you define strategy for handling methods.

  • Default is Type.INCLUDE_ALL – which means that all methods that have non-void return type will be cached unless explicitly marked with Exclude annotation.
  • The reverse is Type.EXCLUDE_ALL which means that no method call will be cached unless marked with Includeannotation.

Sources, packages

Source available on github
Binaries available in repo

UPDATE: See updated version using ejb 3.1 compilant with any application server here.

Jakiś czas temu szukając informacji o szybkiej konfiguracji springa oraz połączeniu go z JAXB natrafiłem na blog Michała Mecha (strona Michała nie jest już dostępna – tekst w wayback machine)który to opisywał wspomniany przeze mnie problem.

Udało mi się w miarę sprawnie przenieść przykład, który zaprezentował na „własne podwórko” i zamiast wstrzykiwać do beana scieżkę do pliku który miałbyć zamieniony poprzez JAXB na obiekt, mogłem wstrzykiwać gotowy obiekt, a bean jak zwykle po prostu nie był swiadom skąd się ten obiekt wziął – z xml’a, czy może ktoś bo sobie „poskładał” łącząc odpowiednio pojo z mappingu xml’owego. Pojawił się tylko mały zgrzyt w momencie, gdy okazało się, że takich podmionionych bean’ów mam 40…

Zacząłem szukać jakiegoś sposobu aby uprościć konfigurację i zamknąć wszystko w jednej linijce i faktycznie udało się wykorzystując poszczególne elementy:

  • dodając do konfiga xml’owego przestrzeń nazw oxm
  • wykorzystując property editora
  • dodając element nadrzędny dla docelowego bean’a

Zmodyfikuje nieco oryginalny przykład w celu prezentacji rozwiązania:

Najpierw property editor w celu zamiany String’a na Source xml’owe:

package pl.bedkowski.test;

import java.beans.PropertyEditorSupport;
import java.io.File;

import javax.xml.transform.stream.StreamSource;

public class String2StreamSource extends PropertyEditorSupport {

	@Override
	public void setAsText(String filePath) {
		setValue(new StreamSource(new File(filePath)));
	}

}

No i kontekst apliacji:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:oxm="http://www.springframework.org/schema/oxm"

	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-1.5.xsd">

	<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
	  <property name="customEditors">
	    <map>
	      <entry key="javax.xml.transform.Source">
	        <bean class="pl.bedkowski.test.String2StreamSource"/>
	      </entry>
	    </map>
	  </property>
	</bean>

	<oxm:jaxb2-marshaller id="jaxb2Marshaller">
		<oxm:class-to-be-bound name="pl.michalmech.config.Config"/>
	</oxm:jaxb2-marshaller>

	<bean id="configParent"  class="pl.michalmech.config.Config" factory-bean="jaxb2Marshaller" factory-method="unmarshal" abstract="true" />

	<bean id="config1" parent="configParent">
		<constructor-arg value="config1.xml" />
	</bean>

	<bean id="config2" parent="configParent">
		<constructor-arg value="config2.xml" />
	</bean>

	<bean id="config3" parent="configParent">
		<constructor-arg value="config3.xml" />
	</bean>

	<bean id="config4" parent="configParent">
		<constructor-arg value="config4.xml" />
	</bean>

</beans>

Na początku może się wydawać, że to więcej jednak jeżeli odejmiemy te pare(-naście) linijek podczas każdej inicjalizacji bean’a dziedziczącego po „configParent”, podobnie do bean’ów z id’kami config1-config4.

Zdaję sobie sprawę, że dla niektórych ten wpis będzie równoznaczny z profanacją, ale ostatnio zastanawiałem się z której strony „ugryźć” problem przestawienia zależności w jednym projekcie na konfigurację spring’ową. Dlaczego – otóż nie miałem za bardzo pomysłu na zintegrowane rozwiązanie, obsługujące zależności w aplikacji w sposób kompleksowy, więc postanowiłem wybrać łatwiejsze rozwiązanie – wstawić xml’a, dorzucić jakiegoś prostego bean’a, a później to już pewnie jakoś pójdzie, no ale dobrze by było zacząć od początku.

Na pierwszy ogień wybrałem sobie plik konfiguracyjny. Poprzednia wersja aplikacji zawierała tekstowy plik konfiguracyjny w formacie zbliżonym do plików ini.

Na początek wyglądało to dość dobrze, bo trzeba było wpisać 2 rzeczy:

lista która to zawiera liste sekcji oddzielonych przecinkiem

– [sekcja1]

#ustawienia

[sekcja2]

#ustawienia

No i na pierwszy rzut oka to faktycznie ma sens, jednak po jakimś czasie okazało się, że to rozwiązanie dostarcza więcej problemów niż rozwiązuje a oto kilka z nich:

– zduplikowana konfiguracja – każde dodanie usunięcie sekcji wiązało się, z edycją wpisów w 2 miejscach

– mała elastyczność – zmiana opcji miejscami, w przypadku ich większej ilości to był koszmar

– małą czytelność w przypadku dużej liczby opcji

– brak wsparcia „ini with sections”  w javie – konieczność samodzielnego parsowania

No i zrodził sie pomysł zastąpienia tego xml’em springowym co w połączeniu z metodą getBeansOfType okazało się strzałem w dziesiątkę, tym bardziej, że opcje konfiguracyjne były już wczytywane do beana i dopiero później przekazywane dalej, więc jedyne co trzeba bylo zrobić to zdefiniować rodzica, podpiąć jary i już, oto przykład:


<!-- korzystam z <a href="http://static.springsource.org/spring/docs/2.0.x/reference/beans.html#beans-p-namespace">p namespace</a> -->

<beans>

<bean class="sample.Bean" id="parent" abstract="true" p:commonProperty="sampleValue" />

<bean id="bean1" parent="parent" p:property="jakas wlasnosc" />

</beans>