Spring App Error: EL1008E

DaniloV picture DaniloV · Mar 9, 2016 · Viewed 13.5k times · Source

I have been working on a Spring Integration project using Enterprise Integration Patterns to consume MQ messages, do some processing, then write them to another queue.

My problem appears very similar to this one however the accepted answer hasn't fixed it for me.

After receiving a response from an external web service, my @Cacheable @Component class returns the body as an ArrayList. I am getting the following error:

org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 1): Property or field 'valid' cannot be found on object of type 'java.util.ArrayList' - maybe not public?

Here is, what I believe to be, the offending class:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.curator.x.discovery.ServiceCache;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

@Component
public class DirectoryRepo {

    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private ServiceCache<ServiceDetail> directoryServiceCache;

    @Autowired
    private RestTemplate restTemplate;

    private ArrayList<X> response;

    private static final Logger logger = LogManager.getLogger();

    @Cacheable(value = "X", unless = "!#result.valid")
    public ArrayList<X> checkForX(String a,
            String b, String c, String d) {

            try {

                //code omitted

                HttpHeaders headers = new HttpHeaders();
                headers.add("token", service.getPayload().getToken());

                ResponseEntity<X[]> responseEntity = restTemplate
                        .exchange(request, HttpMethod.GET, new HttpEntity<>(
                                headers), X[].class);


                if (responseEntity != null && responseEntity.hasBody()) {

                    response = new ArrayList<X>(Arrays.asList(responseEntity.getBody()));
                    return response;
                } else {
                    logger.debug("received unexpected responseEntity: {}",
                            responseEntity);
                }
            } catch (RestClientException e) {
                logger.error("failed to get X - {}",
                        e.getMessage(), e);
            }

        throw new ServiceException(
                "failed to get X - Directory service unavailable");
    }

    public ArrayList<X> getResponse() {
        return this.response;
    }

    /**
     * Clears out all entries from the X cache.
     */
    @CacheEvict(value = "X", allEntries = true)
    public void clearXCache() {
        logger.trace("cacheManager:{}", cacheManager);
    }

}

As you can see I have tried setting a public getter method, but the exception still occurs:

org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 1): Property or field 'valid' cannot be found on object of type 'java.util.ArrayList' - maybe not public
?
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:224) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE
]
        at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:374) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4
.RELEASE]
        at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:170) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.OperatorNot.getValueInternal(OperatorNot.java:47) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.OperatorNot.getValueInternal(OperatorNot.java:36) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:131) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:299) ~[spring-expression-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.cache.interceptor.ExpressionEvaluator.unless(ExpressionEvaluator.java:123) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.canPutToCache(CacheAspectSupport.java:623) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELE
ASE]
        at org.springframework.cache.interceptor.CacheAspectSupport$CachePutRequest.apply(CacheAspectSupport.java:675) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:361) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:302) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
        at somepackage.DirectoryRepo$$EnhancerBySpringCGLIB$$f7709589.checkForX(<generated>) ~[DirectoryRepo.class:?]
        at somepackage.DirectoryService.getX(DirectoryService.java:66) ~[DirectoryService.class:?]

context.xml:

<?xml version='1.0' encoding='utf-8'?>
<Context displayName="appName" path="/appName" copyXML="true">

</Context>

Answer

Gary Russell picture Gary Russell · Mar 9, 2016

The error seems pretty clear to me.

It's not clear what you are trying to do. The #result variable is a reference to the ...er... result of calling the method - i.e. the ArrayList.

ArrayList does not have a isValid() or getValid() method.

The documentation about Conditional Caching describes what variables are available to you.

As you can see I have tried setting a public getter method

I don't see any such thing.

You can do things like result.size() > 0, a != 'foo'.