vigor
vigor

Reputation: 261

CDI 1.1 Dispose injected resource Immediate after using

I have a SimpleResource class

@Vetoed
public class SimpleResource {
  private String value="TestValue";
  public void open(){
     System.out.println("Open SR method");  
 }  
 public void close(){
   System.out.println("Close SR method");
 }
 public String getValue() {
   return value;
 }  
}

Then I've created a Producer Class

@Singleton
public class EntityManagerProducer {

 @Produces
 @Default
 @Dependent
 public static SimpleResource createSimpleResource() {
   SimpleResource sr = new SimpleResource();
   System.out.println("Open SR");
   sr.open();
   return sr;
 }

 public static void disposeSimpleResource(@Disposes @Default SimpleResource  simpleResource) {
  System.out.println("Close SR");
  simpleResource.close();
  }
}

And than a Singleton Business class

@Default
@Singleton
public class InjectConstructor {
 private  String value="init";

 @Inject
 public InjectConstructor(SimpleResource sr){
  value=sr.getValue();
 }

 public String getValue() {
   return value;
 }
}

The test method to run

 @Test
 public void injectConstructor(){
  Weld weld = new Weld();
  WeldContainer container = weld.initialize();
  InjectConstructor inst= container.select(InjectConstructor.class).get();   
  System.out.println("Value= "+inst.getValue());
 }

After runnning test program I've got such response:

INFO org.jboss.weld.Bootstrap - WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
Open SR
Open SR method
Value= TestValue
Close Container
Close SR
Close SR method

The problem is that "SimpleResource" is opend before constructor @Inject BUT not close after constructor exited.

The question is How to inject "SimpleResource" through Constructor injection and closed Immediate after constructor exited?

Is the only tecnique to do this is using @Observes method?

public void watchStartup(@Observes @Initialized(ApplicationScoped.class) Object ctxEvent, SimpleResource sr) {
 ...
}

Upvotes: 2

Views: 499

Answers (2)

vigor
vigor

Reputation: 261

Martin Couba helped me to solve this problem.

you could make use of @javax.enterprise.inject.TransientReference. The producer method for SimpleResource is @Dependent so the disposer method should be called when the invocation of the constructor completes.

@Inject
public InjectConstructor(@TransientReference SimpleResource sr) {
  value = sr.getValue();
}

Thank you very much. It is very ellegant solution

Upvotes: 1

John Ament
John Ament

Reputation: 11723

Because you're making SimpleResource dependent, its scope is tied to the lifecycle of the parent, as a result its managed like a singleton. To do what you're looking for, you'd have to make the constructor aware of the bean directly, and perhaps use Unmanaged to create then destroy an instance.

Upvotes: 0

Related Questions