Source Code Cross Referenced for PersistenceAnnotationBeanPostProcessor.java in  » J2EE » spring-framework-2.5 » org » springframework » orm » jpa » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.orm.jpa.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.orm.jpa.support;
018:
019:        import java.beans.PropertyDescriptor;
020:        import java.io.Serializable;
021:        import java.lang.reflect.AnnotatedElement;
022:        import java.lang.reflect.Field;
023:        import java.lang.reflect.Member;
024:        import java.lang.reflect.Method;
025:        import java.lang.reflect.Modifier;
026:        import java.util.Map;
027:        import java.util.Properties;
028:        import java.util.concurrent.ConcurrentHashMap;
029:
030:        import javax.naming.NamingException;
031:        import javax.persistence.EntityManager;
032:        import javax.persistence.EntityManagerFactory;
033:        import javax.persistence.PersistenceContext;
034:        import javax.persistence.PersistenceContextType;
035:        import javax.persistence.PersistenceProperty;
036:        import javax.persistence.PersistenceUnit;
037:
038:        import org.springframework.beans.BeanUtils;
039:        import org.springframework.beans.BeansException;
040:        import org.springframework.beans.PropertyValues;
041:        import org.springframework.beans.factory.BeanCreationException;
042:        import org.springframework.beans.factory.BeanFactory;
043:        import org.springframework.beans.factory.BeanFactoryAware;
044:        import org.springframework.beans.factory.BeanFactoryUtils;
045:        import org.springframework.beans.factory.ListableBeanFactory;
046:        import org.springframework.beans.factory.NoSuchBeanDefinitionException;
047:        import org.springframework.beans.factory.annotation.InjectionMetadata;
048:        import org.springframework.beans.factory.config.ConfigurableBeanFactory;
049:        import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
050:        import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
051:        import org.springframework.core.Ordered;
052:        import org.springframework.core.PriorityOrdered;
053:        import org.springframework.jndi.JndiLocatorSupport;
054:        import org.springframework.orm.jpa.EntityManagerFactoryInfo;
055:        import org.springframework.orm.jpa.EntityManagerFactoryUtils;
056:        import org.springframework.orm.jpa.EntityManagerProxy;
057:        import org.springframework.orm.jpa.ExtendedEntityManagerCreator;
058:        import org.springframework.orm.jpa.SharedEntityManagerCreator;
059:        import org.springframework.util.ObjectUtils;
060:        import org.springframework.util.ReflectionUtils;
061:
062:        /**
063:         * BeanPostProcessor that processes {@link javax.persistence.PersistenceUnit}
064:         * and {@link javax.persistence.PersistenceContext} annotations, for injection of
065:         * the corresponding JPA resources {@link javax.persistence.EntityManagerFactory}
066:         * and {@link javax.persistence.EntityManager}. Any such annotated fields or methods
067:         * in any Spring-managed object will automatically be injected.
068:         *
069:         * <p>This post-processor will inject sub-interfaces of <code>EntityManagerFactory</code>
070:         * and <code>EntityManager</code> if the annotated fields or methods are declared as such.
071:         * The actual type will be verified early, with the exception of a shared ("transactional")
072:         * <code>EntityManager</code> reference, where type mismatches might be detected as late
073:         * as on the first actual invocation.
074:         *
075:         * <p>Note: In the present implementation, PersistenceAnnotationBeanPostProcessor
076:         * only supports <code>@PersistenceUnit</code> and <code>@PersistenceContext</code>
077:         * with the "unitName" attribute, or no attribute at all (for the default unit).
078:         * If those annotations are present with the "name" attribute at the class level,
079:         * they will simply be ignored, since those only serve as deployment hint
080:         * (as per the Java EE 5 specification).
081:         *
082:         * <p>This post-processor can either obtain EntityManagerFactory beans defined
083:         * in the Spring application context (the default), or obtain EntityManagerFactory
084:         * references from JNDI ("persistence unit references"). In the bean case,
085:         * the persistence unit name will be matched against the actual deployed unit,
086:         * with the bean name used as fallback unit name if no deployed name found.
087:         * Typically, Spring's {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}
088:         * will be used for setting up such EntityManagerFactory beans. Alternatively,
089:         * such beans may also be obtained from JNDI, e.g. using the <code>jee:jndi-lookup</code>
090:         * XML configuration element (with the bean name matching the requested unit name).
091:         * In both cases, the post-processor definition will look as simple as this:
092:         *
093:         * <pre class="code">
094:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/&gt;</pre>
095:         *
096:         * In the JNDI case, specify the corresponding JNDI names in this post-processor's
097:         * {@link #setPersistenceUnits "persistenceUnits" map}, typically with matching
098:         * <code>persistence-unit-ref</code> entries in the Java EE deployment descriptor.
099:         * By default, those names are considered as resource references (according to the
100:         * Java EE resource-ref convention), located underneath the "java:comp/env/" namespace.
101:         * For example:
102:         *
103:         * <pre class="code">
104:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"&gt;
105:         *   &lt;property name="persistenceUnits"&gt;
106:         *     &lt;map/gt;
107:         *       &lt;entry key="unit1" value="persistence/unit1"/&gt;
108:         *       &lt;entry key="unit2" value="persistence/unit2"/&gt;
109:         *     &lt;/map/gt;
110:         *   &lt;/property&gt;
111:         * &lt;/bean&gt;</pre>
112:         *
113:         * In this case, the specified persistence units will always be resolved in JNDI
114:         * rather than as Spring-defined beans. The entire persistence unit deployment,
115:         * including the weaving of persistent classes, is then up to the Java EE server.
116:         * Persistence contexts (i.e. EntityManager references) will be built based on
117:         * those server-provided EntityManagerFactory references, using Spring's own
118:         * transaction synchronization facilities for transactional EntityManager handling
119:         * (typically with Spring's <code>@Transactional</code> annotation for demarcation
120:         * and {@link org.springframework.transaction.jta.JtaTransactionManager} as backend).
121:         *
122:         * <p>If you prefer the Java EE server's own EntityManager handling, specify entries
123:         * in this post-processor's {@link #setPersistenceContexts "persistenceContexts" map}
124:         * (or {@link #setExtendedPersistenceContexts "extendedPersistenceContexts" map},
125:         * typically with matching <code>persistence-context-ref</code> entries in the
126:         * Java EE deployment descriptor. For example:
127:         *
128:         * <pre class="code">
129:         * &lt;bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"&gt;
130:         *   &lt;property name="persistenceContexts"&gt;
131:         *     &lt;map/gt;
132:         *       &lt;entry key="unit1" value="persistence/context1"/&gt;
133:         *       &lt;entry key="unit2" value="persistence/context2"/&gt;
134:         *     &lt;/map/gt;
135:         *   &lt;/property&gt;
136:         * &lt;/bean&gt;</pre>
137:         *
138:         * If the application only obtains EntityManager references in the first place,
139:         * this is all you need to specify. If you need EntityManagerFactory references
140:         * as well, specify entries for both "persistenceUnits" and "persistenceContexts",
141:         * pointing to matching JNDI locations.
142:         *
143:         * <p><b>NOTE: In general, do not inject EXTENDED EntityManagers into STATELESS beans,
144:         * i.e. do not use <code>@PersistenceContext</code> with type <code>EXTENDED</code> in
145:         * Spring beans defined with scope 'singleton' (Spring's default scope).</b>
146:         * Extended EntityManagers are <i>not</i> thread-safe, hence they must not be used
147:         * in concurrently accessed beans (which Spring-managed singletons usually are).
148:         *
149:         * <p>Note: A default PersistenceAnnotationBeanPostProcessor will be registered
150:         * by the "context:annotation-config" and "context:component-scan" XML tags.
151:         * Remove or turn off the default annotation configuration there if you intend
152:         * to specify a custom PersistenceAnnotationBeanPostProcessor bean definition.
153:         *
154:         * @author Rod Johnson
155:         * @author Juergen Hoeller
156:         * @since 2.0
157:         * @see javax.persistence.PersistenceUnit
158:         * @see javax.persistence.PersistenceContext
159:         */
160:        public class PersistenceAnnotationBeanPostProcessor extends
161:                JndiLocatorSupport implements 
162:                InstantiationAwareBeanPostProcessor,
163:                DestructionAwareBeanPostProcessor, PriorityOrdered,
164:                BeanFactoryAware, Serializable {
165:
166:            private transient Map<String, String> persistenceUnits;
167:
168:            private transient Map<String, String> persistenceContexts;
169:
170:            private transient Map<String, String> extendedPersistenceContexts;
171:
172:            private transient String defaultPersistenceUnitName = "";
173:
174:            private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
175:
176:            private transient ListableBeanFactory beanFactory;
177:
178:            private transient final Map<Class<?>, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<Class<?>, InjectionMetadata>();
179:
180:            private final Map<Object, EntityManager> extendedEntityManagersToClose = new ConcurrentHashMap<Object, EntityManager>();
181:
182:            public PersistenceAnnotationBeanPostProcessor() {
183:                setResourceRef(true);
184:            }
185:
186:            /**
187:             * Specify the persistence units for EntityManagerFactory lookups,
188:             * as a Map from persistence unit name to persistence unit JNDI name
189:             * (which needs to resolve to an EntityManagerFactory instance).
190:             * <p>JNDI names specified here should refer to <code>persistence-unit-ref</code>
191:             * entries in the Java EE deployment descriptor, matching the target persistence unit.
192:             * <p>In case of no unit name specified in the annotation, the specified value
193:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
194:             * will be taken (by default, the value mapped to the empty String),
195:             * or simply the single persistence unit if there is only one.
196:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
197:             * lookup driven by the standard JPA annotations, and all EntityManagerFactory
198:             * references obtained from JNDI. No separate EntityManagerFactory bean
199:             * definitions are necessary in such a scenario.
200:             * <p>If no corresponding "persistenceContexts"/"extendedPersistenceContexts"
201:             * are specified, <code>@PersistenceContext</code> will be resolved to
202:             * EntityManagers built on top of the EntityManagerFactory defined here.
203:             * Note that those will be Spring-managed EntityManagers, which implement
204:             * transaction synchronization based on Spring's facilities.
205:             * If you prefer the Java EE 5 server's own EntityManager handling,
206:             * specify corresponding "persistenceContexts"/"extendedPersistenceContexts".
207:             */
208:            public void setPersistenceUnits(Map<String, String> persistenceUnits) {
209:                this .persistenceUnits = persistenceUnits;
210:            }
211:
212:            /**
213:             * Specify the <i>transactional</i> persistence contexts for EntityManager lookups,
214:             * as a Map from persistence unit name to persistence context JNDI name
215:             * (which needs to resolve to an EntityManager instance).
216:             * <p>JNDI names specified here should refer to <code>persistence-context-ref</code>
217:             * entries in the Java EE deployment descriptors, matching the target persistence unit
218:             * and being set up with persistence context type <code>Transaction</code>.
219:             * <p>In case of no unit name specified in the annotation, the specified value
220:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
221:             * will be taken (by default, the value mapped to the empty String),
222:             * or simply the single persistence unit if there is only one.
223:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
224:             * lookup driven by the standard JPA annotations, and all EntityManager
225:             * references obtained from JNDI. No separate EntityManagerFactory bean
226:             * definitions are necessary in such a scenario, and all EntityManager
227:             * handling is done by the Java EE 5 server itself.
228:             */
229:            public void setPersistenceContexts(
230:                    Map<String, String> persistenceContexts) {
231:                this .persistenceContexts = persistenceContexts;
232:            }
233:
234:            /**
235:             * Specify the <i>extended</i> persistence contexts for EntityManager lookups,
236:             * as a Map from persistence unit name to persistence context JNDI name
237:             * (which needs to resolve to an EntityManager instance).
238:             * <p>JNDI names specified here should refer to <code>persistence-context-ref</code>
239:             * entries in the Java EE deployment descriptors, matching the target persistence unit
240:             * and being set up with persistence context type <code>Extended</code>.
241:             * <p>In case of no unit name specified in the annotation, the specified value
242:             * for the {@link #setDefaultPersistenceUnitName default persistence unit}
243:             * will be taken (by default, the value mapped to the empty String),
244:             * or simply the single persistence unit if there is only one.
245:             * <p>This is mainly intended for use in a Java EE 5 environment, with all
246:             * lookup driven by the standard JPA annotations, and all EntityManager
247:             * references obtained from JNDI. No separate EntityManagerFactory bean
248:             * definitions are necessary in such a scenario, and all EntityManager
249:             * handling is done by the Java EE 5 server itself.
250:             */
251:            public void setExtendedPersistenceContexts(
252:                    Map<String, String> extendedPersistenceContexts) {
253:                this .extendedPersistenceContexts = extendedPersistenceContexts;
254:            }
255:
256:            /**
257:             * Specify the default persistence unit name, to be used in case
258:             * of no unit name specified in an <code>@PersistenceUnit</code> /
259:             * <code>@PersistenceContext</code> annotation.
260:             * <p>This is mainly intended for lookups in the application context,
261:             * indicating the target persistence unit name (typically matching
262:             * the bean name), but also applies to lookups in the
263:             * {@link #setPersistenceUnits "persistenceUnits"} /
264:             * {@link #setPersistenceContexts "persistenceContexts"} /
265:             * {@link #setExtendedPersistenceContexts "extendedPersistenceContexts"} map,
266:             * avoiding the need for duplicated mappings for the empty String there.
267:             * <p>Default is to check for a single EntityManagerFactory bean
268:             * in the Spring application context, if any. If there are multiple
269:             * such factories, either specify this default persistence unit name
270:             * or explicitly refer to named persistence units in your annotations.
271:             */
272:            public void setDefaultPersistenceUnitName(String unitName) {
273:                this .defaultPersistenceUnitName = (unitName != null ? unitName
274:                        : "");
275:            }
276:
277:            public void setOrder(int order) {
278:                this .order = order;
279:            }
280:
281:            public int getOrder() {
282:                return this .order;
283:            }
284:
285:            public void setBeanFactory(BeanFactory beanFactory) {
286:                if (beanFactory instanceof  ListableBeanFactory) {
287:                    this .beanFactory = (ListableBeanFactory) beanFactory;
288:                }
289:            }
290:
291:            public Object postProcessBeforeInstantiation(Class beanClass,
292:                    String beanName) throws BeansException {
293:                return null;
294:            }
295:
296:            public boolean postProcessAfterInstantiation(Object bean,
297:                    String beanName) throws BeansException {
298:                InjectionMetadata metadata = findPersistenceMetadata(bean
299:                        .getClass());
300:                try {
301:                    metadata.injectFields(bean, beanName);
302:                } catch (Throwable ex) {
303:                    throw new BeanCreationException(beanName,
304:                            "Injection of persistence fields failed", ex);
305:                }
306:                return true;
307:            }
308:
309:            public PropertyValues postProcessPropertyValues(PropertyValues pvs,
310:                    PropertyDescriptor[] pds, Object bean, String beanName)
311:                    throws BeansException {
312:
313:                InjectionMetadata metadata = findPersistenceMetadata(bean
314:                        .getClass());
315:                try {
316:                    metadata.injectMethods(bean, beanName, pvs);
317:                } catch (Throwable ex) {
318:                    throw new BeanCreationException(beanName,
319:                            "Injection of persistence methods failed", ex);
320:                }
321:                return pvs;
322:            }
323:
324:            public Object postProcessBeforeInitialization(Object bean,
325:                    String beanName) throws BeansException {
326:                return bean;
327:            }
328:
329:            public Object postProcessAfterInitialization(Object bean,
330:                    String beanName) throws BeansException {
331:                return bean;
332:            }
333:
334:            public void postProcessBeforeDestruction(Object bean,
335:                    String beanName) throws BeansException {
336:                EntityManager emToClose = this .extendedEntityManagersToClose
337:                        .remove(bean);
338:                if (emToClose != null) {
339:                    emToClose.close();
340:                }
341:            }
342:
343:            private InjectionMetadata findPersistenceMetadata(Class clazz) {
344:                // Quick check on the concurrent map first, with minimal locking.
345:                InjectionMetadata metadata = this .injectionMetadataCache
346:                        .get(clazz);
347:                if (metadata == null) {
348:                    synchronized (this .injectionMetadataCache) {
349:                        metadata = this .injectionMetadataCache.get(clazz);
350:                        if (metadata == null) {
351:                            final InjectionMetadata newMetadata = new InjectionMetadata();
352:                            ReflectionUtils.doWithFields(clazz,
353:                                    new ReflectionUtils.FieldCallback() {
354:                                        public void doWith(Field field) {
355:                                            PersistenceContext pc = field
356:                                                    .getAnnotation(PersistenceContext.class);
357:                                            PersistenceUnit pu = field
358:                                                    .getAnnotation(PersistenceUnit.class);
359:                                            if (pc != null || pu != null) {
360:                                                if (Modifier.isStatic(field
361:                                                        .getModifiers())) {
362:                                                    throw new IllegalStateException(
363:                                                            "Persistence annotations are not supported on static fields");
364:                                                }
365:                                                newMetadata
366:                                                        .addInjectedField(new PersistenceElement(
367:                                                                field, null));
368:                                            }
369:                                        }
370:                                    });
371:                            ReflectionUtils.doWithMethods(clazz,
372:                                    new ReflectionUtils.MethodCallback() {
373:                                        public void doWith(Method method) {
374:                                            PersistenceContext pc = method
375:                                                    .getAnnotation(PersistenceContext.class);
376:                                            PersistenceUnit pu = method
377:                                                    .getAnnotation(PersistenceUnit.class);
378:                                            if (pc != null || pu != null) {
379:                                                if (Modifier.isStatic(method
380:                                                        .getModifiers())) {
381:                                                    throw new IllegalStateException(
382:                                                            "Persistence annotations are not supported on static methods");
383:                                                }
384:                                                if (method.getParameterTypes().length != 1) {
385:                                                    throw new IllegalStateException(
386:                                                            "Persistence annotation requires a single-arg method: "
387:                                                                    + method);
388:                                                }
389:                                                PropertyDescriptor pd = BeanUtils
390:                                                        .findPropertyForMethod(method);
391:                                                newMetadata
392:                                                        .addInjectedMethod(new PersistenceElement(
393:                                                                method, pd));
394:                                            }
395:                                        }
396:                                    });
397:                            metadata = newMetadata;
398:                            this .injectionMetadataCache.put(clazz, metadata);
399:                        }
400:                    }
401:                }
402:                return metadata;
403:            }
404:
405:            /**
406:             * Return a specified persistence unit for the given unit name,
407:             * as defined through the "persistenceUnits" map.
408:             * @param unitName the name of the persistence unit
409:             * @return the corresponding EntityManagerFactory,
410:             * or <code>null</code> if none found
411:             * @see #setPersistenceUnits
412:             */
413:            protected EntityManagerFactory getPersistenceUnit(String unitName) {
414:                if (this .persistenceUnits != null) {
415:                    String unitNameForLookup = (unitName != null ? unitName
416:                            : "");
417:                    if ("".equals(unitNameForLookup)) {
418:                        unitNameForLookup = this .defaultPersistenceUnitName;
419:                    }
420:                    String jndiName = this .persistenceUnits
421:                            .get(unitNameForLookup);
422:                    if (jndiName == null && "".equals(unitNameForLookup)
423:                            && this .persistenceUnits.size() == 1) {
424:                        jndiName = this .persistenceUnits.values().iterator()
425:                                .next();
426:                    }
427:                    if (jndiName != null) {
428:                        try {
429:                            return (EntityManagerFactory) lookup(jndiName,
430:                                    EntityManagerFactory.class);
431:                        } catch (NamingException ex) {
432:                            throw new IllegalStateException(
433:                                    "Could not obtain EntityManagerFactory ["
434:                                            + jndiName + "] from JNDI", ex);
435:                        }
436:                    }
437:                }
438:                return null;
439:            }
440:
441:            /**
442:             * Return a specified persistence context for the given unit name, as defined
443:             * through the "persistenceContexts" (or "extendedPersistenceContexts") map.
444:             * @param unitName the name of the persistence unit
445:             * @param extended whether to obtain an extended persistence context
446:             * @return the corresponding EntityManager, or <code>null</code> if none found
447:             * @see #setPersistenceContexts
448:             * @see #setExtendedPersistenceContexts
449:             */
450:            protected EntityManager getPersistenceContext(String unitName,
451:                    boolean extended) {
452:                Map<String, String> contexts = (extended ? this .extendedPersistenceContexts
453:                        : this .persistenceContexts);
454:                if (contexts != null) {
455:                    String unitNameForLookup = (unitName != null ? unitName
456:                            : "");
457:                    if ("".equals(unitNameForLookup)) {
458:                        unitNameForLookup = this .defaultPersistenceUnitName;
459:                    }
460:                    String jndiName = contexts.get(unitNameForLookup);
461:                    if (jndiName == null && "".equals(unitNameForLookup)
462:                            && contexts.size() == 1) {
463:                        jndiName = contexts.values().iterator().next();
464:                    }
465:                    if (jndiName != null) {
466:                        try {
467:                            return (EntityManager) lookup(jndiName,
468:                                    EntityManager.class);
469:                        } catch (NamingException ex) {
470:                            throw new IllegalStateException(
471:                                    "Could not obtain EntityManager ["
472:                                            + jndiName + "] from JNDI", ex);
473:                        }
474:                    }
475:                }
476:                return null;
477:            }
478:
479:            /**
480:             * Find an EntityManagerFactory with the given name in the current Spring
481:             * application context, falling back to a single default EntityManagerFactory
482:             * (if any) in case of no unit name specified.
483:             * @param unitName the name of the persistence unit (may be <code>null</code> or empty)
484:             * @param requestingBeanName the name of the requesting bean
485:             * @return the EntityManagerFactory
486:             * @throws NoSuchBeanDefinitionException if there is no such EntityManagerFactory in the context
487:             */
488:            protected EntityManagerFactory findEntityManagerFactory(
489:                    String unitName, String requestingBeanName)
490:                    throws NoSuchBeanDefinitionException {
491:
492:                if (this .beanFactory == null) {
493:                    throw new IllegalStateException(
494:                            "ListableBeanFactory required for EntityManagerFactory bean lookup");
495:                }
496:                String unitNameForLookup = (unitName != null ? unitName : "");
497:                if ("".equals(unitNameForLookup)) {
498:                    unitNameForLookup = this .defaultPersistenceUnitName;
499:                }
500:                if (!"".equals(unitNameForLookup)) {
501:                    return findNamedEntityManagerFactory(unitNameForLookup,
502:                            requestingBeanName);
503:                } else {
504:                    return findDefaultEntityManagerFactory(requestingBeanName);
505:                }
506:            }
507:
508:            /**
509:             * Find an EntityManagerFactory with the given name in the current
510:             * Spring application context.
511:             * @param unitName the name of the persistence unit (never empty)
512:             * @param requestingBeanName the name of the requesting bean
513:             * @return the EntityManagerFactory
514:             * @throws NoSuchBeanDefinitionException if there is no such EntityManagerFactory in the context
515:             */
516:            protected EntityManagerFactory findNamedEntityManagerFactory(
517:                    String unitName, String requestingBeanName)
518:                    throws NoSuchBeanDefinitionException {
519:
520:                EntityManagerFactory emf = EntityManagerFactoryUtils
521:                        .findEntityManagerFactory(this .beanFactory, unitName);
522:                if (this .beanFactory instanceof  ConfigurableBeanFactory) {
523:                    ((ConfigurableBeanFactory) this .beanFactory)
524:                            .registerDependentBean(unitName, requestingBeanName);
525:                }
526:                return emf;
527:            }
528:
529:            /**
530:             * Find a single default EntityManagerFactory in the Spring application context.
531:             * @return the default EntityManagerFactory
532:             * @throws NoSuchBeanDefinitionException if there is no single EntityManagerFactory in the context
533:             */
534:            protected EntityManagerFactory findDefaultEntityManagerFactory(
535:                    String requestingBeanName)
536:                    throws NoSuchBeanDefinitionException {
537:
538:                Map matchingBeans = BeanFactoryUtils
539:                        .beansOfTypeIncludingAncestors(this .beanFactory,
540:                                EntityManagerFactory.class);
541:                if (matchingBeans.size() == 1) {
542:                    Map.Entry entry = (Map.Entry) matchingBeans.entrySet()
543:                            .iterator().next();
544:                    String unitName = (String) entry.getKey();
545:                    if (this .beanFactory instanceof  ConfigurableBeanFactory) {
546:                        ((ConfigurableBeanFactory) this .beanFactory)
547:                                .registerDependentBean(unitName,
548:                                        requestingBeanName);
549:                    }
550:                    return (EntityManagerFactory) entry.getValue();
551:                } else {
552:                    throw new NoSuchBeanDefinitionException(
553:                            EntityManagerFactory.class,
554:                            "expected single bean but found "
555:                                    + matchingBeans.size());
556:                }
557:            }
558:
559:            /**
560:             * Class representing injection information about an annotated field
561:             * or setter method.
562:             */
563:            private class PersistenceElement extends
564:                    InjectionMetadata.InjectedElement {
565:
566:                private final String unitName;
567:
568:                private PersistenceContextType type;
569:
570:                private Properties properties;
571:
572:                public PersistenceElement(Member member, PropertyDescriptor pd) {
573:                    super (member, pd);
574:                    AnnotatedElement ae = (AnnotatedElement) member;
575:                    PersistenceContext pc = ae
576:                            .getAnnotation(PersistenceContext.class);
577:                    PersistenceUnit pu = ae
578:                            .getAnnotation(PersistenceUnit.class);
579:                    Class resourceType = EntityManager.class;
580:                    if (pc != null) {
581:                        if (pu != null) {
582:                            throw new IllegalStateException(
583:                                    "Member may only be annotated with either "
584:                                            + "@PersistenceContext or @PersistenceUnit, not both: "
585:                                            + member);
586:                        }
587:                        Properties properties = null;
588:                        PersistenceProperty[] pps = pc.properties();
589:                        if (!ObjectUtils.isEmpty(pps)) {
590:                            properties = new Properties();
591:                            for (int i = 0; i < pps.length; i++) {
592:                                PersistenceProperty pp = pps[i];
593:                                properties.setProperty(pp.name(), pp.value());
594:                            }
595:                        }
596:                        this .unitName = pc.unitName();
597:                        this .type = pc.type();
598:                        this .properties = properties;
599:                    } else {
600:                        resourceType = EntityManagerFactory.class;
601:                        this .unitName = pu.unitName();
602:                    }
603:                    checkResourceType(resourceType);
604:                }
605:
606:                /**
607:                 * Resolve the object against the application context.
608:                 */
609:                @Override
610:                protected Object getResourceToInject(Object target,
611:                        String requestingBeanName) {
612:                    // Resolves to EntityManagerFactory or EntityManager.
613:                    if (this .type != null) {
614:                        return (this .type == PersistenceContextType.EXTENDED ? resolveExtendedEntityManager(
615:                                target, requestingBeanName)
616:                                : resolveEntityManager(requestingBeanName));
617:                    } else {
618:                        // OK, so we need an EntityManagerFactory...
619:                        return resolveEntityManagerFactory(requestingBeanName);
620:                    }
621:                }
622:
623:                private EntityManagerFactory resolveEntityManagerFactory(
624:                        String requestingBeanName) {
625:                    // Obtain EntityManagerFactory from JNDI?
626:                    EntityManagerFactory emf = getPersistenceUnit(this .unitName);
627:                    if (emf == null) {
628:                        // Need to search for EntityManagerFactory beans.
629:                        emf = findEntityManagerFactory(this .unitName,
630:                                requestingBeanName);
631:                    }
632:                    return emf;
633:                }
634:
635:                private EntityManager resolveEntityManager(
636:                        String requestingBeanName) {
637:                    // Obtain EntityManager reference from JNDI?
638:                    EntityManager em = getPersistenceContext(this .unitName,
639:                            false);
640:                    if (em == null) {
641:                        // No pre-built EntityManager found -> build one based on factory.
642:                        // Obtain EntityManagerFactory from JNDI?
643:                        EntityManagerFactory emf = getPersistenceUnit(this .unitName);
644:                        if (emf == null) {
645:                            // Need to search for EntityManagerFactory beans.
646:                            emf = findEntityManagerFactory(this .unitName,
647:                                    requestingBeanName);
648:                        }
649:                        // Inject a shared transactional EntityManager proxy.
650:                        if (emf instanceof  EntityManagerFactoryInfo
651:                                && !EntityManager.class
652:                                        .equals(((EntityManagerFactoryInfo) emf)
653:                                                .getEntityManagerInterface())) {
654:                            // Create EntityManager based on the info's vendor-specific type
655:                            // (which might be more specific than the field's type).
656:                            em = SharedEntityManagerCreator
657:                                    .createSharedEntityManager(emf,
658:                                            this .properties);
659:                        } else {
660:                            // Create EntityManager based on the field's type.
661:                            em = SharedEntityManagerCreator
662:                                    .createSharedEntityManager(emf,
663:                                            this .properties, getResourceType());
664:                        }
665:                    }
666:                    return em;
667:                }
668:
669:                private EntityManager resolveExtendedEntityManager(
670:                        Object target, String requestingBeanName) {
671:                    // Obtain EntityManager reference from JNDI?
672:                    EntityManager em = getPersistenceContext(this .unitName,
673:                            true);
674:                    if (em == null) {
675:                        // No pre-built EntityManager found -> build one based on factory.
676:                        // Obtain EntityManagerFactory from JNDI?
677:                        EntityManagerFactory emf = getPersistenceUnit(this .unitName);
678:                        if (emf == null) {
679:                            // Need to search for EntityManagerFactory beans.
680:                            emf = findEntityManagerFactory(this .unitName,
681:                                    requestingBeanName);
682:                        }
683:                        // Inject a container-managed extended EntityManager.
684:                        em = ExtendedEntityManagerCreator
685:                                .createContainerManagedEntityManager(emf,
686:                                        this .properties);
687:                    }
688:                    if (em instanceof  EntityManagerProxy && beanFactory != null
689:                            && !beanFactory.isPrototype(requestingBeanName)) {
690:                        extendedEntityManagersToClose.put(target,
691:                                ((EntityManagerProxy) em)
692:                                        .getTargetEntityManager());
693:                    }
694:                    return em;
695:                }
696:            }
697:
698:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.