How can I configure custom Serializers / Copiers in XML for JSR-107 (JCache) with Ehcache? - ehcache

I have a question concerning JCache / Ehcache XML configuration.
I'm using the JSR 107 Cache Annotations CDI Reference Implementation together with Ehcache.
I want to annotate specific methods with #CacheResult, so that the result of these methods will be cached in a cache generated for that specific method.
In our case, these methods have Optional as their return value, and as you probably know, Optional instances are not Serializable and thus cannot be cached by default.
The default used SerializingCopier and PlainJavaSerializer fail on this.
To solve this, I have implemented our own custom OptionalSerializer and OptionalCopier to be able to handle Optional values.
But I am not able to make JCache / Ehcache clear to use my custom Serializer and Copier when it comes around Optional return values.
I tried putting ehcache.xml on the classpath of JBoss EAP 6.4.0 (using JBoss modules) and I tried putting an ehcache.xml in the resources folder of the Maven module, but they are just plainly ignored.
Even if I make those XML's invalid, I don't get any error.
I want to avoid creating a CacheManager, referring to our own ehcache.xml configuration file programmatically, since I would have to create the caches then at that point. I don't want this.
I want the caches to be created by the Cache Annotations CDI CacheResultInterceptor, and I don't seem to have an option to override a method to create a CacheManager of my own...
Does anyone know what I should do to solve this issue?
I just want to use the provided interceptors, and have an XML configuration that specifies that custom serializers and copiers will need to be used for specific return types.
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>org.jsr107.ri.annotations.cdi.CacheResultInterceptor</class>
<class>org.jsr107.ri.annotations.cdi.CachePutInterceptor</class>
<class>org.jsr107.ri.annotations.cdi.CacheRemoveEntryInterceptor</class>
<class>org.jsr107.ri.annotations.cdi.CacheRemoveAllInterceptor</class>
</interceptors>
</beans>
Example method:
#CacheResult
public Optional<User> findUser(String username) {
return userDao.findUser(user);
}
What version of Ehcache you are currently using;
Ehcache 3.4.0
Paste the configuration for the Cache/CacheManager you have an issue with;
<ehcache:config xmlns:ehcache="http://www.ehcache.org/v3"
xmlns:jcache="http://www.ehcache.org/v3/jsr107">
<ehcache:service>
<jcache:defaults default-template="defaultTemplate"/>
</ehcache:service>
<ehcache:cache-template name="defaultTemplate">
<ehcache:value-type
serializer="be.post.min.client.cache.OptionalSerializer"
copier="be.post.min.client.cache.OptionalCopier">java.util.Optional</ehcache:value-type>
</ehcache:cache-template>
<ehcache:default-serializers>
<ehcache:serializer type="java.util.Optional">be.post.min.client.cache.OptionalSerializer</ehcache:serializer>
</ehcache:default-serializers>
<ehcache:default-copiers>
<ehcache:copier type="java.util.Optional">be.post.min.client.cache.OptionalCopier</ehcache:copier>
</ehcache:default-copiers>
</ehcache:config>
Add any name and version of other library or framework you use Ehcache with (e.g. Hibernate);
Java EE 6
EJB 3.x
CDI 1.x
JCache 1.0.0 (JSR 107)
JSR 107 Cache Annotations CDI RI 1.0.0
Providing JDK and OS versions maybe useful as well.
Java SDK 1.8 update 65
JBoss EAP 6.4.0
Windows 10

From my vague understanding of CDI, putting it in src/main/resources should work. Are you sure it ends up in your jar/war?

Related

Binding datasource to application when using springBootApplication in Liberty?

When deploying "regular" web apps to Liberty, I was used to binding the global datasource configured in Liberty's server.xml to the individual application by using a child element within the element, like this:
<application context-root="helloApp" location="..." name="helloApp" type="war">
<application-bnd>
<data-source id="db2appDs" name="jdbc/datasource" binding-name="jdbc/theDB"/>
</application-bnd>
...
</application>
<dataSource id="db2ds" jndiName="jdbc/theDB" type="javax.sql.DataSource">
...
</dataSource>
When configuring my first Spring Boot application to deploy to Liberty, I am trying to use the new <springBootApplication> element for it - but I don't seem to be able to add a binding for the datasource I want to use the same way, as this element doesn't seem to support such a child. (It seems to want only <classloader> as a child).
I've seen people suggest I use an #Resource annotation that includes both application-local JDNI name and global JNDI name for the datasorce - but that defeats the purpose, since I don't want to know what the global name is until deploy time.
Is there another way to do this, like we used to before? Or are applications deployed through <springBootApplication> expected to know the global JNDI name of the datasource(s) they want?
Application-defined datasources are not supported for <springBootApplication/>’s. While your application may certainly access a Liberty datasource using its global JNDI name, you should configure the spring.datasource.jndi-name property within your Spring Boot application as described in section 29.1.3 of the Spring Boot features reference. For your example try spring.datasource.jndi-name=jdbc/theDB.

Spring schema folder & Spring XML namespaces

