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 }