Skip to content

How to resolve error Type referred to is not an annotation type exception?

Introduction

In this post, I will demonstrate how to resolve the error “Type referred to is not an annotation type” when using Spring AOP.

Environment

  • SpringBoot 2
  • Java 1.8+
  • AspectJ Tools 1.9.4

The POM

We only use SpringBoot 2 and AspectJ 1.9.4. The POM is as follows:

pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

The Code

We want to use Spring AOP to add logging ability to SpringBoot web controllers. The code is as follows:

The Controller

HelloController.java
package com.bswen.testspringaop.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@RequestMapping(value = "hello")
public @ResponseBody String getHello() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
}
}

This controller simply returns a string, accessible at the URL http://localhost:8080/hello.

The Spring AOP Aspect

MyConrollerLogger.java
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyConrollerLogger {
private static Logger logger = LoggerFactory.getLogger(MyConrollerLogger.class);
@Around("@within(com.bswen.testspringaop.controllers.HelloController)") // we want HelloController to be instrumented
public void logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.nanoTime();
Object retval = pjp.proceed();
long end = System.nanoTime();
String methodName = pjp.getSignature().getName();
logger.info("Execution of " + methodName + " took " +
TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
}
}

When running the code, we encounter the following error:

Terminal window
2019-07-06 22:54:40.012 WARN 22494 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat': Initialization of bean failed; nested exception is **java.lang.IllegalArgumentException: error Type referred to is not an annotation type: com.bswen.testspringaop.controllers.HelloController**
2019-07-06 22:54:40.024 INFO 22494 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-07-06 22:54:40.039 ERROR 22494 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: com.bswen.testspringaop.controllers.HelloController
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.0.6.RELEASE.jar:5.0.6.RELEASE]

Why did this error happen?

The error occurred because we misused the within expression. According to the Spring AOP documentation, the within expression is used as follows:

  • Any join point (method execution only in Spring AOP) within the service package:
    • within(com.xyz.service.*)
  • Any join point (method execution only in Spring AOP) within the service package or a sub-package:
    • within(com.xyz.service..*)
  • Any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation:
    • @within(org.springframework.transaction.annotation.Transactional)

In our case, we used the within expression incorrectly:

@Around("within(@com.bswen.testspringaop.controllers.HelloController *)")

This caused Spring to look for a class annotated with @HelloController, which does not exist, resulting in the error.

How to resolve this problem?

We should change the pointcut expression to:

@Around("within(com.bswen.testspringaop.controllers.*)")

This means any class under the com.bswen.testspringaop.controllers package should be instrumented.

After making this change, running the code produces the following output:

Terminal window
2019-07-06 23:29:09.443 INFO 22579 --- [nio-8080-exec-1] c.b.t.aspects.MyConrollerLogger : Execution of getHello took 1007 ms

Summary

When using Spring AOP, it’s crucial to use the within pointcut expression correctly. Misusing it can lead to errors like “Type referred to is not an annotation type.” Always ensure that the expression targets the correct package or class, and avoid using @within unless you are targeting an annotation. By following these guidelines, you can effectively leverage Spring AOP for logging and other cross-cutting concerns.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!