Java EE CDI Disposer methods example

04 May 2013
By Gonçalo Marques
In this tutorial you will learn how to use CDI Disposer methods in order to perform clean up of resources created by CDI Producer methods.

Introduction

CDI Producer methods may be used to create resources that are consumed by an application in a very specific context. These resources may need to be cleaned up by the container when the application doesn't need them any more. This clean up process is provided by CDI in the form of Disposer methods as we will see in this tutorial.

Note: This tutorial assumes that you already know about CDI Producer methods. If that is not the case you should first read the following tutorial: Java EE CDI Producer methods tutorial.

This tutorial considers the following environment:

  1. Ubuntu 12.04
  2. JDK 1.7.0.21
  3. Weld 1.1.10
  4. Tomcat 7.0.35

Weld is the CDI reference implementation

A simple resource

In this tutorial we will be producing and disposing a simple resource that is represented by a Connection. Following next is the Connection interface and implementation that should be very straightforward:

Connection interface

package com.byteslounge.connection;

public interface Connection {

  void connect();
  
  void closeConnection();

}



Connection implementation

package com.byteslounge.connection;

public class ConnectionImpl implements Connection {

  @Override
  public void connect() {
    System.out.println("Connecting...");
  }

  @Override
  public void closeConnection() {
    System.out.println("Closing connection...");
  }

}

The Producer and the Disposer

Now we define a class that will contain both the Connection producer and the disposer:

ConnectionFactory.java

package com.byteslounge.connection;

import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Disposes;

public class ConnectionFactory {

  @Produces
  @RequestScoped
  @TestConnection
  public Connection getConnection(){
    Connection conn = new ConnectionImpl();
    conn.connect();
    return conn;
  }
  
  public void closeConnection(
    @Disposes
    @TestConnection Connection connection){
    
    connection.closeConnection();
  
  }
  
}

The method getConnection() is the producer method as we have seen in the previous tutorial so we will not describe it in detail here (see Java EE CDI Producer methods tutorial).

The new element here is the disposer method: closeConnection(). A disposer method must be matched against a producer method, ie. it must have a parameter annotated with @Disposes which type matches a producer method return type (in this case Connection type). This parameter must also have the same qualifiers as the producer method (only if any qualifier was used), in this case the @TestConnection qualifier that we will see next.

A disposer method may also have additional parameters which the container will try to inject.

Our producer method is annotated with @RequestScoped. This means that for a single HTTP request that injects a Connection instance, the producer method will be called once and the Connection reference will be maintained by the container during the life time of that HTTP request, and consequently will be always used in further Connection injection points.

When the HTTP request finishes the container will call the disposer method in order to perform the resource clean up.

Why do we need the @TestConnection qualifier? If we did not used the qualifier the container would not know how to inject a Connection because it had to available options: one is to inject a Connection instance by the means of the producer method while the other is to instantiate a ConnectionImpl instance and to inject it directly into the injection point. What we did was to use a qualifier so we can disambiguate between both the of these scenarios.

The qualifier follows next:

TestConnection.java

package com.byteslounge.connection;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD, PARAMETER})
public @interface TestConnection {

}

Finally we inject the connection like the following:

Connection injection

@Inject
@TestConnection
private Connection connection;

Testing

In order to test the example we may use a simple servlet:

Testing servlet

package com.byteslounge.servlet;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.byteslounge.connection.Connection;
import com.byteslounge.connection.TestConnection;

@WebServlet(name = "testServlet", urlPatterns = {"/testServlet"})
public class TestConnectionServlet extends HttpServlet {

  private static final long serialVersionUID = -3995970242890631574L;
  
  @Inject
  @TestConnection
  private Connection connection;
  
  protected void doGet(HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
    
    System.out.println("Doing something with connection: " 
      + connection.toString());
    
  }
}

When we access this servlet the following output will be generated:

Connecting...
Doing something with connection: ...ConnectionImpl@3dcc0a0f
Closing connection...

The tutorial source code is available for download at the end of this page and it's configured to be run on Tomcat.

Download source code from this article

Related Articles

Comments

About the author
Gonçalo Marques is a Software Engineer with several years of experience in software development and architecture definition. During this period his main focus was delivering software solutions in banking, telecommunications and governmental areas. He created the Bytes Lounge website with one ultimate goal: share his knowledge with the software development community. His main area of expertise is Java and open source.

GitHub profile: https://github.com/gonmarques

He is also the author of the WiFi File Browser Android application: