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.

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

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.

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:

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;