001: /*
002: * Copyright 2004-2006 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.compass.spring.device;
018:
019: import org.compass.core.spi.InternalCompass;
020: import org.compass.core.transaction.TransactionFactory;
021: import org.compass.core.util.Assert;
022: import org.compass.gps.CompassGpsException;
023: import org.compass.gps.CompassGpsDevice;
024: import org.compass.gps.device.AbstractGpsDeviceWrapper;
025: import org.compass.gps.spi.CompassGpsInterfaceDevice;
026: import org.compass.spring.transaction.SpringSyncTransactionFactory;
027: import org.springframework.beans.factory.InitializingBean;
028: import org.springframework.transaction.PlatformTransactionManager;
029: import org.springframework.transaction.TransactionDefinition;
030: import org.springframework.transaction.TransactionStatus;
031: import org.springframework.transaction.support.TransactionCallbackWithoutResult;
032: import org.springframework.transaction.support.TransactionTemplate;
033:
034: /**
035: * A Spring Transaction device wrapper, which starts a new transaction (with transaction propagation of
036: * REQUIRES_NEW) for the device index operation.
037: * <p/>
038: * When using {@link SpringSyncTransactionFactory}, this gps device wrapper should be used to wrap all
039: * the devices within the application. Spring <code>PlatformTransactionManager</code> can either be
040: * injected, or the device wrapper will try to get it from the configured {@link org.compass.spring.LocalCompassBean}
041: * that is associated with the device {@link org.compass.gps.CompassGps}.
042: * <p/>
043: * By default, {@link #setAllowNoTransactionManager(boolean)} is set to <code>true</code>, so changing from
044: * {@link SpringSyncTransactionFactory} to {@link org.compass.core.transaction.LocalTransactionFactory} will not
045: * require additional configuration changes. Changing it to <code>false</code> will mean that a transaction manager
046: * must be accessible (either by setting the transcation manager, or associating one with the local compass bean).
047: *
048: * @author kimchy
049: */
050: public class SpringSyncTransactionGpsDeviceWrapper extends
051: AbstractGpsDeviceWrapper implements InitializingBean {
052:
053: private PlatformTransactionManager transactionManager;
054:
055: private boolean allowNoTransactionManager = true;
056:
057: public SpringSyncTransactionGpsDeviceWrapper() {
058:
059: }
060:
061: public SpringSyncTransactionGpsDeviceWrapper(CompassGpsDevice device) {
062: setGpsDevice(device);
063: }
064:
065: public void afterPropertiesSet() throws Exception {
066: Assert.notNull(gpsDevice, "Must set wrapped gpsDevice");
067: }
068:
069: /**
070: * If a Spring <code>PlatformTransactionManager<code> is available, will use it to execute the wrapped gps device
071: * index operation within a new transcation with a propagation level of REQUIRES_NEW.
072: */
073: public void index() throws CompassGpsException {
074: if (transactionManager == null) {
075: TransactionFactory transactionFactory = ((InternalCompass) ((CompassGpsInterfaceDevice) gpsDevice
076: .getGps()).getIndexCompass())
077: .getTransactionFactory();
078: if (transactionFactory instanceof SpringSyncTransactionFactory) {
079: SpringSyncTransactionFactory springSyncTransactionFactory = (SpringSyncTransactionFactory) transactionFactory;
080: transactionManager = springSyncTransactionFactory
081: .getTransactionManager();
082: }
083: }
084: if (transactionManager == null) {
085: if (allowNoTransactionManager) {
086: if (log.isDebugEnabled()) {
087: log
088: .debug("No transaction manager found, will not execute the index operation within its own transaction");
089: }
090: gpsDevice.index();
091: } else {
092: throw new CompassGpsException(
093: "No transaction manager is found, and it is not allowed");
094: }
095: } else {
096: if (log.isDebugEnabled()) {
097: log
098: .debug("Startin a new Spring transaction for device ["
099: + gpsDevice.getName()
100: + "] index operation");
101: }
102: TransactionTemplate transactionTemplate = new TransactionTemplate(
103: transactionManager);
104: transactionTemplate
105: .setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
106: transactionTemplate
107: .execute(new TransactionCallbackWithoutResult() {
108: protected void doInTransactionWithoutResult(
109: TransactionStatus transactionStatus) {
110: gpsDevice.index();
111: }
112: });
113: }
114: }
115:
116: /**
117: * Sets the Spring <code>PlatformTransactionManager</code> that will be used to start a new transaction
118: * for the {@link #index()} operation. Note, this is an optioanl parameter, since if not set, Compass will
119: * try and get Spring transaction manager from the associated {@link org.compass.spring.LocalCompassBean}.
120: */
121: public void setTransactionManager(
122: PlatformTransactionManager transactionManager) {
123: this .transactionManager = transactionManager;
124: }
125:
126: /**
127: * Should the device allows for cases where no Spring transaction manager is provided (for example, when
128: * using Compass {@link org.compass.core.transaction.LocalTransactionFactory} and not setting an transaction
129: * manager. In such cases, no new transaction will be started.
130: * <p/>
131: * Defaults to <code>true</code>.
132: */
133: public void setAllowNoTransactionManager(
134: boolean allowNoTransactionManager) {
135: this.allowNoTransactionManager = allowNoTransactionManager;
136: }
137: }
|