• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2010 Google, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.inject.persist.jpa;
18 
19 import com.google.common.annotations.VisibleForTesting;
20 import com.google.common.base.Preconditions;
21 import com.google.inject.Inject;
22 import com.google.inject.Provider;
23 import com.google.inject.Singleton;
24 import com.google.inject.persist.PersistService;
25 import com.google.inject.persist.UnitOfWork;
26 
27 import java.lang.annotation.Documented;
28 import java.lang.annotation.ElementType;
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.lang.annotation.Target;
32 import java.util.Map;
33 
34 import javax.persistence.EntityManager;
35 import javax.persistence.EntityManagerFactory;
36 import javax.persistence.Persistence;
37 
38 /**
39  * @author Dhanji R. Prasanna (dhanji@gmail.com)
40  */
41 @Singleton
42 class JpaPersistService implements Provider<EntityManager>, UnitOfWork, PersistService {
43   private final ThreadLocal<EntityManager> entityManager = new ThreadLocal<EntityManager>();
44 
45   private final String persistenceUnitName;
46   private final Map<?,?> persistenceProperties;
47 
48   @Inject
JpaPersistService(@pa String persistenceUnitName, @Nullable @Jpa Map<?,?> persistenceProperties)49   public JpaPersistService(@Jpa String persistenceUnitName,
50       @Nullable @Jpa Map<?,?> persistenceProperties) {
51     this.persistenceUnitName = persistenceUnitName;
52     this.persistenceProperties = persistenceProperties;
53   }
54 
get()55   public EntityManager get() {
56     if (!isWorking()) {
57       begin();
58     }
59 
60     EntityManager em = entityManager.get();
61     Preconditions.checkState(null != em, "Requested EntityManager outside work unit. "
62         + "Try calling UnitOfWork.begin() first, or use a PersistFilter if you "
63         + "are inside a servlet environment.");
64 
65     return em;
66   }
67 
isWorking()68   public boolean isWorking() {
69     return entityManager.get() != null;
70   }
71 
begin()72   public void begin() {
73     Preconditions.checkState(null == entityManager.get(),
74         "Work already begun on this thread. Looks like you have called UnitOfWork.begin() twice"
75          + " without a balancing call to end() in between.");
76 
77     entityManager.set(emFactory.createEntityManager());
78   }
79 
end()80   public void end() {
81     EntityManager em = entityManager.get();
82 
83     // Let's not penalize users for calling end() multiple times.
84     if (null == em) {
85       return;
86     }
87 
88     try {
89       em.close();
90     }
91     finally {
92       entityManager.remove();
93     }
94   }
95 
96   private volatile EntityManagerFactory emFactory;
97 
98   @VisibleForTesting
start(EntityManagerFactory emFactory)99   synchronized void start(EntityManagerFactory emFactory) {
100     this.emFactory = emFactory;
101   }
102 
start()103   public synchronized void start() {
104     Preconditions.checkState(null == emFactory, "Persistence service was already initialized.");
105 
106     if (null != persistenceProperties) {
107       this.emFactory = Persistence
108           .createEntityManagerFactory(persistenceUnitName, persistenceProperties);
109     } else {
110       this.emFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
111     }
112   }
113 
stop()114   public synchronized void stop() {
115     Preconditions.checkState(emFactory.isOpen(), "Persistence service was already shut down.");
116     emFactory.close();
117   }
118 
119   @Singleton
120   public static class EntityManagerFactoryProvider implements Provider<EntityManagerFactory> {
121     private final JpaPersistService emProvider;
122 
123     @Inject
EntityManagerFactoryProvider(JpaPersistService emProvider)124     public EntityManagerFactoryProvider(JpaPersistService emProvider) {
125       this.emProvider = emProvider;
126     }
127 
get()128     public EntityManagerFactory get() {
129       assert null != emProvider.emFactory;
130       return emProvider.emFactory;
131     }
132   }
133 
134   @Documented
135   @Retention(RetentionPolicy.RUNTIME)
136   @Target(ElementType.PARAMETER)
137   private @interface Nullable { }
138 
139 }
140