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

scriptella.execution.EtlExecutor Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2006-2012 The Scriptella Project Team.
 *
 * 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 scriptella.execution;

import scriptella.configuration.ConfigurationEl;
import scriptella.configuration.ConfigurationFactory;
import scriptella.core.Session;
import scriptella.core.SystemException;
import scriptella.core.ThreadSafe;
import scriptella.interactive.ProgressCallback;
import scriptella.interactive.ProgressIndicator;
import scriptella.util.CollectionUtils;
import scriptella.util.IOUtils;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Executor for ETL files.
 * 

Use {@link ConfigurationFactory} to parse script files and to configure * the executor. *

The usage scenario of this class may be described using the following steps: *

    *
  • {@link #EtlExecutor(scriptella.configuration.ConfigurationEl)} Create an instance of this class * and pass a {@link scriptella.configuration.ConfigurationFactory#createConfiguration() script file configuration}. *
  • {@link #execute() Execute} the script *
*
*

Additionally simplified helper methods are declared in this class: *

    *
  • {@link #newExecutor(java.io.File)} *
  • {@link #newExecutor(java.net.URL)} *
  • {@link #newExecutor(java.net.URL, java.util.Map)} *
*

*

ETL Cancellation

* Scriptella execution model relies on a standard Java {@link Thread#interrupt()} mechanism. *

To interrupt the ETL execution invoke {@link Thread#interrupt()} on a thread * which {@link #execute() started} ETL operation. As a part of interruption process * the engine tries to roll back all changes made during the ETL operation. *

{@link java.util.concurrent.ExecutorService} and {@link java.util.concurrent.Future} * can also be used to control ETL execution. *

Integration with third-party systems

* For convenience EtlExecutor implements {@link Runnable} and {@link java.util.concurrent.Callable}. * This feature simplifies integration of Scriptella executors with {@link java.util.concurrent.Executors} * or other systems like Spring/Quartz etc. It also minimizes application code dependency on Scriptella. * * @author Fyodor Kupolov * @version 1.0 */ public class EtlExecutor implements Runnable, Callable { private static final Logger LOG = Logger.getLogger(EtlExecutor.class.getName()); private ConfigurationEl configuration; private boolean jmxEnabled; private boolean suppressStatistics; /** * Creates ETL executor. */ public EtlExecutor() { } /** * Creates an ETL executor for specified configuration file. * * @param configuration ETL configuration. */ public EtlExecutor(ConfigurationEl configuration) { this.configuration = configuration; } /** * Returns ETL configuration for this executor. * * @return ETL configuration. */ public ConfigurationEl getConfiguration() { return configuration; } /** * Sets ETL configuration. * * @param configuration ETL configuration. */ public void setConfiguration(final ConfigurationEl configuration) { this.configuration = configuration; } /** * Returns true if monitoring/management via JMX is enabled. *

If jmxEnabled=true the executor registers MBeans for executed ETL files. * The object names of the mbeans have the following form: * scriptella: type=etl,url="ETL_FILE_URL" * * @return true if monitoring/management via JMX is enabled. */ public boolean isJmxEnabled() { return jmxEnabled; } /** * Enables or disables ETL monitoring/management via JMX. *

If jmxEnabled=true the executor registers MBeans for executed ETL files. * The object names of the mbeans have the following form: * scriptella: type=etl,url="ETL_FILE_URL" * * @param jmxEnabled true if monitoring/management via JMX is enabled. * @see scriptella.execution.JmxEtlManagerMBean */ public void setJmxEnabled(boolean jmxEnabled) { this.jmxEnabled = jmxEnabled; } /** * Getter for {@link #setSuppressStatistics(boolean) suppressStatistics} property. * @return true if statistics collection is disabled. Default value is false. */ public boolean isSuppressStatistics() { return suppressStatistics; } /** * Enables or disables collecting of statistics. Default value is false, which means statistics is collected. *

Setting this option to true may improve performance in some cases. * @param suppressStatistics true if statistics collection should be disabled. */ public void setSuppressStatistics(boolean suppressStatistics) { this.suppressStatistics = suppressStatistics; } /** * Executes ETL based on a specified configuration. * * @return execution statistics for ETL execution. * @throws EtlExecutorException if ETL fails. * @see #execute(scriptella.interactive.ProgressIndicator) */ @ThreadSafe public ExecutionStatistics execute() throws EtlExecutorException { return execute((ProgressIndicator) null); } /** * Executes ETL based on a specified configuration. * * @param indicator progress indicator to use. * @return execution statistics for ETL execution. * @throws EtlExecutorException if ETL fails. */ @ThreadSafe public ExecutionStatistics execute(final ProgressIndicator indicator) throws EtlExecutorException { EtlContext ctx = null; JmxEtlManager etlManager = null; try { ctx = prepare(indicator); if (jmxEnabled) { etlManager = new JmxEtlManager(ctx); etlManager.register(); } execute(ctx); ctx.getProgressCallback().step(5, "Commiting transactions"); commitAll(ctx); } catch (Throwable e) { if (ctx != null) { rollbackAll(ctx); } throw new EtlExecutorException(e); } finally { if (ctx != null) { closeAll(ctx); ctx.getStatisticsBuilder().etlComplete(); ctx.getProgressCallback().complete(); } if (etlManager != null) { etlManager.unregister(); } } return ctx.getStatisticsBuilder().getStatistics(); } void rollbackAll(final EtlContext ctx) { try { ctx.session.rollback(); } catch (Exception e) { LOG.log(Level.SEVERE, "Unable to rollback script", e); } } void commitAll(final EtlContext ctx) { ctx.session.commit(); } void closeAll(final EtlContext ctx) { ctx.session.close(); } private void execute(final EtlContext ctx) { final ProgressCallback oldProgress = ctx.getProgressCallback(); final ProgressCallback p = oldProgress.fork(85, 100); final ProgressCallback p2 = p.fork(100); ctx.setProgressCallback(p2); ctx.session.execute(ctx); p.complete(); ctx.setProgressCallback(oldProgress); } /** * Prepares the scripts context. * * @param indicator progress indicator to use. * @return prepared scripts context. */ protected EtlContext prepare(final ProgressIndicator indicator) { EtlContext ctx = new EtlContext(!suppressStatistics); ctx.getStatisticsBuilder().etlStarted(); ctx.setBaseURL(configuration.getDocumentUrl()); ctx.setProgressCallback(new ProgressCallback(100, indicator)); final ProgressCallback progress = ctx.getProgressCallback(); progress.step(1, "Initializing properties"); ctx.setProperties(configuration.getParameters()); ctx.setProgressCallback(progress.fork(9, 100)); ctx.session = new Session(configuration, ctx); ctx.getProgressCallback().complete(); ctx.setProgressCallback(progress); //Restoring return ctx; } /** * Converts file to URL and invokes {@link #newExecutor(java.net.URL)}. * * @param scriptFile ETL file. * @return configured instance of script executor. * @see #newExecutor(java.net.URL) */ public static EtlExecutor newExecutor(final File scriptFile) { try { return newExecutor(IOUtils.toUrl(scriptFile)); } catch (MalformedURLException e) { throw new IllegalArgumentException(e.getMessage(), e); } } /** * Helper method to create a new ScriptExecutor for specified script URL. *

Calls {@link #newExecutor(java.net.URL, java.util.Map)} and passes {@link System#getProperties() System properties} * as external properties. * * @param scriptFileUrl URL of script file. * @return configured instance of script executor. */ @ThreadSafe public static EtlExecutor newExecutor(final URL scriptFileUrl) { return newExecutor(scriptFileUrl, CollectionUtils.asMap(System.getProperties())); } /** * Helper method to create a new ScriptExecutor for specified script URL. * * @param scriptFileUrl URL of script file. * @param externalProperties see {@link ConfigurationFactory#setExternalParameters(java.util.Map)} * @return configured instance of script executor. * @see ConfigurationFactory */ @ThreadSafe public static EtlExecutor newExecutor(final URL scriptFileUrl, final Map externalProperties) { ConfigurationFactory cf = new ConfigurationFactory(); cf.setResourceURL(scriptFileUrl); if (externalProperties != null) { cf.setExternalParameters(externalProperties); } return new EtlExecutor(cf.createConfiguration()); } //Runnable/Callable convenience interfaces /** * A runnable adapter for {@link #execute()} method. *

Please note that due to a checked * exceptions limitation a {@link scriptella.core.SystemException} is thrown instead of * the {@link scriptella.execution.EtlExecutorException}. * * @throws SystemException a wrapped {@link scriptella.execution.EtlExecutorException}. * @see #execute() */ public void run() throws SystemException { try { execute(); } catch (EtlExecutorException e) { throw new SystemException(e.getMessage(), e); } } /** * A synonym for {@link #execute()}. */ public ExecutionStatistics call() throws EtlExecutorException { return execute(); } }



© 2015 - 2025 Weber Informatics LLC | Privacy Policy