View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.util;
21  
22  import org.grouplens.grapht.InjectionException;
23  import org.grouplens.grapht.Injector;
24  import org.grouplens.grapht.InjectorBuilder;
25  import org.junit.Ignore;
26  import org.junit.Test;
27  
28  import javax.annotation.PostConstruct;
29  import javax.annotation.PreDestroy;
30  import javax.inject.Inject;
31  
32  import static org.hamcrest.Matchers.*;
33  import static org.junit.Assert.*;
34  
35  /*
36   * Grapht, an open source dependency injector.
37   * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
38   * Copyright 2010-2014 Regents of the University of Minnesota
39   *
40   * This program is free software; you can redistribute it and/or modify
41   * it under the terms of the GNU Lesser General Public License as
42   * published by the Free Software Foundation; either version 2.1 of the
43   * License, or (at your option) any later version.
44   *
45   * This program is distributed in the hope that it will be useful, but WITHOUT
46   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
47   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
48   * details.
49   *
50   * You should have received a copy of the GNU General Public License along with
51   * this program; if not, write to the Free Software Foundation, Inc., 51
52   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
53   */
54  public class ComponentLifecycleTest {
55  
56      @Test
57      public void testClosesAutoCloseable() throws Exception {
58          InjectorBuilder bld = InjectorBuilder.create();
59          Flag closed
60                  = new Flag();
61          bld.bind(Flag.class).to(closed);
62          Injector injector = bld.build();
63          try {
64              CloseableComponent comp = injector.getInstance(CloseableComponent.class);
65              assertThat(comp, notNullValue());
66          } finally {
67              injector.close();
68          }
69          // Check that close was called.
70          assertTrue("close was called", closed.isSet());
71      }
72  
73      /**
74       * If we inject an instance of an AutoCloseable, it should not be closed.
75       */
76      @Test
77      public void testDoesNotCloseAutoCloseableInstance() throws Exception {
78          InjectorBuilder bld = InjectorBuilder.create();
79          Flag closed = new Flag();
80          bld.bind(Flag.class).to(closed);
81          bld.bind(CloseableComponent.class).to(new CloseableComponent(closed));
82          Injector injector = bld.build();
83          try {
84              CloseableComponent comp = injector.getInstance(CloseableComponent.class);
85              assertThat(comp, notNullValue());
86          } finally {
87              injector.close();
88          }
89          // Check that close was not called.
90          assertFalse("close was called", closed.isSet());
91      }
92  
93      /**
94       * Test that the lifecycle management calls pre-destroy methods.
95       */
96      @Test
97      public void testCallsPreDestroy() throws Exception {
98          InjectorBuilder bld = InjectorBuilder.create();
99          Flag closed = new Flag();
100         bld.bind(Flag.class).to(closed);
101         Injector injector = bld.build();
102         try {
103             LifecycleShutdownComponent comp = injector.getInstance(LifecycleShutdownComponent.class);
104             assertThat(comp, notNullValue());
105         } finally {
106             injector.close();
107         }
108         // Check that close was called.
109         assertTrue("close was called", closed.isSet());
110     }
111 
112     /**
113      * Test that the lifecycle management does not call pre-destroy methods on an instance.
114      */
115     @Test
116     public void testDoesNotCallPreDestroyOnInstance() throws Exception {
117         InjectorBuilder bld = InjectorBuilder.create();
118         Flag closed = new Flag();
119         bld.bind(LifecycleShutdownComponent.class).to(new LifecycleShutdownComponent(closed));
120         Injector injector = bld.build();
121         try {
122             LifecycleShutdownComponent comp = injector.getInstance(LifecycleShutdownComponent.class);
123             assertThat(comp, notNullValue());
124         } finally {
125             injector.close();
126         }
127         // Check that close was called.
128         assertFalse("close was called", closed.isSet());
129     }
130 
131     /**
132      * Test that the lifecycle management calls post-construct methods
133      */
134     @Test
135     public void testCallsPostConstruct() throws Exception {
136         InjectorBuilder bld = InjectorBuilder.create();
137         Flag setup = new Flag();
138         bld.bind(Flag.class).to(setup);
139         Injector injector = bld.build();
140         try {
141             PostConstructComponent comp = injector.getInstance(PostConstructComponent.class);
142             assertThat(comp, notNullValue());
143             assertTrue("setup was called", setup.isSet());
144         } finally {
145             injector.close();
146         }
147         // Check that close was called.
148         assertTrue("close was called", setup.isSet());
149     }
150 
151     /**
152      * Flag component for detecting closure.
153      */
154     public static class Flag {
155         private boolean value = false;
156 
157         public void set() {
158             value = true;
159         }
160 
161         public boolean isSet() {
162             return value;
163         }
164     }
165 
166     /**
167      * Component implementing AutoCloseable that should be closed.
168      */
169     public static class CloseableComponent implements AutoCloseable {
170         private final Flag flag;
171 
172         @Inject
173         public CloseableComponent(Flag f) {
174             flag = f;
175         }
176 
177         @Override
178         public void close() throws Exception {
179             flag.set();
180         }
181     }
182 
183     /**
184      * Component with PreDestroy method that must be called.
185      */
186     public static class LifecycleShutdownComponent {
187         private final Flag flag;
188 
189         @Inject
190         public LifecycleShutdownComponent(Flag f) {
191             flag = f;
192         }
193 
194         @PreDestroy
195         public void shutdown() {
196             flag.set();
197         }
198     }
199 
200     /**
201      * component with post-construct methods
202      */
203     public static class PostConstructComponent {
204         private Flag setup;
205 
206         // we use setter injection to make sure PostConstruct is called after setters
207         @Inject
208         public void setFlag(Flag f) {
209             setup = f;
210         }
211 
212         @PostConstruct
213         public void setup() {
214             assertThat(setup, notNullValue());
215             setup.set();
216         }
217     }
218 }