To fully integrate Spine with your web application, you will need to perform the activities defined below.

  1. Initialization
  2. Configuration and Implementation
  3. Additional Libraries

>
Initialization

To use spine with your application, you will need to  initialize the spine engines  core variables. This can  be done by:

  1. Ensure the spine libraries packaged in /path_to_installion/lib/ directory of your  system are placed  in your  /WEB_INF/lib directory
  2. Edit the spine-init.xml file, this contains the spine default variables and other variables may need to be defined by the user
  3. You may wish to add custom variables which need initialization in your custom application. This can be added to the spine-init.xml file.Specifically you will need to provide custom SpinePlugin(s) for initialization purposes which must also be defined in the spine-init.xml file.
  4. You may also define datasources in use by your application in the spine-init.xml file if you wish. (this may require writing a DataSourceBuilder if none is provided).Alternatively you can use the DefaultDataSourceBuilder which requires that you specify some/all of the property names and values required to initialize your DataSource.
  5. Edit your servlet configuration to add the Spine Servlet if wishing to use the SpineServlet. Note that the function of SpineServlet is to initialize the framework with the default variables.
  6. If using a custom servlet, you should:

    1. Ensure the steps below are implemented in the init method of your custom Servlet.
    2. Add an <init-param> tag to your custom Servlet using the following values

      <init-param>
      <param-name>startConfigFile</param-name>
      <param-value>path/to/spine-init.xml</param-value>
      </init-param
      >

    3. Create an instance of ConfigReader
    4. Call ConfigReader.createConfig(String), passing it the full path to the spine-init.xml file.
    5. The map obtained from ConfigReader.createConfig(String) should then be passed to the instance of ApplicationConfiguration

  7. If running a custom application, implement steps (iii - v) above.
  8. if using a servlet, start your application server or if running an application start the application.


 
