View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.orchestra.conversation.spring;
21  
22  import org.aopalliance.intercept.MethodInterceptor;
23  import org.aopalliance.intercept.MethodInvocation;
24  import org.apache.myfaces.orchestra.conversation.Conversation;
25  
26  /**
27   * Maintain the appropriate persistence state for the current call-stack.
28   * <p>
29   * This class is a MethodInterceptor (an AOP Advice) which should be configured to intercept
30   * calls to all conversation-scoped beans. It ensures that the appropriate PersistenceContext
31   * object for this conversation is placed into the default location, by invoking the
32   * <i>bind</i> method on the persistence context object. Typically the bind method stores
33   * the persistence context into a thread-local variable, but that is implementation-specific.
34   * <p>
35   * When Spring code retrieves the persistence context in order to inject it into a bean,
36   * it then finds the correct context for the conversation that is associated with the
37   * nearest conversation-scoped bean in the callstack.    
38   * <p>
39   * If no PersistenceContext yet exists for the conversation associated with the bean
40   * that is being invoked then one is created using {@link PersistenceContextFactory}.
41   * <p>
42   * A reference to the {@link PersistenceContext} is put into the conversation attribute
43   * map wrapped in an {@link PersistenceContextCloser} so that when the conversation
44   * ends a callback occurs on it which closes the underlying object.
45   */
46  public class PersistenceContextConversationInterceptor implements MethodInterceptor
47  {
48      private final static String PERSISTENCE_CONTEXT_CONV_ATTRIBUTE = PersistenceContextConversationInterceptor.class.getName() + ".PERSISTENCE_CONTEXT";
49      public final static String REQUEST_ATTRIBUTE = PersistenceContextConversationInterceptor.class.getName() + ".USED_PERSISTENCE_CONTEXTS";
50  
51      private PersistenceContextFactory persistenceContextFactory;
52  
53      public PersistenceContextConversationInterceptor()
54      {
55      }
56  
57      public void setPersistenceContextFactory(PersistenceContextFactory persistenceContextFactory)
58      {
59          this.persistenceContextFactory = persistenceContextFactory;
60      }
61  
62      public Object invoke(MethodInvocation methodInvocation) throws Throwable
63      {
64          PersistenceContext persistenceContext = null;
65  
66          Conversation conversation = Conversation.getCurrentInstance();
67          if (conversation != null)
68          {
69              PersistenceContextCloser persistenceContextCloser = (PersistenceContextCloser) conversation.getAttribute(PERSISTENCE_CONTEXT_CONV_ATTRIBUTE);
70              if (persistenceContextCloser != null)
71              {
72                  persistenceContext = persistenceContextCloser.getPersistenceContext();
73              }
74  
75              if (persistenceContext == null)
76              {
77                  persistenceContext = persistenceContextFactory.create();
78  
79                  conversation.setAttribute(PERSISTENCE_CONTEXT_CONV_ATTRIBUTE, new PersistenceContextCloser(persistenceContext));
80              }
81          }
82  
83          if (persistenceContext != null)
84          {
85              // registerPersistenceContextUsage(persistenceContext);
86  
87              persistenceContext.bind();
88          }
89  
90          try
91          {
92              return methodInvocation.proceed();
93          }
94          finally
95          {
96              if (persistenceContext != null)
97              {
98                  persistenceContext.unbind();
99              }
100         }
101     }
102 
103     /*
104     protected void registerPersistenceContextUsage(PersistenceContext persistenceContext)
105     {
106         FrameworkAdapterInterface fai = FrameworkAdapter.getInstance();
107         Set persistencesContexts = (Set) fai.getRequestAttribute(REQUEST_ATTRIBUTE);
108         if (persistencesContexts == null)
109         {
110             persistencesContexts = new HashSet();
111             fai.setRequestAttribute(REQUEST_ATTRIBUTE, persistencesContexts);
112         }
113         if (!persistencesContexts.contains(persistenceContext))
114         {
115             persistencesContexts.add(persistenceContext);
116         }
117     }
118 
119     public static void cleanupPersistence()
120     {
121         FrameworkAdapterInterface fai = FrameworkAdapter.getInstance();
122         Set persistencesContexts = (Set) fai.getRequestAttribute(REQUEST_ATTRIBUTE);
123         if (persistencesContexts == null)
124         {
125             return;
126         }
127 
128         Iterator iterPersistencesContexts = persistencesContexts.iterator();
129         while (iterPersistencesContexts.hasNext())
130         {
131             PersistenceContext persistenceContext = (PersistenceContext) iterPersistencesContexts.next();
132             persistenceContext.unbind();
133         }
134     }
135     */
136 }