Thank you to click my question. I want to call a caching method in self-invocation, so I need to use AspectJ. (cache's config is okay)
implementation 'org.springframework.boot:spring-boot-starter-aop'
@EnableJpaAuditing
@EnableCaching(mode = AdviceMode.ASPECTJ) // <-- here 
@SpringBootApplication
public class DoctorAnswerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DoctorAnswerApplication.class, args);
    }
}
@Service
public class PredictionService {
    @Cacheable(value = "findCompletedRecordCache")
    public HealthCheckupRecord getRecordComplete(Long memberId, String checkupDate) {
        Optional<HealthCheckupRecord> recordCheckupData;
        recordCheckupData = healthCheckupRecordRepository.findByMemberIdAndCheckupDateAndStep(memberId, checkupDate, RecordStep.COMPLETE);
        return recordCheckupData.orElseThrow(NoSuchElementException::new);
    }
}
    @Test
    public void getRecordCompleteCacheCreate() {
        // given
        Long memberId = (long)this.testUserId;
        List<HealthCheckupRecord> recordDesc = healthCheckupRecordRepository.findByMemberIdAndStepOrderByCheckupDateDesc(testUserId, RecordStep.COMPLETE);
        String checkupDate = recordDesc.get(0).getCheckupDate();
        String checkupDate2 = recordDesc.get(1).getCheckupDate();
        // when
        HealthCheckupRecord first = predictionService.getRecordComplete(memberId,checkupDate);
        HealthCheckupRecord second = predictionService.getRecordComplete(memberId,checkupDate);
        HealthCheckupRecord third = predictionService.getRecordComplete(memberId,checkupDate2);
        // then
        assertThat(first).isEqualTo(second);
        assertThat(first).isNotEqualTo(third);
    }
What did I don't...?
I didn't make any class related with aspectJ.
I think @EnableCaching(mode = AdviceMode.ASPECTJ) make @Cacheable work by AspectJ instead Spring AOP(proxy).
With thanks to @kriegaex, he fixed me by pointing out the spring-aspects dependency and the load-time-weaving javaagent requirement. For the convenience of others, the configuration snippets for Spring Boot and Maven follow.
(Note: In the end, I didn't feel all this (and the side-effects) were worth it for my project. See my other answer for a simple, if somewhat ugly, workaround.)
POM:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
Application Config:
@Configuration
@EnableCaching(mode = AdviceMode.ASPECTJ)
public class ApplicationConfig { ... }
Target Method:
@Cacheable(cacheNames = { "cache-name" })
public Thingy fetchThingy(String identifier) { ... }
Weaving mechanism:
Option 1: Load Time Weaving (Spring default)
Use JVM javaagent argument or add to your servlet container libs
-javaagent:<path-to-jar>/aspectjweaver-<version>.jar
Option 2: Compile Time Weaving
(This supposedly works, but I found a lack of coherent examples for use with Spring Caching - see further reading below)
Use aspectj-maven-plugin: https://www.mojohaus.org/aspectj-maven-plugin/index.html
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.11</version>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <outxml>true</outxml>
        <showWeaveInfo>false</showWeaveInfo>
        <Xlint>warning</Xlint>
        <verbose>false</verbose>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
        <complianceLevel>${java.version}</complianceLevel>
        <source>${java.version}</source>
        <target>${java.version}</target>
    </configuration>
</plugin>
For reference/search purposes, here is the error that started all this:
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/cache/aspectj/AspectJCachingConfiguration.class] cannot be opened because it does not exist
More reading:
Did you read the Javadoc for EnableCaching?
Note that if the mode() is set to
AdviceMode.ASPECTJ, then the value of theproxyTargetClass()attribute will be ignored. Note also that in this case thespring-aspectsmodule JAR must be present on the classpath, with compile-time weaving or load-time weaving applying the aspect to the affected classes. There is no proxy involved in such a scenario; local calls will be intercepted as well.
So please check if you
spring-aspects on the class path andjava -javaagent:/path/to/aspectjweaver.jar.There is an alternative to #2, but using the Java agent is the easiest. I am not a Spring user, so I am not an expert in Spring configuration, but even a Spring noob like me succeeded with the Java agent, so please give that a shot first.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With