Printemps Cache Abstraction VS interfaces VS principaux param (“clé Null est retourné pour le cache de l'opération” d'erreur)
Tandis que la mise en œuvre, je suis tombé sur un problème avec le Printemps Cache Abstraction VS interfaces.
Disons que j'ai l'interface suivante:
package com.example.cache;
public interface IAddItMethod
{
Integer addIt(String key);
}
Et les deux implémentations suivantes:
package com.example.cache;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class MethodImplOne implements IAddItMethod
{
@Override
@Cacheable(value="integersPlusOne", key="#keyOne")
public Integer addIt(String keyOne)
{
return new Integer(Integer.parseInt(keyOne) + 1);
}
}
.
package com.example.cache;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class MethodImplTwo implements IAddItMethod
{
@Override
@Cacheable(value="integersPlusTwo", key="#keyTwo")
public Integer addIt(String keyTwo)
{
return new Integer(Integer.parseInt(keyTwo) + 2);
}
}
Noter que le IAddItMethod n'est pas le seul en précisant @Cacheable. Nous pourrions avoir d'autres de mise en œuvre (ex MethodImplThree) sans le @Cacheable annotation.
Nous avons un simple beans.xml avec:
context:component-scan base-package="com.example.cache"
Ajoutant à cela, deux cas de test jUnit:
package com.example.cache;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:beans.xml"})
public class MethodImplOneTest
{
@Autowired
@Qualifier("methodImplOne")
private IAddItMethod classUnderTest;
@Test
public void testInit()
{
int number = 1;
assertEquals(new Integer(number + 1), classUnderTest.addIt("" + number));
}
}
.
package com.example.cache;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:beans.xml"})
public class MethodImplTwoTest
{
@Autowired
@Qualifier("methodImplTwo")
private IAddItMethod classUnderTest;
@Test
public void testInit()
{
int number = 1;
assertEquals(new Integer(number + 2), classUnderTest.addIt("" + number));
}
}
Lorsque j'exécute les tests individuellement, ils réussissent.
Cependant, si je lance les deux ensemble (en sélectionnant le package, clic droit, exécuter en tant qu'), la seconde (pas nécessairement MethodImplTwoTest, juste le second en cours d'exécution) échoue avec l'exception suivante:
java.lang.IllegalArgumentException: clé Null est retourné pour l'opération de cache (peut-être que vous êtes en utilisant des paramètres nommés sur les classes sans les informations de débogage?) CacheableOperation[public java.lang.Entier com.exemple.le cache.MethodImplOne.addIt(java.lang.String)] caches=[integersPlusOne] | état=" | key='#keyOne' au org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheables(CacheAspectSupport.java:297) au org.springframework.le cache.l'intercepteur.CacheAspectSupport.execute(CacheAspectSupport.java:198) au org.springframework.le cache.l'intercepteur.CacheInterceptor.invoke(CacheInterceptor.java:66) au org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) au org.springframework.aop.cadre.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) à $Proxy16.addIt(Source Inconnue) au com.exemple.le cache.ITMethodImplOneIntegrationTest.testInit(ITMethodImplOneIntegrationTest.java:26) au coucher du soleil.de réfléchir.NativeMethodAccessorImpl.invoke0(Native method) au coucher du soleil.de réfléchir.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) au coucher du soleil.de réfléchir.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) à java.lang.de réfléchir.La méthode.invoke(la Méthode.java:597) au org.junit.les coureurs.de modèle.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) au org.junit.interne.les coureurs.de modèle.ReflectiveCallable.exécuter(ReflectiveCallable.java:15) au org.junit.les coureurs.de modèle.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) au org.junit.interne.les coureurs.des déclarations.InvokeMethod.évaluer(InvokeMethod.java:20) au org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) au org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) au org.springframework.test.contexte.junit4.des déclarations.SpringRepeat.évaluer(SpringRepeat.java:72) au org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) au org.junit.les coureurs.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) au org.junit.les coureurs.ParentRunner$3.exécuter(ParentRunner.java:231) au org.junit.les coureurs.ParentRunner$1.annexe(ParentRunner.java:60) au org.junit.les coureurs.ParentRunner.runChildren(ParentRunner.java:229) au org.junit.les coureurs.ParentRunner.l'accès$000(ParentRunner.java:50) au org.junit.les coureurs.ParentRunner$2.évaluer(ParentRunner.java:222) au org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) au org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) au org.junit.les coureurs.ParentRunner.exécuter(ParentRunner.java:300) au org.springframework.test.contexte.junit4.SpringJUnit4ClassRunner.exécuter(SpringJUnit4ClassRunner.java:174) au org.eclipse.jdt.interne.junit4.runner.JUnit4TestReference.exécuter(JUnit4TestReference.java:50) au org.eclipse.jdt.interne.junit.runner.TestExecution.exécuter(TestExecution.java:38) au org.eclipse.jdt.interne.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) au org.eclipse.jdt.interne.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) au org.eclipse.jdt.interne.junit.runner.RemoteTestRunner.exécuter(RemoteTestRunner.java:390) au org.eclipse.jdt.interne.junit.runner.RemoteTestRunner.principale(RemoteTestRunner.java:197)
note: j'utilise Eclipse STS 3.0 et le "Ajouter une variable d'attributs pour les fichiers de classe" est activé.
IMPORTANT: Si je ne spécifiez pas la "clé" dans le @Cacheable annotations, il fonctionne.
Est-il quelque chose que j'ai oublié de le préciser? config? les annotations?
Merci d'avance!
OriginalL'auteur dostiguy | 2013-01-07
Vous devez vous connecter pour publier un commentaire.
Ma conjecture est que pour jdk proxy le nom du paramètre est récupérée à partir de la méthode de l'interface il est donc
key
et paskeyTwo
.mise à jour: Vous pouvez essayer d'utiliser le paramètre index au lieu
voir http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/cache.html#cache-spel-context
J'ai ajouté un lien vers la documentation concernant l'accès aux paramètres par index, je n'ai pas essayé moi-même bien que
Bonne réflexion, j'avais oublié que nous pouvions le faire. Je l'ai essayé et a couru mes tests (mise en œuvre réelle a environ 100 cas de test, et les touches sont plus complexes que l'exemple) et cela fonctionne. Maintenant, je ne suis pas sûr de la façon que je préfère. Merci encore.
Trouvé ce problème lors de l'ajout d'
@Cachable
à un@FeignClient
interface. Merci!!!!!OriginalL'auteur Boris Treukhov