All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy Maven / Gradle / Ivy

There is a newer version: 5.3.34
Show newest version
/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.orm.jdo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;

/**
 * Proxy for a target JDO {@link javax.jdo.PersistenceManagerFactory},
 * returning the current thread-bound PersistenceManager (the Spring-managed
 * transactional PersistenceManager or a the single OpenPersistenceManagerInView
 * PersistenceManager) on getPersistenceManager(), if any.
 *
 * 

Essentially, getPersistenceManager() calls get seamlessly * forwarded to {@link PersistenceManagerFactoryUtils#getPersistenceManager}. * Furthermore, PersistenceManager.close calls get forwarded to * {@link PersistenceManagerFactoryUtils#releasePersistenceManager}. * *

The main advantage of this proxy is that it allows DAOs to work with a * plain JDO PersistenceManagerFactory reference, while still participating in * Spring's (or a J2EE server's) resource and transaction management. DAOs will * only rely on the JDO API in such a scenario, without any Spring dependencies. * *

Note that the behavior of this proxy matches the behavior that the JDO spec * defines for a PersistenceManagerFactory as exposed by a JCA connector, when * deployed in a J2EE server. Hence, DAOs could seamlessly switch between a JNDI * PersistenceManagerFactory and this proxy for a local PersistenceManagerFactory, * receiving the reference through Dependency Injection. This will work without * any Spring API dependencies in the DAO code! * *

It is usually preferable to write your JDO-based DAOs with Spring's * {@link JdoTemplate}, offering benefits such as consistent data access * exceptions instead of JDOExceptions at the DAO layer. However, Spring's * resource and transaction management (and Dependency Injection) will work * for DAOs written against the plain JDO API as well. * *

Of course, you can still access the target PersistenceManagerFactory * even when your DAOs go through this proxy, by defining a bean reference * that points directly at your target PersistenceManagerFactory bean. * * @author Juergen Hoeller * @since 1.2 * @see javax.jdo.PersistenceManagerFactory#getPersistenceManager() * @see javax.jdo.PersistenceManager#close() * @see PersistenceManagerFactoryUtils#getPersistenceManager * @see PersistenceManagerFactoryUtils#releasePersistenceManager */ public class TransactionAwarePersistenceManagerFactoryProxy implements FactoryBean { private PersistenceManagerFactory target; private boolean allowCreate = true; private PersistenceManagerFactory proxy; /** * Set the target JDO PersistenceManagerFactory that this proxy should * delegate to. This should be the raw PersistenceManagerFactory, as * accessed by JdoTransactionManager. * @see org.springframework.orm.jdo.JdoTransactionManager */ public void setTargetPersistenceManagerFactory(PersistenceManagerFactory target) { this.target = target; Class[] ifcs = ClassUtils.getAllInterfaces(target); this.proxy = (PersistenceManagerFactory) Proxy.newProxyInstance( getClass().getClassLoader(), ifcs, new TransactionAwareFactoryInvocationHandler()); } /** * Return the target JDO PersistenceManagerFactory that this proxy delegates to. */ public PersistenceManagerFactory getTargetPersistenceManagerFactory() { return this.target; } /** * Set whether the PersistenceManagerFactory proxy is allowed to create * a non-transactional PersistenceManager when no transactional * PersistenceManager can be found for the current thread. *

Default is "true". Can be turned off to enforce access to * transactional PersistenceManagers, which safely allows for DAOs * written to get a PersistenceManager without explicit closing * (i.e. a PersistenceManagerFactory.getPersistenceManager() * call without corresponding PersistenceManager.close() call). * @see PersistenceManagerFactoryUtils#getPersistenceManager(javax.jdo.PersistenceManagerFactory, boolean) */ public void setAllowCreate(boolean allowCreate) { this.allowCreate = allowCreate; } /** * Return whether the PersistenceManagerFactory proxy is allowed to create * a non-transactional PersistenceManager when no transactional * PersistenceManager can be found for the current thread. */ protected boolean isAllowCreate() { return allowCreate; } public Object getObject() { return this.proxy; } public Class getObjectType() { return PersistenceManagerFactory.class; } public boolean isSingleton() { return true; } /** * Invocation handler that delegates getPersistenceManager calls on the * PersistenceManagerFactory proxy to PersistenceManagerFactoryUtils * for being aware of thread-bound transactions. */ private class TransactionAwareFactoryInvocationHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on PersistenceManagerFactory interface coming in... PersistenceManagerFactory target = getTargetPersistenceManagerFactory(); if (method.getName().equals("getPersistenceManager")) { PersistenceManager pm = PersistenceManagerFactoryUtils.doGetPersistenceManager(target, isAllowCreate()); Class[] ifcs = ClassUtils.getAllInterfaces(pm); return (PersistenceManager) Proxy.newProxyInstance( getClass().getClassLoader(), ifcs, new TransactionAwareInvocationHandler(pm, target)); } else if (method.getName().equals("equals")) { // Only consider equal when proxies are identical. return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); } else if (method.getName().equals("hashCode")) { // Use hashCode of PersistenceManagerFactory proxy. return new Integer(hashCode()); } // Invoke method on target PersistenceManagerFactory. try { return method.invoke(target, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } /** * Invocation handler that delegates close calls on PersistenceManagers to * PersistenceManagerFactoryUtils for being aware of thread-bound transactions. */ private static class TransactionAwareInvocationHandler implements InvocationHandler { private final PersistenceManager target; private final PersistenceManagerFactory persistenceManagerFactory; public TransactionAwareInvocationHandler(PersistenceManager target, PersistenceManagerFactory pmf) { this.target = target; this.persistenceManagerFactory = pmf; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Invocation on PersistenceManager interface coming in... if (method.getName().equals("equals")) { // Only consider equal when proxies are identical. return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); } else if (method.getName().equals("hashCode")) { // Use hashCode of PersistenceManager proxy. return new Integer(hashCode()); } else if (method.getName().equals("close")) { // Handle close method: only close if not within a transaction. if (this.persistenceManagerFactory != null) { PersistenceManagerFactoryUtils.doReleasePersistenceManager( this.target, this.persistenceManagerFactory); } return null; } // Invoke method on target PersistenceManager. try { return method.invoke(this.target, args); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy