Java and dynamic Proxies

Dynamic proxies in Java is a simple and very useful feature.

Usually we create an interface implementation and then compilation is involved. With dynamic proxies we can implement a list of interfaces at runtime. A proxy object will be created, when a method is invoked on that proxy instance, the methods invoked will be forwarded to an invocation handler specified.

This can have various usages. A common use case would be for a java interface which we can use a proxy and intercept the calls to the methods invoked.

Supposing we have a JDBC connection pool and we want to have something like a micrometer counter. On getting a connection the counter will increase, thus we can identify the rate of acquiring connections in our application.

We shall use a proxy for that.

Let’s first add a docker container for Postgresql using Docker Compose.

version: '3.1'

services:
  postgres:
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432

We can run with the following command

docker compose up

You can find more on Compose on the Developers Essential Guide to Docker Compose.

Let’s add our dependencies to our Java project

    <dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>4.0.3</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

Now will also add a small snippet.

package com.example.gkatzioura.proxy;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class Application {

    public static void main(String[] args) throws SQLException {
        Properties props = new Properties();

        props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
        props.setProperty("dataSource.user", "postgres");
        props.setProperty("dataSource.password", "postgres");
        props.setProperty("dataSource.databaseName", "postgres");
        props.put("dataSource.logWriter", new PrintWriter(System.out));

        HikariConfig config = new HikariConfig(props);
        
        try(HikariDataSource ds = new HikariDataSource(config)) {
            try(Connection connection = ds.getConnection()) {
                System.out.println("Should be printed after the proxy");       
            }
        }
    }

}

We can examine the DataSource interface of Java on the source code. We can see the method of interest, getConnection, present.

public interface DataSource  extends CommonDataSource, Wrapper {

    Connection getConnection() throws SQLException;
    ...
}

Instead of creating an interface implementation and having to implement all those methods and then delegate them to the actual DataSource instance, we shall instead use a proxy and add actions only to the method of interest, in our case getConnection.

We shall implement an InvocationHandler.

package com.example.gkatzioura.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.sql.DataSource;

public class GetConnectionHandler implements InvocationHandler {

    private final DataSource dataSource;

    public GetConnectionHandler(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("getConnection")) {
            System.out.println("Called before actual method");

        }

        return method.invoke(dataSource, args);
    }

    public static DataSource proxy(DataSource dataSource) {
        return (DataSource) Proxy.newProxyInstance(DataSource.class.getClassLoader(), new Class[]{DataSource.class}, new GetConnectionHandler(dataSource));
    }

}

Let’s break it down.

The invocation handler will be called for the method of an interface specified. When an interface method is invoked it is our choice how we shall handle it. In our case we shall print a simple message and then we shall execute the corresponding method to our target instance.

Also we have a static factory specified which shall proxy the object implementing the interface of interest. A new proxy instance will be created, it will implement the interfaces provided and the calls towards the proxy instance will be passed to the handler we provided.

Let’s revisit our main method.

package com.example.gkatzioura.proxy;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import static com.example.gkatzioura.proxy.GetConnectionHandler.proxy;

public class Application {

    public static void main(String[] args) throws SQLException {
        Properties props = new Properties();

        props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
        props.setProperty("dataSource.user", "postgres");
        props.setProperty("dataSource.password", "postgres");
        props.setProperty("dataSource.databaseName", "postgres");
        props.put("dataSource.logWriter", new PrintWriter(System.out));

        HikariConfig config = new HikariConfig(props);

        try(HikariDataSource ds = new HikariDataSource(config)) {
            DataSource dataSource = proxy(ds);
            try(Connection connection = dataSource.getConnection()) {
                System.out.println("Should be printed after the proxy");
            }
        }
    }

}

We wrapped the HikariDataSource with a Dynamic Proxy and if we run the program we should see the following output.

Called before actual method
Should be printed after the proxy

If we break it down, we created a proxy with the DataSource interface. By creating the proxy we provided an invocation handler which shall print a message before the getConnection method is invoked. The getConnection will be invoked by the actual implementation of the DataSource interface that we specified on the InvocationHandler.

You can find the source code on GitHub.

Aspect Oriented Programming: Spring

