Java and Spring development

Posts Tagged ‘Spring

@AspectJ examples with pointcuts based on annotations

with 7 comments

This example demonstrates how to trace methods, constructors and fields annotated with @Inject and that’s inside a class annotated with @Component or a specialization of it like @Service. The aspect has three advices that combines different pointcuts. All the pointcuts uses primary marker interfaces (annotations) to determine where to place the adviced code. The annotations used in the pointcuts have target set to either method or type.

The example consist of a Demo class, a TraceAspect, a Spring configuration file and a JUnit test. The test starts the Spring container and the container injects all fields, methods and constructors in the Demo and DemoTest classes annotated with @Inject. It’s this dependency injection that the aspect will monitor and trace. The last part is when the test method calls the toString() method on the demo object and the toString() method reads the value in the text field. This get operation on the field is also monitored and traced by the aspect.

The Demo class

The Demo class has a text field that’s impossible to advice when the field gets set, since the Spring container injects the value with reflection and it’s no places in the code that sets this field. But it’s possible to advice the toString() method that reads this field. The constructor and method annotated with @Inject are adviced after they have returned successfully.

package demo;

import javax.inject.Inject;
import javax.inject.Named;

import org.springframework.stereotype.Service;

@Service
public class Demo {

	@Inject
	private String text;

	private final Integer integerOne;

	private Integer integerTwo;

	@Inject
	@Named("integerOne")
	public Demo(final Integer integerOne) {
		this.integerOne = integerOne;
	}

	@Inject
	@Named("integerTwo")
	public void setintegerTwo(final Integer integerTwo) {
		this.integerTwo = integerTwo;
	}

	@Override
	public String toString() {
		return "Demo [integerOne=" + integerOne + ", integerTwo=" + integerTwo
				+ ", text=" + text + "]";
	}
}

A screenshot from STS with AspectJ nature enabled:

adviced-demo-class

The first two orange arrows shows the joinpoint for two afterReturn advices, while the last one show the joinpoint for an around advice.

The TraceAspect class

Briefly summarized, the aspect below traces all methods and constructors in the demo package annotated with @Inject and that’s inside a type annotated with @Component or a specialization of it. Further, it demonstrates how to declare a pointcut with or without @args(..). The last advice is an around advice that traces all String fields annotated with @Inject in the demo package. It also prints out the return value.

package demo;

import javax.inject.Inject;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.junit.Test;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

/**
 * An example aspect that shows how to write pointcuts for annotated fields, methods and
 * types and how to advice those aspects.
 *
 * <p>
 * <ul>
 * 	<li>annotation target set to method</li>
 *
<ul>
	<li>{@link Inject @Inject}, {@link Test @Test}</li>
</ul>
 *  <li>annotation target set to type</li>
 *
<ul>
	<li>{@link Component @Component} or a specialization of it</li>
</ul>
 *  	({@link Service @Service}, {@link Repository @Repository})
 * </ul>
 *
 * @author Espen Berntsen
 * @see Demo
 */
@Aspect
public class TraceAspect {

	// Trace injected methods and constructors -->
	@Pointcut("within(@(@org.springframework.stereotype.Component *) *)")
	public void beanAnnotatedWithComponentOrASpecializationOfIt() {}

	@Pointcut("execution(@javax.inject.Inject * demo.*.*(..))")
	public void methodAnnotatedWithInjectAndInDemoPackage() {}

	@Pointcut("execution(@javax.inject.Inject demo.*.new(Integer)) && args(integer)")
	public void constructorAnnotatedWithInjectAndIndemoPackage(
			Integer integer) {}

	// With args(integer).
	@AfterReturning("beanAnnotatedWithComponentOrASpecializationOfIt() &&  " +
			"constructorAnnotatedWithInjectAndIndemoPackage(integer)")
	public void afterReturningFromConstructorInSpringBeanWithIntegerParameter(
			JoinPoint joinPoint, Integer integer) {
		System.out.println("Executed @Injected constructor: "
				+ joinPoint.getSignature() + " with the integer: " + integer);

	}

	// Using joinPoint.getArgs() to show arguments.
	@AfterReturning("beanAnnotatedWithComponentOrASpecializationOfIt() &&  " +
			"methodAnnotatedWithInjectAndInDemoPackage()")
	public void afterReturningFromMethodInSpringBean(JoinPoint joinPoint) {
		System.out.print("Executed the @Injected method: "
				+ joinPoint.getSignature() + " with value(s): ");

		for (Object object : joinPoint.getArgs()) {
			System.out.print(object);
		}
		System.out.println();
	}
	// Trace injected methods and constructors <--

	// Trace get on String fields annotated with @Inject -->
	@Pointcut("get(@javax.inject.Inject java.lang.String demo..*.*)")
	public void getStringFieldAnnotatedWithInjectInTheDemoPackage() {}

	@Pointcut("!withincode(@org.junit.Test * demo..*(..))")
	public void notInTestMethod() {}

	@Pointcut("getStringFieldAnnotatedWithInjectInTheDemoPackage() && notInTestMethod()")
	public void getStringFieldAnnotatedWithInjectInTheDemoPackageAndNotInTestMethod() {}

	@Around("getStringFieldAnnotatedWithInjectInTheDemoPackageAndNotInTestMethod()")
	public String aroundGetStringFieldAnnotatedWithInjectInTheDemoPackageAndNotInTestMethod(
			ProceedingJoinPoint joinPoint) throws Throwable {

		String fieldValue = (String) joinPoint.proceed();
		System.out.println("Get on @Inject String field: "
				+ joinPoint.getSignature() + " with value: " + fieldValue);
		return fieldValue;
	}
	// Trace get on String fields annotated with @Inject <--
}