I am looking for how we should determine the symbol of a namespace in Spring bean XML definitions. I guess they are in the Spring schema folder, but I can't find it. For example, what are c:, p:, util:, .. in the XML bean configuration?
Where can I find the schema's for each namespace? For example, how do I know if I should use http://www.springframework.org/schema/p in xmlns:p="http://www.springframework.org/schema/p", where are the other namespaces and how can I find them?
You can choose the symbol (p, util, jee, beans, ...) by yourself. These are namespaces, and they work by adding the xmlns attribute like:
<beans xmlns:util="http://www.springframework.org/schema/util">
<!-- Content -->
</beans>
In this case we said that util: will be used by the util schema, so you'll have to use <util:properties> to access things from this namespace. But you could also have said xmlns:foobar="http://www.springframework.org/schema/util" in which case you could have used things like <foobar:properties>.
But you also need to provide the location of the XSD of that namespace by using xsi:schemaLocation:
<beans xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Content -->
</beans>
In this case the XSD for http://www.springframework.org/schema/util is available at http://www.springframework.org/schema/util/spring-util.xsd. The http://www.springframework.org/schema/util part is just a label and can be chosen as well. The only thing that has to match is the XSD schema.
For more information about XML namespaces, you should look at this question and its answers.
A list of common XML schema's with Spring can be found in their documentation (33. XML Schema-based configuration). However, these only list the core schemas. Some projects (like Spring Web Services, ...) have their own namespaces like:
http://www.springframework.org/schema/web-services/web-services.xsd
http://www.springframework.org/schema/oxm/spring-oxm.xsd
...
You can find the entire list by visiting the Index of /schema. However, like I mentioned, most of these are only used for specific Spring projects, don't just import them, read the specific documentation to find out what you need. The documentation about the constructor namespace (c:) can be found in 7. The IoC container.

Get config setting in custom taglib using Spring "context-property-placeholder"

I'm creating a custom taglib, and would like to use some config options that are loaded via the underlying Spring framework using:
<context:property-placeholder location="classpath:config.properties" />
How would I get access to these variables in my taglib?
Thanks,
James.
The JSP taglibs have nothing in common with the Spring context's lifecycle, they're managed by the servlet container. This can complicate things a bit, for example: inject-dependency-into-a-taglib-class, how-to-write-tag-in-my-spring-project.
Since you're only mentioning the need for contents of the properties file, you could use plain old java.util.ResourceBundle (or, if you need more flexibility, Apache Commons' org.apache.commons.configuration.PropertiesConfiguration).
(One could also argue that requiring access to configuration in your tags indicates a design problem...)

Can I use Spring's caching features without the annotations?

I'm developing a module I was planning on using Spring's declarative caching to handle. I wrote a number of methods using the cache
#Override
#Cacheable("businessUnitCache")
public BusinessUnit getBusinessUnit(String businessUnitId){
I was planning to provide a classpath beans file and classpath eh-cache configuration to provide the functionality without requiring consuming projects to know the internals of my implementation and which methods need to be cached (many of these methods they'd never access directly).
However, reading the question Using Spring cache annotation in multiple modules and it's answers this is obviously going to cause a problem is any of the consuming projects use Spring cache annotations as well. I was hopeful that Sprint would fail silently if there was no declared cache matching an annotation, but it fails with the error:
java.lang.IllegalArgumentException: Cannot find cache named [businessUnitCache] for CacheableOperation[public
Leading me to the conclusion I can't use the cache annotations (which conflicts with my original conclusion from the question Is it possible to use multiple ehcache.xml (in different projects, same war)?. My testing backs this up.
So: Is it possible to declare the caching separately from the implementation classes, preferably in xml? This would allow me to prepare an additional file with the caching rules, and replace the cache manager name using standard spring property replacement (I'm already doing something similar with the datasource)? Unfortunately the refernece documentation only describes the annotation based configuration.
you can configure the cache using the xml file, see the spring reference manual:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/cache.html#cache-declarative-xml
<!-- the service we want to make cacheable -->
<bean id="bookService" class="x.y.service.DefaultBookService"/>
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="books">
<cache:cacheable method="findBook" key="#isbn"/>
<cache:cache-evict method="loadBooks" all-entries="true"/>
</cache:caching>
</cache:advice>
<!-- apply the cacheable behaviour to all BookService interfaces -->
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.BookService.*(..))"/>
</aop:config>

Switching spring application context or Impl java classes using maven profiles

I know the question I'm asking must be answered somewhere but I cant find an example on the net with some guidelines.
I wish to swap out the Spring 3.0 bean definition at build and runtime for a common codebase. I'm also using Maven profiles to build different versions of the same code.
Currently my bean def is
<bean id="somebean" class="com.x.SomeImpl" >
I will need to replace and deploy it at some times as
<bean id="somebean" class="com.x.SomeOtherImpl" >
Now the approaches I'm thinking of are
1) Use Maven profiles to switch out the complete applicationContext.xml to some other applicationContextB.xml based on the Maven profile.
2) Use Maven profiles to somehow? replace only the bean id definition for "somebean"
My questions are:
a) How can Option 2 be achieved?
b) These approaches still compile and package both SomeImpl and SomeOtherImpl during build. How can I pick only one and not the other for compliation and packaging into EAR?
I know Spring 3.1 has env profiles for the beans, but presently that's not an option.
You could consider using the maven resources and filtering feature available. You could have placeholders in your context file and a property file per profile holding values. In each profile, you could use a different property file and appropriately have your context file filtered.
Take a look to Maven Build Helper Plugin add-source.
You can combine profiles and Build Helper Plugin (add-source goal) to add the required classes in both cases.
you can import multiple config files to your config like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="applicationContextA.xml"/>
<import resource="applicationContextB"/>
</beans>
For switching you can use Spring profiles.

Resources