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 = 49 PersistenceContextConversationInterceptor.class.getName() + ".PERSISTENCE_CONTEXT"; 50 public final static String REQUEST_ATTRIBUTE = 51 PersistenceContextConversationInterceptor.class.getName() + ".USED_PERSISTENCE_CONTEXTS"; 52 53 private PersistenceContextFactory persistenceContextFactory; 54 55 public PersistenceContextConversationInterceptor() 56 { 57 } 58 59 public void setPersistenceContextFactory(PersistenceContextFactory persistenceContextFactory) 60 { 61 this.persistenceContextFactory = persistenceContextFactory; 62 } 63 64 public Object invoke(MethodInvocation methodInvocation) throws Throwable 65 { 66 PersistenceContext persistenceContext = null; 67 68 Conversation conversation = Conversation.getCurrentInstance(); 69 if (conversation != null) 70 { 71 PersistenceContextCloser persistenceContextCloser = (PersistenceContextCloser) 72 conversation.getAttribute(PERSISTENCE_CONTEXT_CONV_ATTRIBUTE); 73 if (persistenceContextCloser != null) 74 { 75 persistenceContext = persistenceContextCloser.getPersistenceContext(); 76 } 77 78 if (persistenceContext == null) 79 { 80 persistenceContext = persistenceContextFactory.create(); 81 82 conversation.setAttribute( 83 PERSISTENCE_CONTEXT_CONV_ATTRIBUTE, 84 new PersistenceContextCloser(persistenceContext)); 85 } 86 } 87 88 if (persistenceContext != null) 89 { 90 // registerPersistenceContextUsage(persistenceContext); 91 92 persistenceContext.bind(); 93 } 94 95 try 96 { 97 return methodInvocation.proceed(); 98 } 99 finally 100 { 101 if (persistenceContext != null) 102 { 103 persistenceContext.unbind(); 104 } 105 } 106 } 107 108 /* 109 protected void registerPersistenceContextUsage(PersistenceContext persistenceContext) 110 { 111 FrameworkAdapterInterface fai = FrameworkAdapter.getInstance(); 112 Set persistencesContexts = (Set) fai.getRequestAttribute(REQUEST_ATTRIBUTE); 113 if (persistencesContexts == null) 114 { 115 persistencesContexts = new HashSet(); 116 fai.setRequestAttribute(REQUEST_ATTRIBUTE, persistencesContexts); 117 } 118 if (!persistencesContexts.contains(persistenceContext)) 119 { 120 persistencesContexts.add(persistenceContext); 121 } 122 } 123 124 public static void cleanupPersistence() 125 { 126 FrameworkAdapterInterface fai = FrameworkAdapter.getInstance(); 127 Set persistencesContexts = (Set) fai.getRequestAttribute(REQUEST_ATTRIBUTE); 128 if (persistencesContexts == null) 129 { 130 return; 131 } 132 133 Iterator iterPersistencesContexts = persistencesContexts.iterator(); 134 while (iterPersistencesContexts.hasNext()) 135 { 136 PersistenceContext persistenceContext = (PersistenceContext) iterPersistencesContexts.next(); 137 persistenceContext.unbind(); 138 } 139 } 140 */ 141 }