The objective of this post is to show how to configure the bussines cache with web services clients generated with maven cxf-codegen-plugin. The only special feature here is that you can not use the cache annotations (@Cacheable, @CacheEvict, etc.) because you have not access to the web service client source code. This code is generated by Maven in the compile phase.
In this example I will use the famous currency converter service: http://www.webservicex.com/CurrencyConvertor.asmx?wsdl
The first step is to configure pom.xml in order to parse the WSDL and to generate all needed classes.
<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>2.7.18</version> <executions> <execution> <id>generate-sources-wsdl</id> <phase>generate-sources</phase> <configuration> <wsdlOptions> <wsdlOption> <wsdl>${basedir}/src/main/resources/META-INF/wsdl/CurrencyConvertor.wsdl</wsdl> <extraargs> <extraarg>-xjc-XhashCode</extraarg> <extraarg>-xjc-Xequals</extraarg> <extraarg>-xjc-XtoString</extraarg> </extraargs> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.jvnet.jaxb2_commons</groupId> <artifactId>jaxb2-basics</artifactId> <version>1.11.1</version> </dependency> </dependencies> </plugin>
I have downloaded the wsdl file and have put it inside the project in /resources/META-INF/wsdl directory.
Next, you have to configure de jaxws client, so you could use this client as a managed spring bean. In a context config file (for example, cxf-config.xml) I have this:
<?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:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"> <property name="prettyLogging" value="true"/> </bean> <bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"> <property name="prettyLogging" value="true"/> </bean> <jaxws:client id="currencyConversorClient" name="{http://www.webserviceX.NET}CurrencyConvertorSoap12" serviceClass="net.webservicex.CurrencyConvertorSoap" address="http://www.webservicex.com/CurrencyConvertor.asmx"> <jaxws:outInterceptors> <ref bean="loggingOutInterceptor" /> </jaxws:outInterceptors> <jaxws:inInterceptors> <ref bean="loggingInInterceptor" /> </jaxws:inInterceptors> </jaxws:client> </beans>
With this configuration you can use the currencyConversorClient injected in other Spring managed beans, for example:
@Autowired private net.webservicex.CurrencyConvertorSoap currencyService;
And finally, you have to configure the cache in a declarative way, by using another context config file, as is explained in the reference documentation.
<!-- cache manager and annotation-driven configuration omited--> <!-- cache definitions --> <cache:advice id="currencyConversorWebServiceCacheAdvice" cache-manager="cacheManager"> <cache:caching cache="currency"> <cache:cacheable method="conversionRate"/> </cache:caching> </cache:advice> <aop:config> <aop:advisor advice-ref="currencyConversorWebServiceCacheAdvice" pointcut="execution(* net.webservicex.CurrencyConvertorSoap.*(..))"/> </aop:config>
In this snippet you declare a cache named "currency" over the conversionRate method in the CurrencyConvertorSoapCurrencyConvertorSoap service. Note that this is actually an interface which was generated by Maven.
Updated 1
Ultimately, a cache is just a hashmap like structure which store keys (the methods parameters) and values (the method return). In order to work properly, the cache keys must override the equals and hashcode methods, because two instances of a class with the same properties may not be equals.
The currency example is very basic and the method params are simple types, which don't require this approximation, but for complex scenarios this would be mandatory.
Updated 2
Under some circumstances (I don't know exactly when) you need to add a dependency with org.jboss.ironjacamar.jdbcadapters module in the jboss-deployment-structure.xml file. Otherwise you will get a very confusing error.
Check this post: http://trabajosdesisifo.blogspot.com.es/2016/08/jboss-illegalargumentexception-warning.html