# Customizations

The standard processing and script operations of the Deployment Template are sufficient to support the operational requirements of most projects. Some applications require customization to enable custom processing steps, script behavior, or even directory structure changes.

Developers are encouraged to use the template as a starting point for customization. The scripts and modules provided with the template incorporate Oracle's best practice recommendations for synchronization, archiving, and update processing. The Deployment Template is intended to provide a set of standards on which development should be founded, while allowing the flexibility to develop custom scripts to meet specific project needs.

The following list describes a number of customization approaches that can be implemented to extend the existing functionality or add new functionality to the template. For further details about configuration and customization in the AppConfig.xml document, refer to Appendix A ("EAC Development Toolkit").

- Configure AppConfig.xml - The simplest form of configuration consists of editing the AppConfig.xml configuration document to change the behavior of components or to add or remove components. This type of configuration includes the addition of removal of Dgraphs to the main cluster or even the creation of additional clusters. In addition, this category includes adjustment of process arguments (for example, adding a Java classpath for the Forge process in order to enable the use of a Java Manipulator), custom properties and directories (for example, changing the number of index archives that are stored on the indexing server).
- Change behavior of existing BeanShell scripts - Scripts are written in the Java scripting language BeanShell. Scripts are defined in the AppConfig.xml document and are interpreted at runtime by the BeanShell interpreter. This allows developers and system administrators to adjust the behavior of the baseline, partial, and configuration update scripts by simply modifying the configuration document. For example, if a deployment uses JDBC to read data into the Forge pipeline instead of using extracted data files, the following changes would be implemented in the BaselineUpdate script:
  1. Remove the line that retrieves data and configuration for Forge: `Forge.getData();`
  2. Insert a new copy command to retrieve configuration for Forge to process:

         ...
         // get Web Studio config, merge with Dev Studio config
         ConfigManager.downloadWsConfig();
         ConfigManager.fetchMergedConfig();

         // fetch extracted data files, run ITL
         srcDir = PathUtils.getAbsolutePath(Forge.getWorkingDir(),
           Forge.getConfigDir()) + "/\\*";
         destDir = PathUtils.getAbsolutePath(Forge.getWorkingDir(),
           Forge.getInputDir());

         dimensionCopy = new CopyUtility(Forge.getAppName(),
           Forge.getEacHost(), Forge.getEacPort(), Forge.isSslEnabled());
         dimensionCopy.init("copy_dimensions", Forge.getHostId(),
           Forge.getHostId(), srcDir, destDir, true);
         dimensionCopy.run();

         Forge.getData();
         Forge.run();
         Dgidx.run();
         ...

  Note that this amended BeanShell script imports two classes from the classpath, references variables that point to elements in the AppConfig.xml document (e.g. Forge, Dgidx) and defines new variables without specifying their type (e.g. srcDir, destDir). Details about BeanShell scripting can be found in Appendix A of this guide.
- Write new BeanShell scripts - Some use cases may call for greater flexibility than can easily be achieved by modifying existing BeanShell scripts. In these cases, writing new BeanShell scripts may accomplish the desired goal. For example, the following BeanShell script extends the previous example by pulling the new functionality into a separate script:

      <script id="CopyConfig">
        <bean-shell-script>
          <![CDATA[

        // fetch extracted data files, run ITL
        srcDir = PathUtils.getAbsolutePath(Forge.getWorkingDir(),
          Forge.getConfigDir()) + "/\\*";
        destDir = PathUtils.getAbsolutePath(Forge.getWorkingDir(),
          Forge.getInputDir());

        dimensionCopy = new CopyUtility(Forge.getAppName(),
          Forge.getEacHost(), Forge.getEacPort(), Forge.isSslEnabled());
        dimensionCopy.init("copy_dimensions", Forge.getHostId(),
          Forge.getHostId(), srcDir, destDir, true);
        dimensionCopy.run();

          ]]>
        </bean-shell-script>
      </script>

  Once the new script is defined, the BaselineUpdate script simplifies to the following:

      ...
      // get Web Studio config, merge with Dev Studio config
      ConfigManager.downloadWsConfig();
      ConfigManager.fetchMergedConfig();

      // fetch extracted data files, run ITL
      CopyConfig.run();
      Forge.getData();
      Forge.run();
      Dgidx.run();
      ...

- Define utilities in AppConfig.xml - A common use case for customization is to add or adjust the functionality of utility invocation. Our previous example demonstrates the need to invoke a new copy utility when the Forge implementation changes. Other common use cases involve invoking a data pre-processing script from the shell and archiving a directory. In order to enable this, the Deployment Template allows utilities to be configured in the AppConfig.xml document. To configure the copy defined above in the document, use the copy element:

      <copy id="CopyConfig" src-host-id="ITLHost" dest-host-id="ITLHost"
        recursive="true">
        <src>./data/complete_index_config/*</src>
        <dest>./data/processing</dest>
      </copy>

  Once configured, this copy utility is invoked using the same command that was previously added to the BaselineUpdate to invoke the custom BeanShell script: `CopyConfig.run();`
- Extend the Java EAC Development Toolkit - In rare cases, developers may need to implement complex custom functionality that would be unwieldy and difficult to maintain if implemented in the AppConfig.xml document. In these cases, developers can extend objects in the toolkit to create new Java objects that implement the desired custom functionality. Staying with the previous example, the developer might implement a custom Forge object to change the behavior of the `getData()` method to simply copy configuration without looking for extracted data files.

      package com.Endeca.soleng.eac.toolkit.component;

      import java.util.logging.Logger;
      import com.Endeca.soleng.eac.toolkit.exception.*;

      public class MyForgeComponent extends ForgeComponent
      {
        private static Logger log =
          Logger.getLogger(MyForgeComponent.class.getName());

        protected void getData() throws AppConfigurationException,
            EacCommunicationException, EacComponentControlException,
            InterruptedException
        {

          // get dimensions for processing
          getConfig();

        }
      }

  Obviously, this trivial customization is too simple to warrant the development of a new class. However, this approach can be used to override the functionality of most methods in the toolkit or to implement new methods.

  In order to use the new functionality, the developer will compile the new class and ensure that it is included on the classpath when invoking scripts. The simplest way to do this is to deploy the compiled .class file to the [appdir]/config/script directory. Once on the classpath, the new component can be loaded in place of the default Forge component by making the following change to the Forge configuration in AppConfig.xml:

      <forge class="com.Endeca.soleng.eac.toolkit.component.MyForgeComponent"
        id="Forge" host-id="ITLHost">
      ...
      </forge>

  Some types of customization will require more complex configuration. Refer to Appendix A ("EAC Development Toolkit") for information about configuring custom Java classes using the Spring Framework namespace in the AppConfig.xml document.