The Spring configuration file

The configuration file below contains a component-scan element that finds the Demo class because it’s annotated with @Service. The three other beans are injected into the demo bean’s field, constructor and method marked with @Inject. This is enabled with the component-scan or annotation-config element in the context namespace. Since it’s two integers, the method and constructor in the Demo class also have an @Named(..) annotation with a value equal to the bean id that’s injected.

<?xml version="1.0" encoding="UTF-8"?>
xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:component-scan base-package="demo" />

	<bean id="a" class="java.lang.String" factory-method="valueOf">
		<constructor-arg value="test" />
	</bean>

	<bean id="integerOne" class="java.lang.Integer" factory-method="valueOf">
		<constructor-arg value="1" />
	</bean>

	<bean id="integerTwo" class="java.lang.Integer" factory-method="valueOf">
		<constructor-arg value="2" />
	</bean>
</beans>

The test class

Finally, the test class that instantiates the Spring container executes the toString() method on the demo object. If you’re not familiar with Spring, you can replace the Spring configuration with a factory method in the test class instead as long as you’re setting the @Inject field, constructor and method.

package demo;

import javax.inject.Inject;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Should have been a main method, but I use the
 * {@link Test} annotation to demonstrate withincode designator
 * {@link TraceAspect#beanAnnotatedWithComponentOrASpecializationOfIt()}
 *
 * @author Espen Berntsen
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(&quot;config.xml&quot;)
public class DemoTest {

	@Inject
	private Demo demo;

	@Test
	public void testToString() {
		System.out.println(&quot;demo.toString(): &quot; + demo.toString());
	}
}

The console output after executing the test class:

Executed @Injected constructor: demo.Demo(Integer) with the integer: 1
Executed the @Injected method: void demo.Demo.setintegerTwo(Integer) with value(s): 2
Get on @Inject String field: String demo.Demo.text with value: test
demo.toString(): Demo [integerOne=1, integerTwo=2, text=test]

Summary

Annotations are very good pointcuts and are frequently used by application containers to add enterprise features. See also this cheat sheet for more information about how to write aspects with @AspectJ style.

The code used in this article was developed in my work time at Redpill Linpro.


Redpill Linpro is the leading provider of Professional Open Source services and products in the Nordic region.

Written by Espen

March 18, 2010 at 22:28

Posted in Aspects

Tagged with , , , ,

Monitoring a web application with tcServer developer edition

with 8 comments

The tcServer developer edition is a Tomcat server with monitor support. The monitor support is provided through a tcServer template called Spring insight. The template is a web application. The monitor data from your application are gathered with AspectJ load-time weaving, stored in memory and presented on the Spring insight web site deployed on the tcServer developer edition server. For local monitoring, you can find the insight application here: http://localhost:8080/insight.

The screenshot shows all the recent traffic to the demo application’s servlets. A click on one of the bars gives you access to detailed information about the requests processed in that time period.

The other view is application health. The screenshot below shows the application health for the “findBalance” web service.

The service monitored above behave quite well and Spring insight claims its health is excellent.

If you click on one of the bars, you can drill down to each response and see details for that response:

The example is from a web service and shows which parameters and return types my monitored beans are invoked with. Almost all the execution time for this request was used in the repository and you can see that the repository throwed an exception back. You can even read the exception message. If you’re using the WEB browser inside Spring Tool Suite (STS), you can also jump directly into the source code through the “Go to STS” link.

For a full introduction into monitoring with tcServer and Spring insight, you should see this presentation. It shows that you can see all the SQLs sent to the database and all the HTTP request and response messages handled by your application’s servlets.

How it works

The Spring insight application uses load-time weaving to monitor your application. Out of the box, Spring insight monitors the SQLs and HTTP request/response messages. To monitor your own classes, you have to add an @Component annotation above your class or preferably a specification like @Controller, @Service or @Repository. For Spring insight, these annotations are just marker annotations that tells AspectJ which classes to weave.

These annotations can also be used to define your Spring beans with component scanning. But it’s not related to the way Spring insight uses them since Spring insight uses them at load-time, which is before the Spring container is started (runtime).

A class that will be monitored because of the @Service annotation:

@Service
public class AccountServiceImpl implements AccountService {

Some examples

The screenshot below shows a server that increases the load with ten clients every fifth second. In the beginning, the throughput increases with a low increase in response time. With more clients the throughput still improves, but the average response time increases much more.

The last image shows the same application with the number of clients doubled every fifth second. After a while it results in bad and unstable response time. The graph isn’t 100% correct since I run the clients on the same machine as the server. But the tests indicates quite clear that this application shouldn’t have unlimited number of server threads.

You can see the response time is very unstable and Spring insight claims the application has bad health. With less server threads the application health improves.

Summary

The tcServer developer edition is an excellent choice for monitoring web applications that can run on Tomcat. With an annotation over all the classes you’re interested in monitoring, you get access to detailed information like execution time, parameters, exceptions and return types. And you’re only a click away from inspecting the code you find something interesting.

The code used in this article was developed in my work time at Redpill Linpro.


Redpill Linpro is the leading provider of Professional Open Source services and products in the Nordic region.

Written by Espen

March 9, 2010 at 19:52