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 }