One of the most powerfull tools spring provides us with is aspect orientation.
Aspect oriented programming helps us to continue development for special use cases, without breaking our modularity.

This is part of a series of blog posts on aspect orientation using different tools.
The first one is about aspect orientation on Spring.

In this example I will display the behaviour of two beans from the same definition but each one has a different aspect.

The employe class will be used to create the beans for this project.

package com.gkatzioura.spring.employees;

public class Employee {

    public void enterWorkArea() {

    }

    public void leaveWorkArea() {

    }

}

However considering a company, probably there are more than one types of employes.
For our project we will use the aspect of the supervisor employee and the aspect of the worker employee.

The worker employee before entering the work area should inform the supervisor employee that he has arrived.
The supervisor employee before entering the area should check that everything is ok.

package com.gkatzioura.spring.employees;

import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class WorkerBeforeAdvice implements MethodBeforeAdvice {

    private static final Logger LOGGER = Logger.getLogger(WorkerBeforeAdvice.class);

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {

        if (method.getName().equals("enterWorkArea")) {
            System.out.println("Informing the supervisor that I have arrived");
        }

    }

}
package com.gkatzioura.spring.employees;

import org.apache.log4j.Logger;
import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class SupervisorBeforeAdvice implements MethodBeforeAdvice {

    private static final Logger LOGGER = Logger.getLogger(SupervisorBeforeAdvice.class);

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        
        if(method.getName().equals("enterWorkArea")) {
            System.out.println("Check if everything is ok");
        }
    }
}

The advices defined above would have to be wired on our employee bean according to the aspect needs.
For the worker bean we will use the WorkerBeforeAdvice before entering the factory.
For the employee bean we wil use the SupervisorBeforeAdvice before leaving the factory

On your META-INF create a spring directory and inside the spring directory create the employeeapects.xml file. This file would wire the employee bean with the behaviours described above.
The first ProxyFactory Bean will be used to create employee beans wired with the WorkerBeforeAdvice behaviour.
The second ProxyFactory Bean will be used to create employee beans wired with the SupervisorBeforeAdvice behaviour.

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

    <bean id="employee" class="com.gkatzioura.spring.employees.Employee"/>

    <bean id="workerBeforeBean" class="com.gkatzioura.spring.employees.WorkerBeforeAdvice"/>
    <bean id="supervisorBeforeBean" class="com.gkatzioura.spring.employees.SupervisorBeforeAdvice"/>

    <bean id="workerProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="employee"/>
        <property name="interceptorNames">
            <list>
                <value>workerBeforeBean</value>
            </list>
        </property>
    </bean>

    <bean id="superVisorProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="employee"/>
        <property name="interceptorNames">
            <list>
                <value>supervisorBeforeBean</value>
            </list>
        </property>
    </bean>

</beans>

On your dispatcher-servlet.xml you need to import employeeapects.xml

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

    <context:component-scan base-package="com.gkatzioura.spring"/>

    <import resource="classpath:/META-INF/spring/employeeapects.xml"/>
    <mvc:annotation-driven/>
</beans>

We will create a controller in order to create the beans.

package com.gkatzioura.spring.controllers;

import com.gkatzioura.spring.employees.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class AspectController {

    @Autowired
    @Qualifier("workerProxy")
    Employee workEmployee;

    @Autowired
    @Qualifier("superVisorProxy")
    Employee superVisorEmployee;

    @RequestMapping(value = "/")
    @ResponseBody
    public String index() {

        return "Check other endpoints";
    }

    @RequestMapping(value = "/worker/enter")
    @ResponseBody
    public String workerEnter() {
        workEmployee.enterWorkArea();
        return "Worker entered the factory";
    }

    @RequestMapping(value = "/supervisor/enter")
    @ResponseBody
    public String superVisortEnter() {
        superVisorEmployee.enterWorkArea();
        return "Supervisor entered the factory";
    }

}

You should hit the endpoint /worker/enter and /supervisor/enter.
You will notice that the workerEmployee and superVisorEmployee have a different reaction once calling the enterWorkArea function.

By hitting the /worker/enter endpoint, the string “Informing the supervisor that I have arrived” is printed on the console.
By hitting the /supervisor/enter endpoint, the string “Check if everything is ok” is printed on the console.