# Spring common mistake : bypassing the proxy features

I want to share with you a common mistake I find in codebases using Spring when it comes to features auto-magically added by annotations.

Let's start with this piece of code :

```java
@Service
public class MyLibrary {

    BookRepository bookRepository;

    @Cacheable("books")
    public Collection<Book> fetchAllBooks() {
        // Do some resources intensive request here
        return bookRepository.fetchAllBooks();
    }
}
```

Pretty straightforward: in our bean `MyLibrary`, the method `fetchAllBooks()` fetches some books and the annotation `@Cacheable` from Spring Cache enables some caching of the result to avoid doing the query at every call. So far so good.

What if I add another method :

```java
@Service
public class MyLibrary {

    BookRepository bookRepository;

    public void createBook(Book Book) {
        // Let's pretend we need the collection of existing books :
        Collection<Book> existingCollection = this.fetchAllBooks();
        // do something with the new book and the collection
    }

    @Cacheable("books")
    public Collection<Book> fetchAllBooks() {
        // Do some resources intensive request here
        return bookRepository.fetchAllBooks();
    }
}
```

Here the method `createBook()` needs to fetch some books too (bear with me for the sake of the example), so it makes sense to call the one already there, right? We expect the method `createBook()` to get the collection of existing books **from the cache**.

**Unfortunately, it won't work as expected**: the cache will never be used, and here is why.

All the nice features of Spring enabled by those annotations are implemented using proxies (and a lot of [AOP](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/aop.html)). As you may know, when you inject the MyLibrary bean, you don't get exactly the instance of the MyLibrary class, instead, **you get a proxy**.

To implement the caching mechanism around the method `fetchAllBooks()`, Spring creates a proxy that will do the caching for you, and only call your method `fetchAllBooks()` if there is nothing in the cache. All your public methods are in fact proxied, even if no extra behavior is implemented.

```java
public class ProxyOfMyLibrary {
    // The class name would be 'MyLibrary$$SpringCGLIB$$0' in reality

    // A reference to your original MyLibrary class
    MyLibrary target;

    public void createBook(Book Book) {
        // Your code is called here
        target.createBook(Book);
    }

    public Collection<Book> fetchAllBooks() {
        // fetch an existing value in cache
        // if found, return it
        // else, call target.fetchAllBooks() (i.e. your code)
        // then store the result in cache
        // and return it
    }
}
```

This is of course simplified but the important info is this:

`ProxyOfMyLibrary.createBook()` will call the real `MyLibrary.createBook()` that you wrote, and your method calls `MyLibrary.fetchAllBooks()`, **not** `ProxyOfMyLibrary.fetchAllBooks()` in which the caching mechanism is.

I often see this with `@Cacheable` but keep in mind that this would apply to any other annotation that adds behavior to your code like `@Transactional`,`@RolesAllowed` or `@Secured`, to name a few.

## How to fix this?

The simple solution would be to put the annotation `@Cacheable` on another bean, the BookRepository in my example.

Another solution is to inject the bean into itself: you will get a pointer to the proxy, on which you call the method.

```java
@Service
public class MyLibrary implements ApplicationContextAware {

    MyLibrary self;
    BookRepository bookRepository;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.self = applicationContext.getBean(MyLibrary.class);
    }

    public void createBook(Book Book) {
        // Note that we don't use 'this' but 'self' here
        Collection<Book> existingCollection = self.fetchAllBooks();
    }

    @Cacheable("books")
    public Collection<Book> fetchAllBooks() {
        return bookRepository.fetchAllBooks();
    }
}
```

However, I would advise against doing this if you can avoid it, as it clutters your code and is a smell of a class trying to do too much.

I hope this can explain why, sometimes, Spring's magic doesn't seem to work.  
Let me know if this helped you avoid a headache!
