In the JEE architecture entities are used to transfer the data between database and business logic. An object relational mapper like hibernate or toplink the handles the transport of the data form the database table to the entity. The ORM does this not only for the requested object, also all referenced objects could be handled automatically.
The most popular ORMs have very good and popular feature: lazy loading. Using this feature it is possible to fetch an entity by the ORM and referenced objects load their data transparent to the developer during the first access. This feature is great for having a good performance without the need of implementing a specially tailored fetch method for every different case of needed object trees. For example the order object is loaded with the ORM. The referenced customer object is only loaded, when accessing the customer attribute of the order. Same for the different addresses of the customer, the order positions and the data of the ordered items.
This works great using the order-object inside of the business logic in the business layer. But what happens when the order is returned by a service to the view layer? The view needs to access subobjects of the order which not have been needed by the getOrder method of the business layer. Because they have not been accessed they are not initialized yet. Because we have a clean architecture we have defined our transaction boundary above the service layer. When accessing now a not initialized subobject in the view layer the transaction is already closed and you get a LazyInitializationException.
There are three common solutions of the problem:
- Open-Session-In-View pattern
- Eager fetch pattern
- DTO pattern
You can find descriptions of the patterns around in the net e.g. here
The Open-Session-In-View pattern is from the architectural view point very ugly. Loading of data is done in the view layer. Additionally it is very easy to get mysterious effects. For example if an attribute of an displayed object has a value, which is not expected by the view layer and therefor replaced by a default value, it could happen, that during the view of the object an update on the database is triggered.
The Eager fetch pattern means when fetching the order all subobjects are also fetched. This is not possible by declaration in all cases and usually absolutely unnecessary and tends to bad performance.
The DTO pattern converts all entities to DTOs with the same name and attributes when leaving the service. Inside the business layer the entities and lazy loading is used. This works well, but is a lot of stupid code to implement and to maintain.
The ideal solution would be to have an automatic conversation from entities to DTOs when leaving the service. It would be nice to define for each service operation which object tree is guaranteed to be initialized. So lets do it!
First we define an Initialized annotation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #008080;"> 1</span> <span style="color: #0000FF;">package</span><span style="color: #000000;"> com.oc.common.annotations; </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 3</span> <span style="color: #000000;">@Target(ElementType.METHOD) </span><span style="color: #008080;"> 4</span> <span style="color: #000000;">@Retention(RetentionPolicy.RUNTIME) </span><span style="color: #008080;"> 5</span> <span style="color: #000000;"></span><span style="color: #0000FF;">public</span><span style="color: #000000;"> @</span><span style="color: #0000FF;">interface</span><span style="color: #000000;"> Initialized { </span><span style="color: #008080;"> 6</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 7</span> <span style="color: #000000;"> String[] initializedProperties(); </span><span style="color: #008080;"> 8</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 9</span> <span style="color: #000000;">} </span><span style="color: #008080;">10</span> <span style="color: #000000;"></span></div> |
This annotation is used for operations this way:
1 2 3 4 5 6 7 8 9 |
<div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #008080;">1</span> <span style="color: #000000;"> @Initialized(initializedProperties </span><span style="color: #000000;">=</span><span style="color: #000000;"> { </span><span style="color: #000000;">"</span><span style="color: #000000;">addresses</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">addresses.persons</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">addresses.persons.connections</span><span style="color: #000000;">"</span><span style="color: #000000;"> }) </span><span style="color: #008080;">2</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> Partner findByIdInitialized(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> </span><span style="color: #0000FF;">long</span><span style="color: #000000;"> id) { </span><span style="color: #008080;">3</span> <span style="color: #000000;"> ... </span><span style="color: #008080;">4</span> <span style="color: #000000;"></span></div> |
Now we can define on each operation which parts of the object tree is guaranteed to be initialized. The view layer using this operation can rely on the initialization. If the view needs in an other case an other combination of initialized objects we can create a second operation with a different annotation.
In the next step we implement a piece of code, which handles the Initialized annotation and loads the needed objects. Here is an example of an implementation as spring AfterReturningAdvice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
<div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #008080;"> 1</span> <span style="color: #0000FF;">package</span><span style="color: #000000;"> com.oc.common.interceptor; </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 3</span> <span style="color: #000000;"></span><span style="color: #0000FF;">import</span><span style="color: #000000;"> java.lang.reflect.InvocationTargetException; </span><span style="color: #008080;"> 4</span> <span style="color: #000000;"></span><span style="color: #0000FF;">import</span><span style="color: #000000;"> java.lang.reflect.Method; </span><span style="color: #008080;"> 5</span> <span style="color: #000000;"></span><span style="color: #0000FF;">import</span><span style="color: #000000;"> org.springframework.aop.AfterReturningAdvice; </span><span style="color: #008080;"> 6</span> <span style="color: #000000;"></span><span style="color: #0000FF;">import</span><span style="color: #000000;"> com.oc.common.annotations.Initialized; </span><span style="color: #008080;"> 7</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 8</span> <span style="color: #000000;"></span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">class</span><span style="color: #000000;"> LazyInitialitationVerifyer </span><span style="color: #0000FF;">implements</span><span style="color: #000000;"> AfterReturningAdvice { </span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 10</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> initialize(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object object) { </span><span style="color: #008080;"> 11</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (object </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Object[]) { </span><span style="color: #008080;"> 12</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object[] objects </span><span style="color: #000000;">=</span><span style="color: #000000;"> (Object[]) object; </span><span style="color: #008080;"> 13</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;"><</span><span style="color: #000000;"> objects.length; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 14</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initialize(objects[i]); </span><span style="color: #008080;"> 15</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 16</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (object </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Iterable) { </span><span style="color: #008080;"> 17</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object subObject : (Iterable) object) { </span><span style="color: #008080;"> 18</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initialize(subObject); </span><span style="color: #008080;"> 19</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 20</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 21</span> <span style="color: #000000;"> object.toString(); </span><span style="color: #008080;"> 22</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 23</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 24</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 25</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> String[] calcGetMethodNames(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String property) { </span><span style="color: #008080;"> 26</span> <span style="color: #000000;"> String[] result </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">; </span><span style="color: #008080;"> 27</span> <span style="color: #000000;"> result </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> String[</span><span style="color: #000000;">1</span><span style="color: #000000;">]; </span><span style="color: #008080;"> 28</span> <span style="color: #000000;"> result[</span><span style="color: #000000;">0</span><span style="color: #000000;">] </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">"</span><span style="color: #000000;">get</span><span style="color: #000000;">"</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> (</span><span style="color: #000000;">""</span><span style="color: #000000;"> </span><span style="color: #000000;">+</span><span style="color: #000000;"> property.charAt(</span><span style="color: #000000;">0</span><span style="color: #000000;">)).toUpperCase() </span><span style="color: #000000;">+</span><span style="color: #000000;"> property.substring(</span><span style="color: #000000;">1</span><span style="color: #000000;">); </span><span style="color: #008080;"> 29</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">return</span><span style="color: #000000;"> result; </span><span style="color: #008080;"> 30</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 31</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 32</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">private</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> initializePath(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object object, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String[] initializationPath, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> </span><span style="color: #0000FF;">int</span><span style="color: #000000;"> startIndex) { </span><span style="color: #008080;"> 33</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String property </span><span style="color: #000000;">=</span><span style="color: #000000;"> initializationPath[startIndex]; </span><span style="color: #008080;"> 34</span> <span style="color: #000000;"> Object pathObject </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">; </span><span style="color: #008080;"> 35</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String[] methodNames </span><span style="color: #000000;">=</span><span style="color: #000000;"> LazyInitialitationVerifyer.calcGetMethodNames(property); </span><span style="color: #008080;"> 36</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">; (pathObject </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">) </span><span style="color: #000000;">&&</span><span style="color: #000000;"> (i </span><span style="color: #000000;"><</span><span style="color: #000000;"> methodNames.length); i</span><span style="color: #000000;">++</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 37</span> <span style="color: #000000;"> Method method </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">; </span><span style="color: #008080;"> 38</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">try</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 39</span> <span style="color: #000000;"> method </span><span style="color: #000000;">=</span><span style="color: #000000;"> object.getClass().getMethod(methodNames[</span><span style="color: #000000;">0</span><span style="color: #000000;">], </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Class[</span><span style="color: #000000;">0</span><span style="color: #000000;">]); </span><span style="color: #008080;"> 40</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> SecurityException e) { </span><span style="color: #008080;"> 41</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Access denied trying other method</span><span style="color: #008000;"> </span><span style="color: #008080;"> 42</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> NoSuchMethodException e) { </span><span style="color: #008080;"> 43</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Wrong name trying other method</span><span style="color: #008000;"> </span><span style="color: #008080;"> 44</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #008080;"> 45</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (method </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 46</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">try</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 47</span> <span style="color: #000000;"> pathObject </span><span style="color: #000000;">=</span><span style="color: #000000;"> method.invoke(object, </span><span style="color: #0000FF;">new</span><span style="color: #000000;"> Object[</span><span style="color: #000000;">0</span><span style="color: #000000;">]); </span><span style="color: #008080;"> 48</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> IllegalArgumentException e) { </span><span style="color: #008080;"> 49</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Wrong method name trying other method</span><span style="color: #008000;"> </span><span style="color: #008080;"> 50</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> IllegalAccessException e) { </span><span style="color: #008080;"> 51</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Access denied trying other method</span><span style="color: #008000;"> </span><span style="color: #008080;"> 52</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #0000FF;">catch</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> InvocationTargetException e) { </span><span style="color: #008080;"> 53</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Access denied trying other method</span><span style="color: #008000;"> </span><span style="color: #008080;"> 54</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #008080;"> 55</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 56</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 57</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 58</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (pathObject </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 59</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (startIndex </span><span style="color: #000000;"><</span><span style="color: #000000;"> initializationPath.length </span><span style="color: #000000;">-</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 60</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (pathObject </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Iterable) { </span><span style="color: #008080;"> 61</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object subObject : (Iterable) pathObject) { </span><span style="color: #008080;"> 62</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(subObject, initializationPath, startIndex </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">); </span><span style="color: #008080;"> 63</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 64</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (pathObject </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Object[]) { </span><span style="color: #008080;"> 65</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object[] subObjects </span><span style="color: #000000;">=</span><span style="color: #000000;"> (Object[]) pathObject; </span><span style="color: #008080;"> 66</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;"><</span><span style="color: #000000;"> subObjects.length; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 67</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(subObjects[i], initializationPath, startIndex </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">); </span><span style="color: #008080;"> 68</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 69</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 70</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(pathObject, initializationPath, startIndex </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #000000;">1</span><span style="color: #000000;">); </span><span style="color: #008080;"> 71</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 72</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 73</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initialize(pathObject); </span><span style="color: #008080;"> 74</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 75</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 76</span> <span style="color: #000000;"> </span><span style="color: #008000;">//</span><span style="color: #008000;"> TODO error</span><span style="color: #008000;"> </span><span style="color: #008080;"> 77</span> <span style="color: #008000;"></span><span style="color: #000000;"> } </span><span style="color: #008080;"> 78</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 79</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 80</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">static</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> initialize(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object object, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String[] initializedProperties) { </span><span style="color: #008080;"> 81</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String initializedProperty : initializedProperties) { </span><span style="color: #008080;"> 82</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> String[] path </span><span style="color: #000000;">=</span><span style="color: #000000;"> initializedProperty.split(</span><span style="color: #000000;">"</span><span style="color: #000000;">\\.</span><span style="color: #000000;">"</span><span style="color: #000000;">); </span><span style="color: #008080;"> 83</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (object </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Iterable) { </span><span style="color: #008080;"> 84</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object entry : (Iterable) object) { </span><span style="color: #008080;"> 85</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(entry, path, </span><span style="color: #000000;">0</span><span style="color: #000000;">); </span><span style="color: #008080;"> 86</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 87</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> (object </span><span style="color: #0000FF;">instanceof</span><span style="color: #000000;"> Object[]) { </span><span style="color: #008080;"> 88</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object[] entries </span><span style="color: #000000;">=</span><span style="color: #000000;"> (Object[]) object; </span><span style="color: #008080;"> 89</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">for</span><span style="color: #000000;"> (</span><span style="color: #0000FF;">int</span><span style="color: #000000;"> i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;"><</span><span style="color: #000000;"> entries.length; i</span><span style="color: #000000;">++</span><span style="color: #000000;">) { </span><span style="color: #008080;"> 90</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(entries[i], path, </span><span style="color: #000000;">0</span><span style="color: #000000;">); </span><span style="color: #008080;"> 91</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 92</span> <span style="color: #000000;"> } </span><span style="color: #0000FF;">else</span><span style="color: #000000;"> { </span><span style="color: #008080;"> 93</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initializePath(object, path, </span><span style="color: #000000;">0</span><span style="color: #000000;">); </span><span style="color: #008080;"> 94</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 95</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 96</span> <span style="color: #000000;"> } </span><span style="color: #008080;"> 97</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 98</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">public</span><span style="color: #000000;"> </span><span style="color: #0000FF;">void</span><span style="color: #000000;"> afterReturning(</span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object returnValue, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Method method, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object[] args, </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Object target) { </span><span style="color: #008080;"> 99</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">final</span><span style="color: #000000;"> Initialized in </span><span style="color: #000000;">=</span><span style="color: #000000;"> method.getAnnotation(Initialized.</span><span style="color: #0000FF;">class</span><span style="color: #000000;">); </span><span style="color: #008080;">100</span> <span style="color: #000000;"> </span><span style="color: #0000FF;">if</span><span style="color: #000000;"> ((in </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">) </span><span style="color: #000000;">&&</span><span style="color: #000000;"> (returnValue </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000FF;">null</span><span style="color: #000000;">)) { </span><span style="color: #008080;">101</span> <span style="color: #000000;"> LazyInitialitationVerifyer.initialize(returnValue, in.initializedProperties()); </span><span style="color: #008080;">102</span> <span style="color: #000000;"> } </span><span style="color: #008080;">103</span> <span style="color: #000000;"> } </span><span style="color: #008080;">104</span> <span style="color: #000000;"> </span><span style="color: #008080;">105</span> <span style="color: #000000;">} </span><span style="color: #008080;">106</span> <span style="color: #000000;"></span></div> |
Finally we have to attach the LazyInitialitationVerifyer to every (spring-)service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div><!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --><span style="color: #008080;"> 1</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">bean </span><span style="color: #FF0000;">id</span><span style="color: #0000FF;">="lazyInitialiationInterceptor"</span><span style="color: #FF0000;"> class</span><span style="color: #0000FF;">="com.oc.common.interceptor.LazyInitialitationVerifyer"</span><span style="color: #0000FF;">/></span><span style="color: #000000;"> </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> </span><span style="color: #008080;"> 3</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">bean </span><span style="color: #FF0000;">id</span><span style="color: #0000FF;">="abstractService"</span><span style="color: #FF0000;"> abstract</span><span style="color: #0000FF;">="true"</span><span style="color: #FF0000;"> class</span><span style="color: #0000FF;">="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span style="color: #0000FF;">></span><span style="color: #000000;"> </span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">property </span><span style="color: #FF0000;">name</span><span style="color: #0000FF;">="transactionManager"</span><span style="color: #FF0000;"> ref</span><span style="color: #0000FF;">="transactionManager"</span><span style="color: #0000FF;">/></span><span style="color: #000000;"> </span><span style="color: #008080;"> 5</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">property </span><span style="color: #FF0000;">name</span><span style="color: #0000FF;">="transactionAttributes"</span><span style="color: #FF0000;"> ref</span><span style="color: #0000FF;">="transactionAttributes"</span><span style="color: #0000FF;">/></span><span style="color: #000000;"> </span><span style="color: #008080;"> 6</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">property </span><span style="color: #FF0000;">name</span><span style="color: #0000FF;">="postInterceptors"</span><span style="color: #0000FF;">></span><span style="color: #000000;"> </span><span style="color: #008080;"> 7</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">list</span><span style="color: #0000FF;">></span><span style="color: #000000;"> </span><span style="color: #008080;"> 8</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"><</span><span style="color: #800000;">ref </span><span style="color: #FF0000;">bean</span><span style="color: #0000FF;">="lazyInitialiationInterceptor"</span><span style="color: #0000FF;">/></span><span style="color: #000000;"> </span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"></</span><span style="color: #800000;">list</span><span style="color: #0000FF;">></span><span style="color: #000000;"> </span><span style="color: #008080;">10</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"></</span><span style="color: #800000;">property</span><span style="color: #0000FF;">></span><span style="color: #000000;"> </span><span style="color: #008080;">11</span> <span style="color: #000000;"> </span><span style="color: #0000FF;"></</span><span style="color: #800000;">bean</span><span style="color: #0000FF;">></span></div> |
Bernhard Mähr @ OPITZ-CONSULTING published at http://thecattlecrew.wordpress.com/