KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > jdo > LocalPersistenceManagerFactoryBean


1 /*
2  * Copyright 2002-2006 the original author or authors.
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 org.springframework.orm.jdo;
18
19 import java.io.IOException JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21 import java.util.Properties JavaDoc;
22
23 import javax.jdo.JDOException;
24 import javax.jdo.JDOHelper;
25 import javax.jdo.PersistenceManagerFactory;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 import org.springframework.beans.factory.DisposableBean;
31 import org.springframework.beans.factory.FactoryBean;
32 import org.springframework.beans.factory.InitializingBean;
33 import org.springframework.core.io.Resource;
34 import org.springframework.core.io.support.PropertiesLoaderUtils;
35 import org.springframework.dao.DataAccessException;
36 import org.springframework.dao.support.PersistenceExceptionTranslator;
37 import org.springframework.util.ClassUtils;
38 import org.springframework.util.CollectionUtils;
39 import org.springframework.util.ReflectionUtils;
40
41 /**
42  * {@link org.springframework.beans.factory.FactoryBean} that creates a
43  * JDO {@link javax.jdo.PersistenceManagerFactory}. This is the usual way to
44  * set up a shared JDO PersistenceManagerFactory in a Spring application context;
45  * the PersistenceManagerFactory can then be passed to JDO-based DAOs via
46  * dependency injection. Note that switching to a JNDI lookup or to a bean-style
47  * PersistenceManagerFactory instance is just a matter of configuration!
48  *
49  * <p>Configuration settings can either be read from a properties file,
50  * specified as "configLocation", or completely via this class. Properties
51  * specified as "jdoProperties" here will override any settings in a file.
52  *
53  * <p>This PersistenceManager handling strategy is most appropriate for
54  * applications which solely use JDO for data access. In this case,
55  * {@link JdoTransactionManager} is more convenient than setting up your
56  * JDO provider for JTA transactions (which might involve a JCA connector).
57  *
58  * <p><b>NOTE:</b> This class is compatible with both JDO 1.0 and JDO 2.0,
59  * as far as possible. It uses reflection to adapt to the actual API present
60  * on the class path (concretely: for the <code>getPersistenceManagerFactory</code>
61  * method with either a <code>Properties</code> or a <code>Map</code> argument).
62  * Make sure that the JDO API jar on your class path matches the one that
63  * your JDO provider has been compiled against!
64  *
65  * <p>This class also implements the
66  * {@link org.springframework.dao.support.PersistenceExceptionTranslator}
67  * interface, as autodetected by Spring's
68  * {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
69  * for AOP-based translation of native exceptions to Spring DataAccessExceptions.
70  * Hence, the presence of a LocalPersistenceManagerFactoryBean automatically enables
71  * a PersistenceExceptionTranslationPostProcessor to translate JDO exceptions.
72  *
73  * <p><b>Alternative: Configuration of a PersistenceManagerFactory provider bean</b>
74  *
75  * <p>As alternative to the properties-driven approach that this FactoryBean offers
76  * (which is analogous to using the standard JDOHelper class with a Properties
77  * object that is populated with standard JDO properties), you can set up an
78  * instance of your PersistenceManagerFactory implementation class directly.
79  *
80  * <p>Like a DataSource, a PersistenceManagerFactory is encouraged to
81  * support bean-style configuration, which makes it very easy to set up as
82  * Spring-managed bean. The implementation class becomes the bean class;
83  * the remaining properties are applied as bean properties (starting with
84  * lower-case characters, in contrast to the corresponding JDO properties).
85  *
86  * <p>For example, in case of <a HREF="http://www.jpox.org">JPOX</a>:
87  *
88  * <p><pre>
89  * &lt;bean id="persistenceManagerFactory" class="org.jpox.PersistenceManagerFactoryImpl" destroy-method="close"&gt;
90  * &lt;property name="connectionFactory" ref="dataSource"/&gt;
91  * &lt;property name="nontransactionalRead" value="true"/&gt;
92  * &lt;/bean&gt;
93  * </pre>
94  *
95  * <p>Note that such direct setup of a PersistenceManagerFactory implementation
96  * is the only way to pass an external connection factory (i.e. a JDBC DataSource)
97  * into a JDO PersistenceManagerFactory. With the standard properties-driven approach,
98  * you can only use an internal connection pool or a JNDI DataSource.
99  *
100  * <p>The <code>close()</code> method is standardized as of JDO 1.0.1; don't forget to
101  * specify it as "destroy-method" for any PersistenceManagerFactory instance.
102  * Note that this FactoryBean will automatically invoke <code>close()</code> for
103  * the PersistenceManagerFactory that it creates, without any special configuration.
104  *
105  * @author Juergen Hoeller
106  * @since 03.06.2003
107  * @see JdoTemplate#setPersistenceManagerFactory
108  * @see JdoTransactionManager#setPersistenceManagerFactory
109  * @see org.springframework.jndi.JndiObjectFactoryBean
110  * @see javax.jdo.JDOHelper#getPersistenceManagerFactory
111  * @see javax.jdo.PersistenceManagerFactory#setConnectionFactory
112  * @see javax.jdo.PersistenceManagerFactory#close()
113  * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
114  */

115 public class LocalPersistenceManagerFactoryBean
116         implements FactoryBean, InitializingBean, DisposableBean, PersistenceExceptionTranslator {
117
118     // Determine whether the JDO 1.0 getPersistenceManagerFactory(Properties) method
119
// is available, for use in the "newPersistenceManagerFactory" implementation.
120
private final static Method JavaDoc getPersistenceManagerFactoryMethod = ClassUtils.getMethodIfAvailable(
121             JDOHelper.class, "getPersistenceManagerFactory", new Class JavaDoc[] {Properties JavaDoc.class});
122
123
124     protected final Log logger = LogFactory.getLog(getClass());
125
126     private Resource configLocation;
127
128     private Properties JavaDoc jdoProperties;
129
130     private PersistenceManagerFactory persistenceManagerFactory;
131
132     private JdoDialect jdoDialect;
133
134
135     /**
136      * Set the location of the JDO properties config file, for example
137      * as classpath resource "classpath:kodo.properties".
138      * <p>Note: Can be omitted when all necessary properties are
139      * specified locally via this bean.
140      */

141     public void setConfigLocation(Resource configLocation) {
142         this.configLocation = configLocation;
143     }
144
145     /**
146      * Set JDO properties, such as"javax.jdo.PersistenceManagerFactoryClass".
147      * <p>Can be used to override values in a JDO properties config file,
148      * or to specify all necessary properties locally.
149      */

150     public void setJdoProperties(Properties JavaDoc jdoProperties) {
151         this.jdoProperties = jdoProperties;
152     }
153
154     /**
155      * Return the JDO properties, if any. Mainly available for
156      * configuration through property paths that specify individual keys.
157      */

158     public Properties JavaDoc getJdoProperties() {
159         if (this.jdoProperties == null) {
160             this.jdoProperties = new Properties JavaDoc();
161         }
162         return this.jdoProperties;
163     }
164
165     /**
166      * Set the JDO dialect to use for the PersistenceExceptionTranslator
167      * functionality of this factory.
168      * <p>Default is a DefaultJdoDialect based on the PersistenceManagerFactory's
169      * underlying DataSource, if any.
170      * @see JdoDialect#translateException
171      * @see #translateExceptionIfPossible
172      * @see org.springframework.dao.support.PersistenceExceptionTranslator
173      */

174     public void setJdoDialect(JdoDialect jdoDialect) {
175         this.jdoDialect = jdoDialect;
176     }
177
178
179     /**
180      * Initialize the PersistenceManagerFactory for the given location.
181      * @throws IllegalArgumentException in case of illegal property values
182      * @throws IOException if the properties could not be loaded from the given location
183      * @throws JDOException in case of JDO initialization errors
184      */

185     public void afterPropertiesSet() throws IllegalArgumentException JavaDoc, IOException JavaDoc, JDOException {
186         if (this.configLocation == null && this.jdoProperties == null) {
187             throw new IllegalArgumentException JavaDoc("Either configLocation or jdoProperties must be set");
188         }
189
190         Properties JavaDoc mergedProps = new Properties JavaDoc();
191
192         if (this.configLocation != null) {
193             if (logger.isInfoEnabled()) {
194                 logger.info("Loading JDO config from [" + this.configLocation + "]");
195             }
196             PropertiesLoaderUtils.fillProperties(mergedProps, this.configLocation);
197         }
198
199         CollectionUtils.mergePropertiesIntoMap(this.jdoProperties, mergedProps);
200
201         // Build PersistenceManagerFactory instance.
202
logger.info("Building new JDO PersistenceManagerFactory");
203         this.persistenceManagerFactory = newPersistenceManagerFactory(mergedProps);
204
205         // Build default JdoDialect if none explicitly specified.
206
if (this.jdoDialect == null) {
207             this.jdoDialect = new DefaultJdoDialect(this.persistenceManagerFactory.getConnectionFactory());
208         }
209     }
210
211     /**
212      * Subclasses can override this to perform custom initialization of the
213      * PersistenceManagerFactory instance, creating it via the given Properties
214      * that got prepared by this LocalPersistenceManagerFactoryBean.
215      * <p>The default implementation invokes JDOHelper's
216      * <code>getPersistenceManagerFactory</code> method.
217      * A custom implementation could prepare the instance in a specific way,
218      * or use a custom PersistenceManagerFactory implementation.
219      * <p>Implemented to work with either the JDO 1.0
220      * <code>getPersistenceManagerFactory(java.util.Properties)</code> method or
221      * the JDO 2.0 <code>getPersistenceManagerFactory(java.util.Map)</code> method,
222      * detected through reflection.
223      * @param props the merged Properties prepared by this LocalPersistenceManagerFactoryBean
224      * @return the PersistenceManagerFactory instance
225      * @see javax.jdo.JDOHelper#getPersistenceManagerFactory(java.util.Map)
226      */

227     protected PersistenceManagerFactory newPersistenceManagerFactory(Properties JavaDoc props) {
228         // Use JDO 1.0 getPersistenceManagerFactory(Properties) method, if available.
229
if (getPersistenceManagerFactoryMethod != null) {
230             return (PersistenceManagerFactory) ReflectionUtils.invokeMethod(
231                     getPersistenceManagerFactoryMethod, null, new Object JavaDoc[] {props});
232         }
233         // Use JDO 2.0 getPersistenceManagerFactory(Map) method else.
234
return JDOHelper.getPersistenceManagerFactory(props);
235     }
236
237
238     /**
239      * Return the singleton PersistenceManagerFactory.
240      */

241     public Object JavaDoc getObject() {
242         return this.persistenceManagerFactory;
243     }
244
245     public Class JavaDoc getObjectType() {
246         return (this.persistenceManagerFactory != null ?
247             this.persistenceManagerFactory.getClass() : PersistenceManagerFactory.class);
248     }
249
250     public boolean isSingleton() {
251         return true;
252     }
253
254
255     /**
256      * Implementation of the PersistenceExceptionTranslator interface,
257      * as autodetected by Spring's PersistenceExceptionTranslationPostProcessor.
258      * <p>Converts the exception if it is a JDOException, preferably using a specified
259      * JdoDialect. Else returns <code>null</code> to indicate an unknown exception.
260      * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
261      * @see JdoDialect#translateException
262      * @see PersistenceManagerFactoryUtils#convertJdoAccessException
263      */

264     public DataAccessException translateExceptionIfPossible(RuntimeException JavaDoc ex) {
265         if (ex instanceof JDOException) {
266             if (this.jdoDialect != null) {
267                 return this.jdoDialect.translateException((JDOException) ex);
268             }
269             else {
270                 return PersistenceManagerFactoryUtils.convertJdoAccessException((JDOException) ex);
271             }
272         }
273         return null;
274     }
275
276
277     /**
278      * Close the PersistenceManagerFactory on bean factory shutdown.
279      */

280     public void destroy() {
281         logger.info("Closing JDO PersistenceManagerFactory");
282         this.persistenceManagerFactory.close();
283     }
284
285 }
286
Popular Tags