[Batchserver-cvs] batchserver/src/org/jmonks/batch/framework ErrorCode.java, NONE, 1.1 JobContext.j
Brought to you by:
suresh_pragada
Update of /cvsroot/batchserver/batchserver/src/org/jmonks/batch/framework In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv19484 Added Files: ErrorCode.java JobContext.java JobStatistics.java LoggingManager.java Main.java Repository.java Log Message: no message --- NEW FILE: JobContext.java --- /* * JobContext.java * * Created on September 13, 2006, 1:18 PM * * To change this template, choose Tools | Options and locate the template under * the Source Creation and Management node. Right-click the template and choose * Open. You can then make changes to the template in the Source Editor. */ package org.jmonks.batch.framework; import java.util.Collections; import java.util.Map; import org.apache.log4j.Logger; import org.jmonks.batch.framework.config.FrameworkConfig; import org.jmonks.batch.framework.config.JobConfig; /** * <p> * JobContext provides the references to the framework resources. * All the jobs will receives the JobContext reference either in their * initialize methods or process methods based on the controllers they choose to * implement the job. It exposes the resources like reference to repository (by * using which you can transfer the data between the jobs, saves the management & * monitoring information and job running statistics), running job configuration * (by using which you can refer the properties defined in the controller/processor * configuration), configuration provided to invoke the job (could be either command * line configuration or configuration provided to process method) and finally * framework configuration. All the configuration maps accessed through this job * context are unmodifiable. Framework creates the JobContext instance and passes * it to the controllers. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public class JobContext { /** * Constant defines the parameter name to be used in the context parameters * map to pass the job configuration to create the job context. */ public static final String CONTEXT_PARAM_JOB_CONFIG="batch.framework.job.context.job.config"; /** * Constant defines the parameter name to be used in the context parameters * map to pass the job invoke configuration to create the job context. */ public static final String CONTEXT_PARAM_JOB_INVOKE_CONFIG="batch.framework.job.context.job.invoke.config"; /** * Constant defines the parameter name to be used in the context parameters * map to pass the repository instance to create the job context. */ public static final String CONTEXT_PARAM_REPOSITORY="batch.framework.job.context.repository"; /** * Holds the job configuration object reference. */ protected JobConfig jobConfig=null; /** * Holds the framework repository reference. */ protected Repository repository=null; /** * Holds the job invoke configuration reference. */ protected Map jobInvokeConfig=null; private static Logger logger=Logger.getLogger(JobContext.class); /** * <p> * Creates and Initializes the JobContext object by looking up the information * in the given context parameters map. It looks for all the required parameters * and then initializes the complete job context. It accepts the Main class * instance context creator reference to make sure this will not be created * by other than Main class. * </p> * * @param contextParams Map contains all the required information to initialize the job context. * @param contextCreator Main class instance to make sure nobody can instantiate the job context. * * @throws SecurityException If context creator is other than Main class. * @throws IllegalArgumentException If any of the required parameters are missing in the context params. * */ public JobContext(Map contextParams, Main contextCreator) { logger.trace("Entering JobContext init. params= " + contextParams + " creator = " + contextCreator); if(!(contextCreator instanceof Main)) throw new SecurityException("Not authorized to create the job context."); if(contextParams==null) throw new IllegalArgumentException("Context params to initialize the context cannot be null."); /** * Retrieve and add the invoke configuration map to the context. */ if(contextParams.containsKey(JobContext.CONTEXT_PARAM_JOB_INVOKE_CONFIG)) { Object objectInvokeConfig=contextParams.get(JobContext.CONTEXT_PARAM_JOB_INVOKE_CONFIG); if(objectInvokeConfig instanceof Map) this.jobInvokeConfig=(Map)objectInvokeConfig; else throw new IllegalArgumentException("Provided job invoke configuration object to initalize job context is not valid."); } else throw new IllegalArgumentException("Missing the required job invoke configuration map object in context params."); logger.debug("Added the invoke configuration to JobContext"); /** * Retrieve and add the job config instance to the context. */ if(contextParams.containsKey(JobContext.CONTEXT_PARAM_JOB_CONFIG)) { Object objectJobConfig=contextParams.get(JobContext.CONTEXT_PARAM_JOB_CONFIG); if(objectJobConfig instanceof JobConfig) this.jobConfig=(JobConfig)objectJobConfig; else throw new IllegalArgumentException("Provided job config object to initailize the job context is not valid."); } else throw new IllegalArgumentException("Missing the required job configuration object in context params."); logger.debug("Added the job config reference to JobContext"); /** * Retrieve and add the repository instance to the context. */ if(contextParams.containsKey(JobContext.CONTEXT_PARAM_REPOSITORY)) { Object objectRepository=contextParams.get(JobContext.CONTEXT_PARAM_REPOSITORY); if(objectRepository instanceof Repository) this.repository=(Repository)objectRepository; else throw new IllegalArgumentException("Provided repository object to initailize the job context is not valid."); } else throw new IllegalArgumentException("Missing the required repository object in context params."); logger.debug("Added the repository reference to JobContext"); logger.trace("Exiting JobContext init"); } /** * Gets the name of the job this context is associated with. * * @return Returns the name of the job. */ public String getJobName() { return this.jobConfig.getJobName(); } /** * Gets the repository reference configured for this framework. * * @return Gets the repository reference. */ public Repository getRepository() { return this.repository; } /** * Gets the job configuration object belongs to the running job. * * @return Returns the running job's configuration object. */ public JobConfig getJobConfig() { return this.jobConfig; } /** * Gets the configuration passed in the invocation to the framework. This * could be command line parameters, if job is invoked from command line or * config map if job is invoked through Main.process method. * * @return Returns the configuration provided at the invocation time. */ public Map getJobInvokeConfig() { return Collections.unmodifiableMap(this.jobInvokeConfig); } /** * Gets the reference to the framework configuration. * * @return Gets the framework configuration reference. */ public FrameworkConfig getFrameworkConfig() { return FrameworkConfig.getInstance(); } } --- NEW FILE: JobStatistics.java --- package org.jmonks.batch.framework; import java.util.Date; /** * <p> * JobStatistics holds the useful metrics and information of particular run of a job. * These statistics helpful in research of the periodic growth of the jobs. * Statistics it holds are start and end time of the run, records have been processed * in the run, memory has been utilized in the run and exit code of that run. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public class JobStatistics { /** * Starting time of the job. */ private Date startTime; /** * Ending time of the job. */ private Date endTime; /** * Number of records processed in this job. */ private long recordsProcessed; /** * Maximum memory consumption in bytes. */ private long maxMemoryUsage; /** * Name of the job. */ private String jobName; /** * Exit code of the job. */ private ErrorCode exitCode=null; /** * Constructor takes the job name and build the skelton. */ public JobStatistics(String jobName) { this.jobName=jobName; this.startTime=null; this.endTime=null; this.maxMemoryUsage=0; this.recordsProcessed=0; this.exitCode=ErrorCode.JOB_COMPLETED_SUCCESSFULLY; } /** * Sets the startime of the job. * * @param startTime Starting time of the job. */ public void setStartTime(Date startTime) { this.startTime=startTime; } /** * Sets the endtime of the job. * * @param endTime Ending time of the job. */ public void setEndTime(Date endTime) { this.endTime = endTime; } /** * Sets the number of the records processed in this job. * * @param recordCount Sets the number of records got processed. */ public void setRecordsProcessed(long recordCount) { this.recordsProcessed = recordCount; } /** * Sets the maximum memory used for the job in bytes. * * @param memoryUsaeg Sets the memory usage by the job. */ public void setMaxMemeoryUsage(long memoryUsage) { this.maxMemoryUsage=memoryUsage; } /** * Gets the start time of this job. * * @return Returns the starting time of this job. */ public Date getStartTime() { return this.startTime; } /** * Gets the ending time of this job. * * @return Gets the end time of this job. */ public Date getEndTime() { return this.endTime; } /** * Gets the number of records processed. * * @return Returns the number of records got processed. */ public long getRecordsProcessed() { return this.recordsProcessed; } /** * Gets the maximum memory used by this job in bytes. * * @return Returns the max memory used by this job. */ public long getMaxMemoryUsage() { return this.maxMemoryUsage; } /** * Gets the job name * * @return Returns the name of this job. */ public String getJobname() { return this.jobName; } /** * Sets the given error code as exit code. * * @param exitCode Error code controller is going to return to the framework. */ public void setExitCode(ErrorCode exitCode) { this.exitCode=exitCode; } /** * Gets the exit code. */ public ErrorCode getExitCode() { return this.exitCode; } /** * <p> * Returns the string representation of JobStatistics class in the format * <br> {JobStatistics [jobName = value] [startTime = value] [endTime = value]} * </p> * * @return Returns the string representation of JobStatistics. */ public String toString() { StringBuffer stringValue=new StringBuffer("{JobStatistics "); stringValue.append("[jobName = " + this.jobName + "]"); stringValue.append("[startTime = " + ((this.startTime!=null)?this.startTime.toString():"") + "]"); stringValue.append("[endTime = " + ((this.endTime!=null)?this.endTime.toString():"") + "]"); stringValue.append("[maxMemoryUsage = " + this.maxMemoryUsage + "]"); stringValue.append("[recordsProcessed = " + this.recordsProcessed + "]"); stringValue.append("[exitCode = " + this.exitCode.toString() + "]"); stringValue.append("}"); return stringValue.toString(); } } --- NEW FILE: LoggingManager.java --- package org.jmonks.batch.framework; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.RollingFileAppender; import org.jmonks.batch.framework.config.ConfigurationException; import org.jmonks.batch.framework.config.FrameworkConfig.FrameworkLoggingConfig; import org.jmonks.batch.framework.config.JobLoggingConfig; /** * <p> * Logging Manager provides the logging services to the framework. * It defines the default logging mechanism at the framework level * which works for all the jobs and provide the facility to * use their own logging mechanism. * </p> * <p> * The default logging mechanism defined at the framework will * work like this. It reads the directory to create the log files from * the framework logging configuration <logging-config> and creates a directory * with the "job-name" and create the log files for each run. So, the format * will be * <br><br> * <directory-defined-in-config>/job-name/jobname_with_timestamp.log * <br><br> * </p> * <p> * If job developer would like to override this logging mechanism, they can * define their logging configuration in the element <job-logging-config> in * batch job configuration file or defining entries in job_logging_config table. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public class LoggingManager { /** * Framework configuration file which is batch_framework.log. */ public static final String FRAMEWORK_LOGGING_FILE = "batch_framework.log"; /** * Standard pattern expression used for all the log files. */ public static final String DEFAULT_MESSAGE_PATTERN = "%5p [%d{ISO8601}] [%t - %C] %m%n"; /** * Tells whether framework logging has been already initailized or not. */ private static boolean isFrameworkLoggingInitialized=false; /** * Private constructor to make sure LoggingManager will not be instantiated. */ private LoggingManager() { } /** * <p> * This method accepts all the information available from framwork logging configuration * and job logging configuration and loads the required loggers appropriately. * This does the follwing steps. * <ul> * <li>Create the directory <directory name configured in logging config>/jobName * <li>Generates the logging file name jobName_yyyymmdd_hhmmss_ms.log * <li>Creates the Rolling File appender with the above created directory and logging file name. * <li>Remove all the existing appenders from the root logger. * <li>Attaches the above created appender to the root logger and set the log level to the defined in framework configuration. * <li>Access the defined loggers at job level and set the level for those loggers. * </ul> * * @param jobName Name of the job. * @param frameworkLoggingConfig Logging configuration defined at the framework. * @param jobLoggingFramework Logging configuration defined at the job level. * @param loggingInitalizer Main class instance which is authorized to initailze the job logging. * * @throws SecurityException If any class other than Main(framework) tried to initialize the job logging. * @throws ConfigurationException If logging file cannot be created at the configured directory. * </p> */ public static void initializeJobLogging(String jobName, FrameworkLoggingConfig frameworkLoggingConfig,JobLoggingConfig jobLoggingConfig, Main loggingInitalizer) { if(!(loggingInitalizer instanceof Main)) throw new SecurityException("Not authorized to initialize the job logging."); File loggingDirecotry=new File(frameworkLoggingConfig.getJobLoggingDirecotry()+File.separator+jobName); LoggingManager.createDirectory(loggingDirecotry); String completeFileName=loggingDirecotry.getAbsolutePath()+File.separator+ jobName+"_"+new SimpleDateFormat("yyyyMMdd_HHmmss_S").format(Calendar.getInstance().getTime())+".log"; PatternLayout layout=new PatternLayout(LoggingManager.DEFAULT_MESSAGE_PATTERN); RollingFileAppender fileAppender=null; try { fileAppender=new RollingFileAppender(layout,completeFileName); } catch(IOException exception) { exception.printStackTrace(); throw new ConfigurationException(ConfigurationException.LOGGING_CONFIG, exception.getMessage()); } fileAppender.setMaxFileSize("10MB"); fileAppender.activateOptions(); Logger rootLogger=LogManager.getRootLogger(); rootLogger.removeAllAppenders(); rootLogger.addAppender(fileAppender); rootLogger.setLevel(Level.toLevel(frameworkLoggingConfig.getJobLoggingLevel())); if(jobLoggingConfig!=null) { JobLoggingConfig.JobLoggerConfig jobLoggerConfigs[]=jobLoggingConfig.getLoggers(); for(int i=0;i<jobLoggerConfigs.length;i++) { Logger customLogger=Logger.getLogger(jobLoggerConfigs[i].getLoggerName()); if(customLogger!=null) customLogger.setLevel(Level.toLevel(jobLoggerConfigs[i].getLoggerLevel())); } } } /** * Initializes the logging of the framework in the directory defined in framework configuration. * After initialized the job logging framework logging will be send to the job and framwork * log files. * * @param frameworkLoggingConfig Framework logging configuration object. * @param loggingInitalizer Main class instance which is authorized to initailze the logging. * * @throws SecurityException If any class other than Main(framework) tried to initialize the framework logging. * @throws ConfigurationException If logging directory cannot be created. */ public static synchronized void initializeFrameworkLogging(FrameworkLoggingConfig frameworkLoggingConfig, Main loggingInitalizer) { if(!(loggingInitalizer instanceof Main)) throw new SecurityException("Not authorized to initialize the framework logging."); if(!isFrameworkLoggingInitialized) { File loggingDirecotry=new File(frameworkLoggingConfig.getJobLoggingDirecotry()); LoggingManager.createDirectory(loggingDirecotry); String completeFileName=loggingDirecotry.getAbsolutePath()+File.separator+LoggingManager.FRAMEWORK_LOGGING_FILE; PatternLayout layout=new PatternLayout(LoggingManager.DEFAULT_MESSAGE_PATTERN); RollingFileAppender fileAppender=null; try { fileAppender=new RollingFileAppender(layout,completeFileName,true); } catch(IOException exception) { exception.printStackTrace(); throw new ConfigurationException(ConfigurationException.LOGGING_CONFIG, exception.getMessage()); } fileAppender.setMaxFileSize("10MB"); fileAppender.activateOptions(); Logger rootLogger=LogManager.getRootLogger(); rootLogger.removeAllAppenders(); Logger frameworkLogger=Logger.getLogger("org.jmonks.batch.framework"); frameworkLogger.addAppender(fileAppender); frameworkLogger.setAdditivity(true); frameworkLogger.setLevel(Level.toLevel(frameworkLoggingConfig.getFrameworkLoggingLevel())); isFrameworkLoggingInitialized=true; } else { /** * Framework logging has been already initialized. Ignore this call. */ } } /** * Method to make sure given file entry exist. If it doenst exist, it will tries to create that * entry. */ private static void createDirectory(File loggingDirecotry) { if(loggingDirecotry.exists() && loggingDirecotry.isFile()) throw new ConfigurationException(ConfigurationException.LOGGING_CONFIG, "Logging directory " + loggingDirecotry.getAbsolutePath() + " defined in framework configuration is a file."); else if(!loggingDirecotry.exists()) { boolean created=loggingDirecotry.mkdirs(); if(!created) throw new ConfigurationException(ConfigurationException.LOGGING_CONFIG, "Logging directory " + loggingDirecotry.getAbsolutePath() + " defined in framework configuration cannot be created."); } } /** * Gets the log level of the given logger name. * * @param loggerName Name of the logger wants to find the log level. * * @return Returns the log level, null, if the given logger could not be found. */ public static Level getLogLevel(String loggerName) { Logger logger=Logger.getLogger(loggerName); if(logger==null) return null; else return logger.getLevel(); } /** * Changes the log level for the requested logger name with the given log level. * * @param loggerName Logger name needs to be modified. * @param newLogLevel new logging level. * * @return Returns true, if log level could be changed, false, otherwise. */ public static boolean changeLogLevel(String loggerName,Level newLogLevel) { boolean logLevelChanged=false; Logger logger=Logger.getLogger(loggerName); if(logger!=null) { logger.setLevel(newLogLevel); logLevelChanged=true; } return logLevelChanged; } } --- NEW FILE: Repository.java --- package org.jmonks.batch.framework; import java.util.Map; import org.apache.log4j.Logger; import org.jmonks.batch.framework.config.ConfigurationException; import org.jmonks.batch.framework.config.FrameworkConfig.RepositoryConfig; /** * <p> * Repository class provides utility methods to access and use the repository maintained * by the framework. The repository could be any data store from files to databases, useful * to save and retrieve the data. So, there could be different implementations available of * this Repository class. Framework configuration defines which implementation should * be used for the framework. * </p> * <p> * This povides utility methods to log the job statistics and transfer data between the jobs * and register & unregister management and monitoring information. Framework creates the * repository at the startup and provides this reference through the JobContext to all the jobs. * When the repository get created, it will be associated with the job beign run and all the * operations will be performed with respect to that job only. The job being run will be taken * as source job in all the operations. * </p> * <p> * Default framework configuration uses Db4o database as repository for its simplicity. * There is a JdbcRepository implementation by using which we can use any database that * can be used JDBC can be configured to use as repository. If anyone wish to use tools * provided to manage and monitor the applications, consider of using the JdbcRepository * implementation. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public abstract class Repository { private static Logger logger=Logger.getLogger(Repository.class); /** * Variable to hold the singleton instance of repository implementation * defined in framework configuration. */ private static Repository repository=null; /** * Name of the job associated with the repository. */ protected String jobName=null; /** * <p> * Method to initialize the repository implementation by using the properties * defined in the framework configuration. This method will be called immediately * after instantiating the implementation class. * </p> * * @param configProps Configuration properties defined in <repository-config> element * in framework configuration file. * * @throws ConfigurationException If required configuration properties are missing or the values * are invalid. */ protected abstract void init(Map configProps); /** * <p> * Factory method creates the repository instance based on the given repository configuration and associate * this repository instance with the given job. So, all the repository operations performed * using this repository instance will be associated with that job and taken that job as source * job in all operations. This method will be called by the framework to create the repository and * places the reference in JobContext object. * </p> * * @param jobName Name of the job this repository will be associated with. * @param repositoryConfig Repository configuration defined in framework configuration. * @param repositoryCreator Creator of the repository. This is is restrict only framework can instantiate the repository. * * @throws SecurityException If an attempt is made to create the repository by other than the Main class(framework). * @throws IllegalArgumentException If jobName is null to create the repository instance. * @throws ConfigurationException If required properties are missing in the repository configuration or the values are invalid. */ public static Repository createRepository(String jobName, RepositoryConfig repositoryConfig, Main repositoryCreator) { logger.trace("Entering createRepository"); if(!(repositoryCreator instanceof Main)) throw new SecurityException("Not authorized to create the repository."); if(repositoryConfig==null) throw new ConfigurationException(ConfigurationException.REPOSITORY_CONFIG, "Repository configuration is not defined in framework configuration"); if(jobName==null || "".equals(jobName)) throw new IllegalArgumentException("Job Name cannot be null or empty to create repository instance."); String repositoryClassName=repositoryConfig.getRepositoryClassName(); if(repositoryClassName==null || "".equals(repositoryClassName)) throw new ConfigurationException(ConfigurationException.REPOSITORY_CONFIG, "Repository class name is not defined in repository configuration"); logger.debug("repository class name = " + repositoryClassName); try { repository=(Repository)Class.forName(repositoryClassName).newInstance(); repository.jobName=jobName; repository.init(repositoryConfig.getRepositoryConfigProperties()); logger.debug("created the repository implemenation class"); } catch(ClassNotFoundException exception) { exception.printStackTrace(); logger.error(exception.getMessage(),exception); throw new ConfigurationException(ConfigurationException.REPOSITORY_CONFIG, exception.getMessage()); } catch(InstantiationException exception) { exception.printStackTrace(); logger.error(exception.getMessage(),exception); throw new ConfigurationException(ConfigurationException.REPOSITORY_CONFIG, exception.getMessage()); } catch(IllegalAccessException exception) { exception.printStackTrace(); logger.error(exception.getMessage(),exception); throw new ConfigurationException(ConfigurationException.REPOSITORY_CONFIG, exception.getMessage()); } logger.trace("Exiting createRepository " + (repository!=null)); return repository; } /** * <p> * Data will be send to the specified next job and will be identified with the * given identifier. By using different identifiers, multiple data objects * can be send to the same next job. Next job should use the data identifier * and this (source) job name to read the data. If there is any data with this * identifier from this job to the next job, it will be overriden. * </p> * * @param dataIdentifier Identifier to be used to exchange the data between two jobs. * @param nextJobName Name of the next job this data to be send. * @param data Data that needs to be send as the object. * * @return Returns true, if it could save the data to be send to the next job. * * @throws IllegalArgumentException If any one of the incoming values are null. */ public abstract boolean sendDataToNextJob(String dataIdentifier, String nextJobName, final Object data); /** * Gets the data that has been sent by the previous job with the given data identifier. * * @param dataIdentifier Identifier tied to the data that has been sent. * @param previousJobName Name of the previous job sent the data to this job. * * @return Returns the data, null, if it couldnt find any data from the previous job with that identifier. * * @throws IllegalArgumentException If any one of the input values are null. */ public abstract Object getDataFromPreviousJob(String dataIdentifier, String previousJobName); /** * <p> * This method will clear all the data that has been sent by this job to all the next jobs. * </p> * * @return Returns true if it could clear all the data, false, otherwise. * */ public abstract boolean clearDataTransferredFromThisJob(); /** * <p> * Registers the given job management and monitoring information to this job. * If there is any information already associated with this job, it * will be overriden. * </p> * * @param registrationInfo Information to be associated with the job. * * @return Return true, if it could assosciate this information, false, otherwise. * * @throws IllegalArgumentException If input argument registration information * value is null. */ public abstract boolean registerJobMgmtMntrInfo(final Object registrationInfo); /** * Unregisters the job management and monitoring information assosciated with this job. * * @return Return true, it it could unregister the information, false, otherwise. */ public abstract boolean unregisterJobMgmtMntrInfo(); /** * <p> * Logs the job statistics given in the form of JobStatistics object * in the repository for further use/references. * </p> * @param statistics Job Statistics object which holds all the statistics related to that job. * * @return Returns true if statistics can be logged into repository, false, otherwise. * * @throws IllegalArgumentException If input argument job statistics is null. */ public abstract boolean logStatistics(final JobStatistics statistics); } --- NEW FILE: Main.java --- package org.jmonks.batch.framework; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.jmonks.batch.framework.config.ConfigurationException; import org.jmonks.batch.framework.config.FrameworkConfig; import org.jmonks.batch.framework.config.JobConfig; import org.jmonks.batch.framework.config.JobConfigFactory; import org.jmonks.batch.framework.controller.JobController; import org.jmonks.batch.framework.management.JobManagementAgent; /** * <p> * Main is the entry point to the batch framework. This provides * the methods to accept the information to identify the job and kicks off the job. * The framework can be executed either through command line as an independent * program or from any other java program. The information on how to kickoff using * these two methods available in {@link #main(String[])} and {@link #process(java.util.Map)} * methods of this class. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public final class Main { private static Logger logger=Logger.getLogger(Main.class); /** * Name of the parameter key holds the job name in configuration map which * is <code>job-name</code>. */ public static final String JOB_NAME_KEY_NAME = "job-name"; /** * Restrict the temptation of creating the instance of Main to create * any resources in the framework. */ private Main() { } /** * <p> * This method provides the interface to execute the job from another java * program. This accepts the job name and additional configuration information * relate to this job as a key value pairs in the map. Among these entries * in the map, there should be a <i>job-name</i> parameter key available to * identify the job to be executed. * <br><br> * <pre> * Map configMap=new HashMap(); * configMap.put("job-name","process_file_abc"); * configMap.put("config-name1","config-value1"); * configMap.put("config-name2","config-value2"); * * ErrorCode exitCode=Main.process(configMap); * System.out.println("Job exited with return code : " + exitCode.getCode()); * </pre> * <br><br> * Whatever the configuration passed here can be retrived from the JobContext * instance passed to all the jobs either through initialize methods or process * methods. * </p> * <br> * * @param configMap Map object consist of all the properties needed to kick off this batch job. * * @return Returns ErrorCode provides the status of the batch job. * * @throws IllegalArgumentException If input configMap is null. */ public static ErrorCode process(Map configMap) { if(configMap==null) throw new IllegalArgumentException("Argument configMap cannot be null."); ErrorCode returnCode=ErrorCode.JOB_COMPLETED_SUCCESSFULLY; JobManagementAgent jobManagementAgent=null; JobContext jobContext=null; Main frameworkCreator=new Main(); String jobName=null; try { /** * Get the framework configuration and initialize the framework logging. */ logger.debug("Retrieving the framework configuration"); FrameworkConfig frameworkConfig=FrameworkConfig.getInstance(); logger.debug("Initializing the framework logging"); LoggingManager.initializeFrameworkLogging( frameworkConfig.getFrameworkLoggingConfig(), frameworkCreator); /** * Get the job name from given configMap and start execution. */ logger.error("Received configuration map = " + configMap); jobName=(String)configMap.get(Main.JOB_NAME_KEY_NAME); logger.info("Job to be invoked = " + jobName); if(jobName!=null && !"".equals(jobName.trim())) { /** * Get the job configuration from the configuration factory. */ logger.debug("Retrieving the configuration factory"); JobConfigFactory jobConfigFactory=JobConfigFactory. getJobConfigFactory(frameworkConfig.getJobConfigFactoryConfig()); logger.debug("Retrieving the job configuration"); JobConfig jobConfig=jobConfigFactory.getJobConfig(jobName); if(jobConfig!=null) { /** * Initialize the job logging and kick off the controller after * registering it to the management agent. */ logger.debug("Initializing the job logging"); LoggingManager.initializeJobLogging(jobName,frameworkConfig. getFrameworkLoggingConfig(), jobConfig.getJobLoggingConfig(), frameworkCreator); logger.debug("Create the job context"); jobContext=createJobContext(jobConfig, configMap, frameworkCreator); logger.debug("Creating the job controller"); JobController jobController=JobController.getJobController(jobContext); logger.debug("Retrieving the management agent"); jobManagementAgent=JobManagementAgent.getJobManagementAgent(); logger.debug("Registering the controller with the management agent"); jobManagementAgent.start(jobContext, jobController, frameworkCreator); logger.error("Kicking off the controller"); returnCode=jobController.process(); /** * Save the statistics into repository */ JobStatistics jobStatistics=jobController.getJobStatistics(); logger.error(jobStatistics); jobContext.getRepository().logStatistics(jobStatistics); } else { logger.fatal("Unable to find the job configuration for the given job = " + jobName + " in the configured job configuration factory = " + jobConfigFactory.toString()); returnCode=ErrorCode.JOB_IS_NOT_CONFIGURED; } } else { logger.fatal("job-name parameter cannot be found in the configuration to kick " + "off the job . Received configuration = " + configMap); returnCode=ErrorCode.JOB_INVOKATION_CONFIGURAION_ERROR; } } catch(ConfigurationException exception) { exception.printStackTrace(); logger.fatal("Configuration Exception in the component " + exception.getExceptionComponent() + " while processing the job = " + jobName + " Message = " + exception.getMessage(),exception); returnCode=exception.getErrorCode(); } catch(Throwable exception) { exception.printStackTrace(); logger.fatal("Exception while processing the job = " + jobName + " Message = "+ exception.getMessage(),exception); returnCode=ErrorCode.JOB_COMPLETED_WITH_ERRORS.appendMessage(exception.getMessage()); } finally { logger.debug("Unregistering the controller with the management agent"); if(jobManagementAgent!=null && jobManagementAgent.isRunning()) jobManagementAgent.stop(jobContext, returnCode, frameworkCreator); } logger.error("Exiting process = " + returnCode); return returnCode; } /** * <p> * This method provides the interface to execute the jobs from command line. * This accepts the job name and additional configuration information related * to this job as a command line parameters. Each parameter passed through * command line should be in the format <i>name=value</i>. Among these, * <i>job-name=process_file_abc</i> property should exist to identify the job * to kick off. The ErrorCode's code value will be returned as exit code. * </p> * <p> * The format to invoke the job using this interface is as follows. <br> * java org.jmonks.batch.framework.Main job-name=process_file_abc config-name1=config-value1 config-name2=config-value2 * <br><br> * Whatever the configuration paremters passed here can be retrieved using * the JobContext reference passed to all the jobs either using their initialize * methods or process methods. * </p> * * @param args Configuration details in command line params as name=value format */ public static void main(String args[]) { ErrorCode exitCode=ErrorCode.JOB_COMPLETED_SUCCESSFULLY; Main frameworkCreator=new Main(); try { /** * Get the framework configuration and initialize the framework logging. */ logger.debug("Retrieving the framework configuration"); FrameworkConfig frameworkConfig=FrameworkConfig.getInstance(); logger.debug("Initializing the framework logging"); LoggingManager.initializeFrameworkLogging(frameworkConfig. getFrameworkLoggingConfig(), frameworkCreator); /** * Translate the command line parameters into the configuration map. */ logger.info("Job processing has been started"); Map configMap=new HashMap(); for(int i=0;i<args.length;i++) { int index=args[i].indexOf("="); if(index>1) { configMap.put(args[i].substring(0, index), args[i].substring(index+1)); logger.info("Loaded the argument = " + args[i] + " into configuration map."); } else logger.info("Not loading the argument = " + args[i] + " into configuration map. " + "It is not following the name=value format."); } /** * Kick off the process by passing configuration map. */ exitCode=Main.process(configMap); } catch(ConfigurationException exception) { exception.printStackTrace(); logger.fatal("Configuration Exception in the component " + exception.getExceptionComponent() + " while processing the job. Message = " + exception.getMessage(),exception); exitCode=exception.getErrorCode(); } catch(Throwable exception) { exception.printStackTrace(); logger.fatal("Exception while processing the job. Message = "+ exception.getMessage(),exception); exitCode=ErrorCode.JOB_COMPLETED_WITH_ERRORS.appendMessage(exception.getMessage()); } logger.error("Job finishing with the exit code = " + exitCode.toString()); System.exit(exitCode.getCode()); } /** * Creates the map to be passed to create the JobContext and passes it to the * JobContext and returns the created JobContext object. * * @param jobConfig Job configuration object. * @param invokeConfig Configuration provided at invocation time. * @param frameworkCreator Authorized class to the create the job context. * * @return Returns the JobContext reference. */ private static JobContext createJobContext(JobConfig jobConfig, Map invokeConfig, Main frameworkCreator) { /** * Create the context params map to create the JobContext instance. */ Map contextParams=new HashMap(); contextParams.put(JobContext.CONTEXT_PARAM_JOB_CONFIG, jobConfig); contextParams.put(JobContext.CONTEXT_PARAM_JOB_INVOKE_CONFIG, invokeConfig); Repository repository=Repository.createRepository(jobConfig.getJobName(), FrameworkConfig.getInstance().getRepositoryConfig(), frameworkCreator); contextParams.put(JobContext.CONTEXT_PARAM_REPOSITORY, repository); /** * Create the JobContext and return it. */ JobContext jobContext=new JobContext(contextParams, frameworkCreator); return jobContext; } } --- NEW FILE: ErrorCode.java --- package org.jmonks.batch.framework; /** * <p> * The ErrorCode represents the error condition that can generate in the system. * It consists of the code which uniquely identifies the ErrorCode and message * which explains the error in the system. This is also used to represent the status code * for any processor/controller/job. This provides the flexibility to create * new custom ErrorCodes and append the message to the existing ErrorCode. * Codes ranging from 0 to 100 are reserved for framework purposes. Use the codes * above 100 to create the custom error codes. * </p> * * @author Suresh Pragada * @version 1.0 * @since 1.0 */ public final class ErrorCode { /** * Code represents the error. */ private int code; /** * Message illustrates the code. */ private String message=null; /** * <p> * Private constructor to make sure no instances of ErrorCode will be created * from outside of this class and it is not extensible. * </p> * * @param code Code represents the error. * @param errorMsg Message explains the failure or success reason. */ private ErrorCode(int code, String errorMsg) { this.code=code; this.message=errorMsg; } /** * Returns the error code represents the error. * * @return Returns the error code represents the error. */ public int getCode() { return this.code; } /** * Returns the error message illustrates the exit code. * * @return Returns the error message. */ public String getMessage() { return this.message; } /** * Creates a new ErrorCode object with the same error code and appends the given * message to the existing message and returns new ErrorCode. * * @param messageToBeAppended Message that needs to be appended to the existing message. * * @return Returns a new error code contains the same error code and appended message. */ public ErrorCode appendMessage(String messageToBeAppended) { return new ErrorCode(this.code, this.message+" " + messageToBeAppended); } /** * Creates a new error code instance by accepting the code and message. The newMessage * should not be null or empty message. * * @param newCode Code to be used to construct the ErrorCode. * @param newMessage Mesage to be used to construct the ErrorCode. * * @throws java.lang.IllegalArgumentException If given message is null or empty. */ public static ErrorCode createErrorCode(int newCode, String newMessage) { if(newMessage!=null && !"".equals(newMessage.trim())) return new ErrorCode(newCode,newMessage); else throw new IllegalArgumentException("Message to create new ErrorCode should not be null or empty."); } /** * Equality will be based on the code the two ErrorCodes contains. * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object errorCode) { return (errorCode!=null) && (this.getClass()==errorCode.getClass()) && (this.code==((ErrorCode)errorCode).getCode()); } /** * Code represented by ErrorCode will be returned as a hash code. * * @see java.lang.Object#hashCode() */ public int hashCode() { return this.code; } /** * <p> * Returns the string representation of ErrorCode class in the format * <br> {ErrorCode [code = value] [message = value]} * </p> * * @return Returns the string representation of ErrorCode. */ public String toString() { StringBuffer stringValue=new StringBuffer("{ErrorCode "); stringValue.append("[code = " + this.code + "]"); stringValue.append("[message = " + this.message + "]"); stringValue.append("}"); return stringValue.toString(); } /** * Represents job got completed successfully. Error code is 0. */ public static final ErrorCode JOB_COMPLETED_SUCCESSFULLY = new ErrorCode(0,"Job completed successfully."); /** * Represents job got completed with errors. This represents the partial success. Error code is 1. */ public static final ErrorCode JOB_COMPLETED_WITH_ERRORS = new ErrorCode(1, "Job completed with some errors."); /** * Represents the configuration error used to invoke the job. Error code is 10. */ public static final ErrorCode JOB_INVOKATION_CONFIGURAION_ERROR = new ErrorCode(10,"Error in configuraion passed to invoke job."); /** * Represents the framework configuration error. Error code is 11. */ public static final ErrorCode FRAMEWORK_CONFIGURATION_ERROR = new ErrorCode(11,"Error while accessing or parsing the framework configuration file."); /** * Represents the job config factory configuration error. Error code is 12. */ public static final ErrorCode JOB_CONFIG_FACTORY_CONFIGURATION_ERROR = new ErrorCode(12,"Job configuration factory cannot be created by the given factory configuration."); /** * Represents the job configuration error. Error code is 13. */ public static final ErrorCode JOB_CONFIGURATION_ERROR = new ErrorCode(13,"Error while loading the job configuration from the defined factory."); /** * Represents the job is not configured error. Error code is 14. */ public static final ErrorCode JOB_IS_NOT_CONFIGURED = new ErrorCode(14,"Job is not configured"); /** * Represents the job controller configuration error. Error code is 15. */ public static final ErrorCode JOB_CONTROLLER_CONFIGURATION_ERROR = new ErrorCode(15,"Job controller configuration is not defined properly."); /** * Represents the logging configuration error. Error code is 16. */ public static final ErrorCode JOB_LOGGING_CONFIGURATION_ERROR = new ErrorCode(16,"Job logging configuration is not defined properly."); /** * Represents the repository configuration error. Error code is 17. */ public static final ErrorCode JOB_REPOSITORY_CONFIGURATION_ERROR = new ErrorCode(17,"Repository configuration in framework configuration is not defined properly."); /** * Represents the connector configuration error. Error code is 18. */ public static final ErrorCode JOB_CONNECTOR_CONFIGURATION_ERROR = new ErrorCode(18,"Repository configuration in framework configuration is not defined properly."); /** * Represents the unknown configuration error. Error code is 19. */ public static final ErrorCode UNKNOWN_CONFIGURATION_ERROR = new ErrorCode(19,"Configuration error related to unknown component."); /** * Represents error because of the exception in basic job processor. Error code is 20. */ public static final ErrorCode BASIC_JOB_PROCESSOR_EXCEPTION = new ErrorCode(20,"Basic Job Controller caught exception while executing process method on basic job processor."); /** * Represents error because of the exception in pool job loader. Error code is 21. */ public static final ErrorCode POOL_JOB_LOADER_EXCEPTION = new ErrorCode(21,"Exception while executing the loader to load the pool."); /** * Represents error because of the exception in pool job processor. Error code is 22. */ public static final ErrorCode POOL_JOB_PROCESSOR_EXCEPTION = new ErrorCode(22,"Exception while executing the processor to process the pool."); } |