>
Configuration and Implementation
To configure and run a Spine driven process you should perform the steps below:

  1. Create a process flow for each request set you wish to service by:

    • Defining the process flow in configuration.

    • Create the classes needed to service the process flow. You will usually be creating a BusinessDelegate and a DataAccessObject, for more sophisticated process flows, you may need to create a ViewProcessor or MultiViewProcessor and more than one BusinessDelegate.

    • Ensure you application follows the  spine paradigm of  keeping business logic and rules  in the business layer and  data operations in the data layer.


  2. To define a process flow in configuration, you will usually be using one of the following:

    1. Simple Process Flow

    2. Multidelegate Process Flow

    3. MultiView Processor Flow

    Simple Process Flow


    A simple process flow will need to have a definition in configuration. An example is given below:

    <processor name="simpleProcessor">
            <processorClass>
                com.zphinx.spine.core.viewprocessors.DefaultViewProcessor
            </processorClass>
            <delegate>

                <subclass>
                    com.zphinx.spine.examples.simpledelegate.SimpleDelegate
                </subclass>
                <dataAccessObject>
                    <className>
                        com.zphinx.spine.examples.dao.ExampleFileDAO
                    </className>
                    <proxyIndex>1</proxyIndex>
                </dataAccessObject>
            </delegate>

        </processor>

    This example implies that the process flow will be from the ViewProcessor known as DefaultViewProcessor to ExampleFileDAO. As DefaultViewProcessor is provided by Spine Framework, all the client developer will be creating are the two classes known as SimpleDelegate and ExampleFileDAO.

    In Spine paradigm, the class SimpleDelegate will contain all the business methods and rules while ExampleFileDAO will provide the means to access and retrieve data from the data store.
    The client developer will of course need to access this configuration in his application or MVC be invoking the call:

    ViewProcessor vp =  ViewProcessorFactory.getInstance().createProcessor("SimpleProcessor");

    This call effectively creates the ViewProcessor and initializes it for running the process flow. To complete the process flow, the developer will need to create a DataTransferObject or alternatively wrap a custom object in a DTOWrapper to ensure the system is capable of running the process. The example shown below uses a DataTransportBean which is a DataTransferObject available within the API.

    ViewProcessor vp =  ViewProcessorFactory.getInstance().createProcessor("SimpleProcessor");

    DataTransportBean dto = new DataTransportBean("transporter",new Object());

    dto.setId(Universal.getRandom(7));

    String daoPath = "/home/user/spineApp/somePropertiesFile.properties";

    String[] proxyInit = new String[]{daoPath,true};

    ResultObject result = vp.processData(dto,proxyInit);

    The ResultObject obtained from the process can then be queried for the results of the process invocation. The ResultObject can contain any arbitary  object as a returned object or a collection. i.e

     Identifier id =  (Identifier) resultObject.getObj();
    String firstName =  id.getFirstName();
    String userName = id.getUserName();
    String password =  id.getAccountSecrets().getPassword1();

    It can also have localized messages or errors sent to the invoking Object which can be obtained as a collection or as a line delimited string. E.g

    String s = result.getDisplayMessages(locale).getAllErrorString();
                    System.err.println(s);

    To get only specific types of error identified by a key, the client programmer can invoke the following:

    String key = "validationErrors";
    DisplayError[] errors = result.getDisplayMessages().getErrors(key);
    if(errors.length > 0){
        System.err.println("There has been a validation error!!");
    }


    As long as business logic is kept in the BusinessDelegate and data calls are in the DAO, Spine will ensure your process flow is fully transposable.

    Multi Delegate Process Flow


    The multi delegate process flow is only slightly different from the simple process flow. It allows the developer to use more than one delegate in the configuration, these delegates are then called by the framework in the order they are declared in configuration. A multi delegate processor example configuration is shown below:

        <!--// The MultiDelegateProcessor:- An example simple processor which uses multiple delegates and multiple DAOs in the order in which they are declared  //-->

        <processor name="MultiDelegateProcessor">
            <processorClass>
                com.zphinx.spine.core.viewprocessors.DefaultViewProcessor
            </processorClass>
            <delegate>

                <subclass>
                    com.zphinx.spine.examples.multipledelegates.LogonDelegate
                </subclass>
                <dataAccessObject>
                    <className>
                        com.zphinx.spine.examples.dao.LogonDAO
                    </className>
                    <proxyIndex>2</proxyIndex>
                </dataAccessObject>
            </delegate>
            <delegate>

                <subclass>
                    com.zphinx.spine.examples.multipledelegates.PendingJobsDelegate
                </subclass>
                <dataAccessObject>
                    <className>
                        com.zphinx.spine.examples.dao.PendingJobsDAO
                    </className>
                    <proxyIndex>2</proxyIndex>
                </dataAccessObject>
            </delegate>

    <delegate>

                <subclass>
                    com.zphinx.spine.examples.multipledelegates.InboxDelegate
                </subclass>
                <dataAccessObject>
                    <className>
                        com.zphinx.spine.examples.dao.InboxDAO
                    </className>
                    <proxyIndex>2</proxyIndex>
                </dataAccessObject>
            </delegate>

        </processor>



    This example implies that the stated process flow will require the following objects:

    1. DefaultViewProcessor
    2. LogonDelegate
    3. LogonDAO
    4. PendingJobsDelegate
    5. PendingJobsDAO
    6. InboxDelegate
    7. InboxDAO


    In this example, we depict the process of an administrator logging into an application, which on a successful logon will display two tables, one a list of pending jobs and the other an internal inbox of customer emails. 

    In reality what the framework will do is to call the process flows in the order shown and on success make available all the objects needed to populate the page where the admistrator is logged into.

    This can be shown by the example below:

    DefaultViewProcessor dvp =  (DefaultViewProcessor) ViewProcessorFactory.getInstance().createProcessor("MultiDelegateProcessor");

    DataTransportBean dto = new DataTransportBean("joebloggs","password");

    dto.setId(Universal.getRandom(7));

    DataSource dataSource = DataSourceServiceLocator.getInstance().getDataSource();
    User user = null;
    List pendingJobsList = null;
    List inboxList = null;

    ResultObject result = dvp.processData(dto,dataSource);

    if(!result.isErrorFlag){
         //     gets the logged on user's details .. . .

                     user = (User) result.getObj();

                     String id = user.getId();

                    DataTransportBean pendingDto = new DataTransportBean("pending",new Boolean(true));
                    pendingDto.setId(id);
                    result = dvp.processData(dto,dataSource);
                    if(!result.isErrorFlag){
        
                                pendingJobsList = (List)  result.getObj();

                                DataTransportBean inboxDto = new DataTransportBean("metadata",null);
                                inboxDto.setId(id);
                                result = dvp.processData(dto,dataSource);
                                if(!result.isErrorFlag){
        
                                            inboxList = (List)  result.getObj();
                                }
                                else{

                                            System.out.println("Error :"+
    result.getDisplayMessages(locale).getAllErrorString());
                                }
                     }
                     else{

                                System.out.println("Error :"+
    result.getDisplayMessages(locale).getAllErrorString());
                      }
                  
    }
    else{
                System.out.println("Error :"+result.getDisplayMessages(locale).getAllErrorString()
    );
    }

    The Objects retrieved from the invocation will be packaged and persisted in the users session or request as needed.
    Should an error occur, it can be retrieved from the ResultObject and sent to the user in the presentation tier as demanded.

    The client developer should note the calls made by the ViewProcessor, the code calls ViewProcessor.processData(DataTransferObject,Object):ResultObject multiple times but does not specify which delegate or DAO to use. This fact is automatically derived from the order in which delegates are declared in the spine.xml file.


    Multi View Process Flow


    Multi view process flow possesses the ability to run several delegates and multiple DAOs with the same configuration. It is the most versatile ViewProcessor available and the framework provides an example ViewProcessor called MultiViewProcessor which is useful for handling invocations derived from this type of configuration.
     
    It also declares an attached object (a Builder) which is useful for running or creating other objects whilst processing, an example configuration is shown below:

        <!--// The MultiViewProcessor:- An example  multiview processor using different DataAccessObjects  //-->
        <processor name="MultiViewProcessor">
            <processorClass>
                com.zphinx.spine.examples.multiview.ExtendedMultiViewProcessor
            </processorClass>
            <multiDelegate>

                <subclass>
                    com.zphinx.spine.examples.multiview.MultiViewExampleDelegate
                </subclass>

                <managedObject>

                    <objectClass>
                        com.zphinx.spine.examples.beans.SpineBean1
                    </objectClass>

                    <dataAccessObject>
                        <className>
                            com.zphinx.spine.examples.dao.SpineBean1DAO
                        </className>
                        <proxyIndex>1</proxyIndex>

                    </dataAccessObject>
                    <pageIndex>1</pageIndex>
                </managedObject>

                <managedObject>

                    <objectClass>
                        com.zphinx.spine.examples.beans.SpineBean2
                    </objectClass>
                    <dataAccessObject>
                        <className>
                            com.zphinx.spine.examples.dao.SpineBean2DAO
                        </className>
                        <proxyIndex>2</proxyIndex>

                    </dataAccessObject>
                    <pageIndex>2</pageIndex>
                </managedObject>

                <managedObject>

                    <objectClass>
                        com.zphinx.spine.examples.beans.SpineBean3
                    </objectClass>
                    <dataAccessObject>
                        <className>
                            com.zphinx.spine.examples.dao.SpineBean3DAO
                        </className>
                        <proxyIndex>2</proxyIndex>

                    </dataAccessObject>
                    <pageIndex>3</pageIndex>
                </managedObject>

                <builder>
                    com.zphinx.spine.examples.multiview.ExampleBuilder
                </builder>
            </multiDelegate>
        </processor>


  3. The configuration above declares a single delegate and several managedObjects which are expected to be made available by the builder when needed.
    To use a configuration like that shown above, the code will instantiate the ViewProcessor from the ViewProcessorFactory, the developer can then create a SpineBean from a builder specified in configuration and subsequently invoke the process flow. eg:

    try{
    DataSource dataSource = DataSourceServiceLocator.getInstance().getDataSource();
    MultiViewProcessor mvp = ViewProcessorFactory.getInstance().createProcessor( "MultiViewProcessor");
    SomeBuilder builder = mvp.findBuilder("MultiViewProcessor","MultiViewTestDelegate");

    //create a bean for your use
    SpineBean2 sp2 = builder.createBean( 2);
    //popuate the bean's methods
    sp2.setModifiedDate(new Date());

    //to invoke a process and run methods in the business delegate
    final ResultObject resultObject = mvp.processData(sp2,dataSource,null,4,-1);
    //process the ResultObject as in the above example

    }
    catch(Exception e){
      e.printStackTrace();
    }


    It can be seen from the example above that passing a pageNumber/pageIndex to the  MultiViewProcessor will  indicate to the  MultiViewProcessor which object is been processed and which DataAccessObject should be invoked for the particular process flow.

    Users should note that in certain instances (eg invoking the builder) there  is a need to pass the name of the BusinessDelegate in use to the stated method. This is because a MultiViewProcessor is capable of using more than one BusinessDelegate to service it's request.


  4. Ensure you write a suitable test for the process flow, there are some examples provided in the /test-src/ directory of the distribution

 
>
Additional Libraries

You may need to add additional libraries to the application. This can usually be deployed in your /path_to_application_context/WEB_INF/lib/. if running a  servlet, otherwise the libraries should be placed in a classpath defined and recognised by your application.

Please ensure that libraries are placed in a path recognized by the spine classes, preferably in the same directory as where the spine.jar file
resides.You may also deploy any other libaries in this directory to ensure that you application  is able to access the required class libraries.


<< Back    |     Home    |     Index    |     Forward >>

Copyright © 2008 Zphinx Software Solutions , all rights reserved