Spring #Cacheable with complex keys still executed - java

I have the following for the usage of a #Cacheable in spring (3.1):
spring:
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" />
<!-- Ehcache library setup -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml" />
Maven:
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.3</version>
</dependency>
The to be cached method:
#Cacheable(value="cahceName", key="concat(#param1).concat(‘-’).concat(#param2)")
public String cachedMethod(String param1,String param2)
Alas, when I debug the code, I see that the cached method gets called more than once even when param1 and param2 are the same (i.e the cahce is not used).
Any ideas?

The key does not appear correct -
You may have meant - #Cacheable(value="cacheName", key="#param1.concat(‘-’).concat(#param2)")
Further, if the compilation is done without debug information, the param1, param2 argument names will not be available to expression evaluator. Instead you can refer to them using p0, p1 etc this way:
#Cacheable(value="cahceName", key="#p0.concat('-').concat(#p1)")
Update:
I have a one page test here which demonstrates how this works - https://gist.github.com/3315275

In my case, the problem was caused by using the wrong configuration of the cache provider (Caffeine):
#Bean
public Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(1000)
.expireAfterAccess(10, TimeUnit.MINUTES)
.weakKeys(); // cause problems when concatenated keys used
}
As the docs says, weakKeys() method:
Specifies that each key (not value) stored in the cache should be wrapped in a WeakReference (by default, strong references are used).
Warning: when this method is used, the resulting cache will use identity ({#code ==})
comparison to determine equality of keys. Its {#link Cache#asMap} view will therefore
technically violate the {#link Map} specification (in the same way that {#link IdentityHashMap}
does).

Related

Spring config Map overrides Keys with value bean names

I'm having trouble trying to create a map in Spring config, since the keys I define are replaced when the map is autowired.
I defined the map in my spring-config.xml
<?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:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="basePackageWhereMyBeansAre"/>
<util:map id="beanMapper" map-class="java.util.HashMap">
<entry key="QueryType1" value-ref="bean1"/>
<entry key="QueryType2" value-ref="bean2"/>
</util:map>
</beans>
I try to autowire the map in my Java code:
#Resource
Map<String, BeanSuperClass> beanMapper;
#Autowired
DefaultBeanClass defaultBean;
public String callMethod(Query query) {
BeanSuperClass bean = beanMapper.getOrDefault(query.getTypeName(), defaultBean);
...
}
The problem is that when I debug the Java code and I check the beanMapper object, I can see that the keys for the entries are replaced with the bean names:
beanMapper {
entry: key="bean1" (the bean name), value=bean1 (the actual bean)
entry: key="bean2" (the bean name), value=bean2 (the actual bean)
}
so beanMapper.getOrDefault() always returns the defaultBean.
Does anyone knows why the keys are replaced? What am I doing wrong?
Thanks in advance

spring security oauth2 check_token using Xml

I'm trying to enable outh/check_token using but having some difficulty
according to this answer How to enable /oauth/check_token with Spring Security Oauth2 using XML
You need to create a bean of type CheckTokenEndpoint.
How do we do that I included this in my spring security.xml
<bean id="checkTokenEndpoint" class="org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint">
<constructor-arg name="resourceServerTokenServices" ref="tokenServices"/>
</bean>
this class org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint is throwing error
Multiple annotations found at this line:
- Class 'org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint' not found
- Class 'org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint' not found [config set: AuthenticationApp/web-
context]
this is all the
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
Can someone please help all the examples are using spring boot and java config but I have to do using xml config
Use the last version of spring oauth2:
<dependency>
<groupId>org.springframework.security.oauth</groupId
<artifactId>spring-security-oauth2</artifactId
<version>2.0.10.RELEASE</version>
</dependency>
Ensure what the correct version of xsd is in use in spring security oauth file configuration:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd>
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
Insert the option check-token-enabled="true" in the element authorization-server:
<oauth:authorization-server check-token-enabled="true" client-details-service-ref="jdbcClientDetailsService"/>

spring xml override utils:list same id

I'm trying to set up a local overrides file for some of my bean definitions. Yes, it's a fragile system, but it's just for testing. Basically, I've got one XML file which looks more or less like:
<?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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- so many beaaaannzzz -->
<utils:list id="partnerList" value-type="my.partner.Class">
<ref bean="previouslyDefinedBean"/>
</utils:list>
<!-- include local bean definition overrides -->
<import resource="file://${user.home}/somedirectory/prefix-*.xml"/>
</beans>
This works in general, but it has an unexpected and undesirable result with the utils:list element.
My somedirectory/prefix-*.xml override file defines another list:
<utils:list id="partnerList" value-type="my.partner.class">
<ref bean="otherBean"/>
</utils:list>
When it is picked up however, I get an undesired result: partnerList has two beans in it, previouslyDefinedBean and otherBean, while I want it to only have the latter.
Now, I'm aware Spring offers some weird weird collection merging, so I tried setting <utils:list merge="false"... but that blew up as an unsupported attribute. Is there something I can do to continue using this override system for the util:list, or have I got to take another tack entirely?

Spring #Aspect & Maven. Not working in external modules, but it's working witouth annotations

I've a question about Spring AOP and AspectJ, defining aspects, pointcut etc with annotations.
The context is this:
I have 2 maven modules (A and B).
Module B uses module A (via <dependency>...</dependency> in maven) and import his spring context.
I'm trying to write and use an very stupid test aspect (catch all public operations).
This aspect is defined in module A,
I wan't that this aspect works when I call any public operation in A or B.
Well, now the "postergeist". My first aproach was define all in XML. Aspect, pointcut, etc. And it works really well. This is the code:
ApplicationContext
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<aop:config>
<aop:aspect id="myAspectAOP" ref="myAspect">
<aop:around method="validateCall"
pointcut="execution(public * *(..))" />
</aop:aspect>
</aop:config>
<context:component-scan base-package="com.mypackage"/>
</beans>
MyAspect.java and Test.java is the same that the next case (without Aspect annotations). I don't put it here yet to avoid spreading much text.
That works fine!
Ok, next aproach. Using annotations. This is the code:
ApplicationContext
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.mypackage"/>
</beans>
And MyAspect class
#Aspect
#Component //I have tried without this annotation, and it doesn't work
public class MyAspect {
#Pointcut("execution(public * *(..))")
public void allPublic() {
}
#Around("allPublic()")
public Object validateCall(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// Some Code
}
}
Test.java (package com.mypackage)
#Component
public class Test{
public void foo(){
//Some code
}
}
In this case:
when I put Test.java into module B and call an public operation (remember, class is in B module), it doesn't work.
BUT when I put Test.java into A Module and I call a public operation (It's in A module), it works. It looks like only works with calls to public operations of classes defined into the same module where Aspect is defined (A module), but not in "externals" (B Module). Remember. B module includes/uses A Module and import his context. But it isn't happening when I use "xml declaration" instead of "annotations declaration"
Important: MyAspect.java is in A Module allways
Remember, in the first case (defining all in applicationContext, and not using #Aspect #Pointcut,#...) works allways, in B and A module public operations.
In both cases, the classes are into com.mypackage, so are injected by spring.
I'm really lost, It's the first time I get this kind of "postergeist", and I have been looking and looking into Spring documentation an google for days, but I can't find any solution.
I'm using Spring 3.1.2 and Aspectj 1.6.11
Please, any idea?
Thanks!

spring + aspectj, define an aspect #Around

i want to define an #Around aspect for a method of my #Entity
All my entities are in package data.entity
A define an aspect like this:
#Aspect
public class TestAspect {
#Around("execution(* data.entity..*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("INTERCEPT: "+pjp.toLongString());
return pjp.proceed();
}
}
But never is intercepted... where is my error?
In spring 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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="data.dao, data.service" />
<tx:annotation-driven proxy-target-class="true"/>
<aop:aspectj-autoproxy/>
<bean id="testAspect" class="spring.TestAspect" />
... datasource and other ...
</beans>
I try also
#Around("target(data.entity.MyEntity)")
and
#Around("target(data.entity..)")
but still not work.
Thanks.
It looks like you use spring-proxy-aop. This works only if the class is a spring manged bean, and the adviced method must be invoked from an other object.
Try to use real aspectJ instead of spring-proxy-aop.
I have just started using AOP and below are the findings at my level
i am assuming you have necessary jar files, aspectjweaver-1.6.10.jar and org.springframework.aop-3.0.5.RELEASE.jar present in your apps classpath.
The method aroundAdvice, as you have defined currently is perfect.
Could you remove the below line and try.
<context:component-scan base-package="data.dao, data.service" />

Categories

Resources