SlideShare a Scribd company logo
GeoBliki
                                                                 Pat Cappelaere
                                                                        pat@geobliki.com
                                                                 Linda Derezinski
                                                                        linda@geobliki.com




And    GeoBPMS                                                    June 7th, 2007
                                           Part I
Business Process Management System For the Enterprise Using Open Source
Components


Targeted Audience: Rails Integrators, Business Process Analysts and OpenWFEru
enthusiasts.

Warning: This is not a Ruby or Rails tutorial. This document assumes that you have a
working knowledge of Ruby and Rails.

BPMS Business Case:

Sophisticated products and/or automation require the definition of service chains (or
workflows) that can involve many participants from humans to web services collaborating in
a seamless manner. These processes need to be managed and defined at the Enterprise level
and fall in a category called: Business Process Management.

This can be fairly complex and expensive. Many acronyms and technologies need to be
mastered. Our goal is to show that we can put together a solid framework based around open
source components and keep it relatively simple and manageable. Let’s walk through an
example.

Scope of this document:

- Step description of all components and tools required for BPMS and integration within
Ruby on Rails.
- Example of a workflow with code snippets.




www.geobliki.com
Introduction:

Service-chains can be defined to sequence and allocate activities or tasks across many
participants using workflows.

First step is to capture and visualize the process. A good picture is worth a thousand words.
So we need to make it look really good!

There are many ways to generate Business Process diagrams. A de-facto notation standard
has been released in Feb 2006 (BPMN1) supported by more than 42 implementations (as of
April 12, 2007). Eclipse is actively working on its own STP BPMN Modeler2. For the time
being, we will be using Business Process Visual Architect3 from Visual Paradigm.

Preflight check-list:
Before getting into the tutorial, check to see that you have everything required.

1) You have Ruby and Rails4 installed. Check that you have at least the following
versions.
     ruby –version
        ruby 1.8.6
     rails –version
       Rails 1.2.3

If you need to install Ruby on Rails:
For Windows, use Instant Rails.
For Mac OS X, use Locomotive.
For Linux, try the Rails LiveCD.

A good development environment on Macintosh is TextMate5 or Eclipse with Ruby RDT6 on
all platforms.

To get rolling with Ruby on Rails: Check this out

2) MySQL7 installed. 4.x distribution or later is fine.
    mysql –version
      mysql Ver 14.12 Distrib 5.0.20a

If you need to install MySQL download


1
  http://www.bpmn.org/
2
  http://www.eclipse.org/stp/bpmn/
3
  http://www.visual-paradigm.com/product/bpva/
4
  http://www.rubyonrails.org/
5
  http://macromates.com/
6
  http://www-128.ibm.com/developerworks/opensource/library/os-rubyeclipse/
7
  http://www.mysql.org

www.geobliki.com
Create a empty Rails application “geobpms”

    rails geobpms
        And make sure it works by testing it – Start the application
    cd geobpms
    ./script/server
        in your favorite browser, go to http://127.0.0.1:3000/

      Double check the environment one more time by selecting the “About your
      application’s environment” link. You should have these or later versions:




www.geobliki.com
Download OpenWFERu
    Go to: http://openwferu.rubyforge.org/

You can get it as a gem, latest stable version or from the svn trunk.
Note: My personal preference is to download the latest version and keep it under control so I
can go back to previous version as necessary (or check what changed between versions).

Install the gem
     gem install -y openwferu
         Successfully installed openwferu-0.9.11
         Installing ri documentation for openwferu-0.9.11...
         Installing RDoc documentation for openwferu-0.9.11...

Copy the gem into your vendor directory. In this case the current version is 0.9.11. From
your geobpms rails project directory
      cp –R /usr/local/lib/ruby/gems/1.8/gems/openwferu-0.9.11 vendor/

Edit geobpms/config/environment.rb to point to the newly installed version of openwferu

Add this text:
   config.load_paths += %W(
        vendor/openwferu-0.9.11/lib
     ).map {|dir| "#{RAILS_ROOT}/#{dir}"}.select { |dir|
   File.directory?(dir) }

Below the commented out config.load_paths line like so:




To change between versions, change the version number on line #25.




www.geobliki.com
Workflow Description:

This workflow example shows the tasking request of the EO-1 satellite by a user who interacts
with the system via XForms. The user enters a tasking request using some input (lat/long…).
The workflow proceeds by calling the Sensor Planning System (SPS) to check for feasibilities.
The user is prompted to select a feasibility and the task is submitted. Eventually, the task is
completed onboard. The data is down-linked to the ground and published by the Sensor
Observation Service (SOS). Finally the user is alerted that data is available via email by the Web
Notification Service (WNS).




Figure 1. “Simple” EO1 Satellite Tasking Workflow


www.geobliki.com
The various participants in this workflows are: XForms, SPS, SOS and WNS. They are
represented as Pools. They perform various tasks for this workflow.

Ideally, we would save this workflow in OpenWFERu XML format (or XPDL 2.0 and then
translate it). This would be a possible outcome:

Create a workflows directory in the public folder and then copy the following into flow.xml.
/rails/public/workflows/flow.xml
<process-definition
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.openwfe.org/flowdef.xsd"
    name="EO1 Simple Tasking Workflow"
    revision="0.1"
    theme="n/a"
    security="restricted" >

     <sequence>
       <set field="msg" value="Workflow has been sequenced" />
       <participant ref="WNS"      task='Email' />

       <participant ref='XForms' task='RequestTasking'    comments='Enter EO-1 Tasking Parameters'
/>

    <participant ref="SPS"       task='GetFeasibilities' timeout="2d"    comments='Check EO-1
Tasking Feasibilities'/>

       <participant ref='XForms' task='SelectFeasibility' comments='Select Desired Feasibility'
/>

       <cancel-process if="${f:status} == 'cancelled'" />

       <participant ref="SPS"    task='Submit'    comments='Submit Task to JPL'/>

       <cancel-process if="${f:status} == 'cancelled'" />

    <participant ref="SOS"       task='Publish'    comments="SOS will make raw data file
available"/>

       <set field="msg" value="You've got data" />
       <participant ref="WNS"      task='Email' />

  </sequence>
</process-definition>



Implementation Details:

Step 1: Tell OpenWFERu about those participants

I created a small class to create the workflow engine and register the participants. Some of
the participants are in-lined as examples. Major participants have their own classes.




www.geobliki.com
/rails/lib/wfe.rb

require   'openwfe/engine/engine'
require   'openwfe/expool/history'
require   'openwfe/expool/journal'
require   'openwfe/engine/file_persisted_engine'
require   'rexml/document'

class Wfe
def self.create_wfe_engine_and_participants
    #
    # === the ENGINE itself as a global variable
    #
    $engine = OpenWFE::Engine.new

    #
    # dumps all the process history in a file name "history.log"
    # in the work directory
    $engine.init_service("history", FileHistory)

    # -- process journaling
    $engine.init_service("journal", Journal)
    $engine.application_context[:keep_journals] = true

    #
    # === some LISTENERS
    #

    #
    # === the PARTICIPANTS
    #
    $engine.register_participant :WPS do |workitem|
      puts "wps output file:"+workitem.processed_file
    end

    $engine.register_participant("XForms", XformParticipant.new )

    $engine.register_participant("SPS", SpsParticipant.new )

    $engine.register_participant :WNS do | flowexpression, workitem|
      # Check msg and email it
      puts "WNS Task:"+workitem.params['task']
      puts "msg:"+workitem.msg
    end

    $engine.register_participant :SOS do | flowexpression, workitem|
      puts "SOS Task:"+workitem.params['task']
    end

    puts "workflow engine started..."
  end
end



At the bottom of your environment file /rails/config/environment.rb, add these lines:

require "wfe"
Wfe.create_wfe_engine_and_participants




www.geobliki.com
Now we need to create our SPS participant. The Sensor Planning Service is a web service
that requires the posting of specific XML snippets to a URL. This service has many methods
and we will only use two of them:
 - GetFeasibilities, to return the imaging feasibilities for a specific latitude/longitude.
 - Submit, to package the requested parameters and request the tasking to happen.

The various tasks of this participant will pick up the required parameters in the workitem.
The user will have entered those parameters in previous steps (later for more information)

Let’s create two stubbed participants, to get our first workflow working

/rails/lib/sps_participant.rb

require 'openwfe/participants/participant'

class SpsParticipant
  include LocalParticipant

  def logger
    @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
  end

  #
  # Consume the workitem received from engine
  #
  def consume (workitem)
    fe    = get_flow_expression(workitem)
    task = fe.attributes['task']

      raise "request parameter is undefined" if task == nil

    logger.debug("SPS Participant Request: #{task}")
    reply_to_engine(workitem)
  end

end




www.geobliki.com
and /rails/lib/xform_participant.rb

require 'openwfe/participants/participant'

class XformParticipant
  include LocalParticipant

  def logger
    @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
  end

  #
  # Consume the workitem received from engine
  #
  def consume (workitem)
    fe    = get_flow_expression(workitem)
    task = fe.attributes['task']

      raise "request parameter is undefined" if task == nil

    logger.debug("XForm Participant Request: #{task}")
    reply_to_engine(workitem)
  end

end



How Do I execute a Workflow?

Somehow the user could discover what workflows are available, pick one from a list or a
database.

One could quickly create a rails controller and a launch method. Other methods can be
written to view, add, delete workflows to the list…

Let’s create a rails controller “Worklist” and 2 methods: intialize & launch. From the rails
project directory:
     ./script/generate controller Worklist initialize launch




www.geobliki.com
Let’s edit the file generated in geobpms/app/controller/worklist_controller.rb.
We will complete the initialize and launch methods.

class WorklistController < ApplicationController

  def initialize
    @workflows_dir = "#{RAILS_ROOT}/public/workflows/"
  end

  def launch
    workflow_name = params[:id]

    #get the process flow from file based on passed-in parameter
    flow = IO.read("#{@workflows_dir}#{workflow_name}.xml")

    launchitem = LaunchItem.new(flow)

    fei,t = $engine.launch(launchitem)

    puts "launching fei: #{fei.to_s}"
    puts "inspect:"+fei.inspect

    @wfid = fei.wfid
  end
end


Before running this, let’s quickly add a view to render the results
Rails has created for us:

/geobpms/app/views/worklist/launch.rhtml

<h1>Worklist#launch</h1>
 <h2>Your workflow has been launched successfully!</h2>
 <h3> Flow id: <%= @wfid %></h3>


Time to test it out to see what we have so far:

Start your application
     ./script/server
       => Booting Mongrel (use 'script/server webrick' to force WEBrick)
       => Rails application starting on http://0.0.0.0:3000
       => Call with -d to detach
       => Ctrl-C to shutdown server
       ** Starting Mongrel listening at 0.0.0.0:3000
       ** Starting Rails with development environment...
       workflow engine started...
       ** Rails loaded.
       ** Loading any Rails specific GemPlugins
       ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no
       restart).
       ** Rails signals registered. HUP => reload (without restart). It
       might not work well.
       ** Mongrel available at 0.0.0.0:3000
       ** Use CTRL-C to stop.




www.geobliki.com
and from your web browser, try this:
http://localhost:3000/worklist/launch/flow

You should see in your browser something like:




The terminal window should show something like:

launching fei: (fei 0.9.11 engine/engine field:__definition
EO1_Simple_Tasking_Workflow 0.1 20070606-koyobibute process-definition 0)
inspect:#<OpenWFE::FlowExpressionId:0x322cc7c
@workflow_definition_revision="0.1", @engine_id="engine",
@workflow_definition_name="EO1_Simple_Tasking_Workflow",
@expression_name="process-definition", @expression_id="0",
@initial_engine_id="engine", @workflow_instance_id="20070606-koyobibute",
@workflow_definition_url="field:__definition", @owfe_version="0.9.11">
WNS Task:Email
msg:Workflow has been sequenced
SOS Task:Publish
WNS Task:Email
msg:You've got data


Processing WorklistController#launch (for 127.0.0.1 at 2007-06-06
15:19:21) [GET]
  Session ID: cebe910aa8bbad3201d752b6d5ddde4c
  Parameters: {"action"=>"launch", "id"=>"flow", "controller"=>"worklist"}
script/../config/../public/workflows/flow.xml
Rendering worklist/launch
Completed in 0.01020 (98 reqs/sec) | Rendering: 0.00111 (10%) | 200 OK
[http://localhost/worklist/launch/flow]
XForm Participant Request: RequestTasking
SPS Participant Request: GetFeasibilities
XForm Participant Request: SelectFeasibility
SPS Participant Request: Submit

Congratulations, you have successfully run your first workflow within Rails!

In the tradition of Rails, we need to capture this milestone and create a test.
[We should have written the test first …]

Note: If you haven’t already stopped your application, do that now by pressing CTRL-C in
the terminal window.


www.geobliki.com
First lets get the databases setup. Edit your database configuration file:
geobpms/config/database.yml

Set the username and password for each of the databases to what ever you would like to use.
In MySQL create geobpms_development, geobpms_test, geobpms_production databases
with the username and password you put in database.yml.

Go to your application directory and type:
   rake test
   (in /Users/linda/work/geobpms)
   workflow engine started...
   /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-
   0.7.3/lib/rake/rake_test_loader.rb"
   /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-
   0.7.3/lib/rake/rake_test_loader.rb"
   "test/functional/worklist_controller_test.rb"
   workflow engine started...
   Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-
   0.7.3/lib/rake/rake_test_loader
   Started
   .
   Finished in 0.038817 seconds.

   1 tests, 1 assertions, 0 failures, 0 errors
   /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake-
   0.7.3/lib/rake/rake_test_loader.rb" and it should pass.

Rails already created a test stub for your controller in:
geobpms/test/functional/worklist_controller_test.rb

Now we need to replace the test_truth method with something like:

def test_launch_flow
  get :launch, :id=>"flow"
  assert_template 'launch'
end

Exercise the test:
    rake test
       (in /Users/linda/work/geobpms)
       workflow engine started...
       /usr/local/bin/ruby -Ilib:test
       "/usr/local/lib/ruby/gems/1.8/gems/rake-
       0.7.3/lib/rake/rake_test_loader.rb"
       /usr/local/bin/ruby -Ilib:test
       "/usr/local/lib/ruby/gems/1.8/gems/rake-
       0.7.3/lib/rake/rake_test_loader.rb"
       "test/functional/worklist_controller_test.rb"
       workflow engine started...
       Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake-
       0.7.3/lib/rake/rake_test_loader
       Started


www.geobliki.com
launching fei: (fei 0.9.11 engine/engine field:__definition
       EO1_Simple_Tasking_Workflow 0.1 20070606-kusokadami process-
       definition 0)
       inspect:#<OpenWFE::FlowExpressionId:0x3216490
       @expression_name="process-definition",
       @workflow_definition_url="field:__definition", @engine_id="engine",
       @initial_engine_id="engine", @workflow_instance_id="20070606-
       kusokadami", @owfe_version="0.9.11", @expression_id="0",
       @workflow_definition_revision="0.1",
       @workflow_definition_name="EO1_Simple_Tasking_Workflow">
       .
       Finished in 0.082942 seconds.

       1 tests, 1 assertions, 0 failures, 0 errors
       /usr/local/bin/ruby -Ilib:test
       "/usr/local/lib/ruby/gems/1.8/gems/rake-
       0.7.3/lib/rake/rake_test_loader.rb"



Congratulations, you have successfully run your first workflow test within Rails!



TO BE CONTINUED.




www.geobliki.com

More Related Content

What's hot

Why Laravel?
Why Laravel?Why Laravel?
Why Laravel?
Jonathan Goode
 
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and ScalabilitySolving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
ZendCon
 
Apache Aries Overview
Apache Aries   OverviewApache Aries   Overview
Apache Aries Overview
Ian Robinson
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
Agnieszka Figiel
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
Joshua Long
 
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
Shailendra Rai
 
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for HadoopMay 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
Yahoo Developer Network
 
Getting started with agile database migrations for java flywaydb
Getting started with agile database migrations for java flywaydbGetting started with agile database migrations for java flywaydb
Getting started with agile database migrations for java flywaydb
Girish Bapat
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
Manoj Kumar
 
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
Hiroshi Ono
 
GR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting GrailsGR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting Grails
GR8Conf
 
Adventures in Laravel 5 SunshinePHP 2016 Tutorial
Adventures in Laravel 5 SunshinePHP 2016 TutorialAdventures in Laravel 5 SunshinePHP 2016 Tutorial
Adventures in Laravel 5 SunshinePHP 2016 Tutorial
Joe Ferguson
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
Viral Solani
 
Virtual CD4PE Workshop
Virtual CD4PE WorkshopVirtual CD4PE Workshop
Virtual CD4PE Workshop
Puppet
 
The Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
The Cloud Foundry bootcamp talk from SpringOne On The Road - EuropeThe Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
The Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
Joshua Long
 
a Running Tour of Cloud Foundry
a Running Tour of Cloud Foundrya Running Tour of Cloud Foundry
a Running Tour of Cloud Foundry
Joshua Long
 
Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]
Ryan Cuprak
 
Cakephp
CakephpCakephp
File Processing - Process Execution Solution
File Processing - Process Execution SolutionFile Processing - Process Execution Solution
File Processing - Process Execution Solution
Abimael Desales López
 

What's hot (19)

Why Laravel?
Why Laravel?Why Laravel?
Why Laravel?
 
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and ScalabilitySolving the C20K problem: Raising the bar in PHP Performance and Scalability
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
 
Apache Aries Overview
Apache Aries   OverviewApache Aries   Overview
Apache Aries Overview
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
 
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
OpenUI5 Conf 2019: Promise Chaining - Create UI applications with Flexible, M...
 
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for HadoopMay 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
May 2012 HUG: Oozie: Towards a scalable Workflow Management System for Hadoop
 
Getting started with agile database migrations for java flywaydb
Getting started with agile database migrations for java flywaydbGetting started with agile database migrations for java flywaydb
Getting started with agile database migrations for java flywaydb
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
Solving_the_C20K_problem_PHP_Performance_and_Scalability-phpquebec_2009
 
GR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting GrailsGR8Conf 2011: Adopting Grails
GR8Conf 2011: Adopting Grails
 
Adventures in Laravel 5 SunshinePHP 2016 Tutorial
Adventures in Laravel 5 SunshinePHP 2016 TutorialAdventures in Laravel 5 SunshinePHP 2016 Tutorial
Adventures in Laravel 5 SunshinePHP 2016 Tutorial
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
 
Virtual CD4PE Workshop
Virtual CD4PE WorkshopVirtual CD4PE Workshop
Virtual CD4PE Workshop
 
The Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
The Cloud Foundry bootcamp talk from SpringOne On The Road - EuropeThe Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
The Cloud Foundry bootcamp talk from SpringOne On The Road - Europe
 
a Running Tour of Cloud Foundry
a Running Tour of Cloud Foundrya Running Tour of Cloud Foundry
a Running Tour of Cloud Foundry
 
Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]Faster java ee builds with gradle [con4921]
Faster java ee builds with gradle [con4921]
 
Cakephp
CakephpCakephp
Cakephp
 
File Processing - Process Execution Solution
File Processing - Process Execution SolutionFile Processing - Process Execution Solution
File Processing - Process Execution Solution
 

Viewers also liked

forms
formsforms
Tutorial
TutorialTutorial
Tutorial
tutorialsruby
 
OSOM - Ruby on Rails
OSOM - Ruby on Rails OSOM - Ruby on Rails
OSOM - Ruby on Rails
Marcela Oniga
 
Rubyonrails 090715105949-phpapp01
Rubyonrails 090715105949-phpapp01Rubyonrails 090715105949-phpapp01
Rubyonrails 090715105949-phpapp01
sagaroceanic11
 
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
tutorialsruby
 
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
tutorialsruby
 

Viewers also liked (6)

forms
formsforms
forms
 
Tutorial
TutorialTutorial
Tutorial
 
OSOM - Ruby on Rails
OSOM - Ruby on Rails OSOM - Ruby on Rails
OSOM - Ruby on Rails
 
Rubyonrails 090715105949-phpapp01
Rubyonrails 090715105949-phpapp01Rubyonrails 090715105949-phpapp01
Rubyonrails 090715105949-phpapp01
 
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
The Art Institute of Atlanta IMD 210 Fundamentals of Scripting &lt;b>...&lt;/b>
 
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
TopStyle Help &amp; &lt;b>Tutorial&lt;/b>
 

Similar to BPMS1

Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
Jean-Baptiste Feldis
 
Create a new project in ROR
Create a new project in RORCreate a new project in ROR
Create a new project in ROR
akankshita satapathy
 
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
Paul Jensen
 
RoR guide_p1
RoR guide_p1RoR guide_p1
RoR guide_p1
Brady Cheng
 
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
Jesse Gallagher
 
Dev streams2
Dev streams2Dev streams2
Dev streams2
David Mc Donagh
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails Basics
Amit Solanki
 
Openshift cheat rhce_r3v1 rhce
Openshift cheat rhce_r3v1 rhceOpenshift cheat rhce_r3v1 rhce
Openshift cheat rhce_r3v1 rhce
Darnette A
 
sveltekit-en.pdf
sveltekit-en.pdfsveltekit-en.pdf
sveltekit-en.pdf
ssuser65180a
 
Workflow Yapceu2010
Workflow Yapceu2010Workflow Yapceu2010
Workflow Yapceu2010
Jonas Brømsø
 
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Mack Hardy
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
Raimonds Simanovskis
 
TorqueBox
TorqueBoxTorqueBox
TorqueBox
bobmcwhirter
 
NodeJS @ ACS
NodeJS @ ACSNodeJS @ ACS
NodeJS @ ACS
Mauro Parra-Miranda
 
Introduction to Node.JS
Introduction to Node.JSIntroduction to Node.JS
Introduction to Node.JS
Collaboration Technologies
 
Beginning MEAN Stack
Beginning MEAN StackBeginning MEAN Stack
Beginning MEAN Stack
Rob Davarnia
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
Su Zin Kyaw
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
Gautam Rege
 
High Performance NodeJS
High Performance NodeJSHigh Performance NodeJS
High Performance NodeJS
Dicoding
 
Devopstore
DevopstoreDevopstore
Devopstore
Farkhad Badalov
 

Similar to BPMS1 (20)

Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
 
Create a new project in ROR
Create a new project in RORCreate a new project in ROR
Create a new project in ROR
 
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Em...
 
RoR guide_p1
RoR guide_p1RoR guide_p1
RoR guide_p1
 
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
CollabSphere 2021 - DEV114 - The Nuts and Bolts of CI/CD With a Large XPages ...
 
Dev streams2
Dev streams2Dev streams2
Dev streams2
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails Basics
 
Openshift cheat rhce_r3v1 rhce
Openshift cheat rhce_r3v1 rhceOpenshift cheat rhce_r3v1 rhce
Openshift cheat rhce_r3v1 rhce
 
sveltekit-en.pdf
sveltekit-en.pdfsveltekit-en.pdf
sveltekit-en.pdf
 
Workflow Yapceu2010
Workflow Yapceu2010Workflow Yapceu2010
Workflow Yapceu2010
 
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
 
Extending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on RailsExtending Oracle E-Business Suite with Ruby on Rails
Extending Oracle E-Business Suite with Ruby on Rails
 
TorqueBox
TorqueBoxTorqueBox
TorqueBox
 
NodeJS @ ACS
NodeJS @ ACSNodeJS @ ACS
NodeJS @ ACS
 
Introduction to Node.JS
Introduction to Node.JSIntroduction to Node.JS
Introduction to Node.JS
 
Beginning MEAN Stack
Beginning MEAN StackBeginning MEAN Stack
Beginning MEAN Stack
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
Ruby On Rails
Ruby On RailsRuby On Rails
Ruby On Rails
 
High Performance NodeJS
High Performance NodeJSHigh Performance NodeJS
High Performance NodeJS
 
Devopstore
DevopstoreDevopstore
Devopstore
 

More from tutorialsruby

&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
tutorialsruby
 
Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0
tutorialsruby
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
tutorialsruby
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
tutorialsruby
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
tutorialsruby
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
tutorialsruby
 
CSS
CSSCSS
CSS
CSSCSS
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
tutorialsruby
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
tutorialsruby
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
tutorialsruby
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
tutorialsruby
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
tutorialsruby
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
tutorialsruby
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
tutorialsruby
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
tutorialsruby
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascript
tutorialsruby
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascript
tutorialsruby
 

More from tutorialsruby (20)

&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />&lt;img src="../i/r_14.png" />
&lt;img src="../i/r_14.png" />
 
Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0Standardization and Knowledge Transfer – INS0
Standardization and Knowledge Transfer – INS0
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
 
xhtml_basics
xhtml_basicsxhtml_basics
xhtml_basics
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
 
xhtml-documentation
xhtml-documentationxhtml-documentation
xhtml-documentation
 
CSS
CSSCSS
CSS
 
CSS
CSSCSS
CSS
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
 
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa0602690047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
0047ecaa6ea3e9ac0a13a2fe96f4de3bfd515c88f5d90c1fae79b956363d7f02c7fa060269
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
 
HowTo_CSS
HowTo_CSSHowTo_CSS
HowTo_CSS
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
 
BloggingWithStyle_2008
BloggingWithStyle_2008BloggingWithStyle_2008
BloggingWithStyle_2008
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
 
cascadingstylesheets
cascadingstylesheetscascadingstylesheets
cascadingstylesheets
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascript
 
Winter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20JavascriptWinter%200405%20-%20Advanced%20Javascript
Winter%200405%20-%20Advanced%20Javascript
 

Recently uploaded

Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
ThomasParaiso2
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
DianaGray10
 

Recently uploaded (20)

Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
 
GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...GridMate - End to end testing is a critical piece to ensure quality and avoid...
GridMate - End to end testing is a critical piece to ensure quality and avoid...
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5UiPath Test Automation using UiPath Test Suite series, part 5
UiPath Test Automation using UiPath Test Suite series, part 5
 

BPMS1

  • 1. GeoBliki Pat Cappelaere pat@geobliki.com Linda Derezinski linda@geobliki.com And GeoBPMS June 7th, 2007 Part I Business Process Management System For the Enterprise Using Open Source Components Targeted Audience: Rails Integrators, Business Process Analysts and OpenWFEru enthusiasts. Warning: This is not a Ruby or Rails tutorial. This document assumes that you have a working knowledge of Ruby and Rails. BPMS Business Case: Sophisticated products and/or automation require the definition of service chains (or workflows) that can involve many participants from humans to web services collaborating in a seamless manner. These processes need to be managed and defined at the Enterprise level and fall in a category called: Business Process Management. This can be fairly complex and expensive. Many acronyms and technologies need to be mastered. Our goal is to show that we can put together a solid framework based around open source components and keep it relatively simple and manageable. Let’s walk through an example. Scope of this document: - Step description of all components and tools required for BPMS and integration within Ruby on Rails. - Example of a workflow with code snippets. www.geobliki.com
  • 2. Introduction: Service-chains can be defined to sequence and allocate activities or tasks across many participants using workflows. First step is to capture and visualize the process. A good picture is worth a thousand words. So we need to make it look really good! There are many ways to generate Business Process diagrams. A de-facto notation standard has been released in Feb 2006 (BPMN1) supported by more than 42 implementations (as of April 12, 2007). Eclipse is actively working on its own STP BPMN Modeler2. For the time being, we will be using Business Process Visual Architect3 from Visual Paradigm. Preflight check-list: Before getting into the tutorial, check to see that you have everything required. 1) You have Ruby and Rails4 installed. Check that you have at least the following versions.  ruby –version ruby 1.8.6  rails –version Rails 1.2.3 If you need to install Ruby on Rails: For Windows, use Instant Rails. For Mac OS X, use Locomotive. For Linux, try the Rails LiveCD. A good development environment on Macintosh is TextMate5 or Eclipse with Ruby RDT6 on all platforms. To get rolling with Ruby on Rails: Check this out 2) MySQL7 installed. 4.x distribution or later is fine.  mysql –version mysql Ver 14.12 Distrib 5.0.20a If you need to install MySQL download 1 http://www.bpmn.org/ 2 http://www.eclipse.org/stp/bpmn/ 3 http://www.visual-paradigm.com/product/bpva/ 4 http://www.rubyonrails.org/ 5 http://macromates.com/ 6 http://www-128.ibm.com/developerworks/opensource/library/os-rubyeclipse/ 7 http://www.mysql.org www.geobliki.com
  • 3. Create a empty Rails application “geobpms”  rails geobpms And make sure it works by testing it – Start the application  cd geobpms  ./script/server in your favorite browser, go to http://127.0.0.1:3000/ Double check the environment one more time by selecting the “About your application’s environment” link. You should have these or later versions: www.geobliki.com
  • 4. Download OpenWFERu Go to: http://openwferu.rubyforge.org/ You can get it as a gem, latest stable version or from the svn trunk. Note: My personal preference is to download the latest version and keep it under control so I can go back to previous version as necessary (or check what changed between versions). Install the gem  gem install -y openwferu Successfully installed openwferu-0.9.11 Installing ri documentation for openwferu-0.9.11... Installing RDoc documentation for openwferu-0.9.11... Copy the gem into your vendor directory. In this case the current version is 0.9.11. From your geobpms rails project directory  cp –R /usr/local/lib/ruby/gems/1.8/gems/openwferu-0.9.11 vendor/ Edit geobpms/config/environment.rb to point to the newly installed version of openwferu Add this text: config.load_paths += %W( vendor/openwferu-0.9.11/lib ).map {|dir| "#{RAILS_ROOT}/#{dir}"}.select { |dir| File.directory?(dir) } Below the commented out config.load_paths line like so: To change between versions, change the version number on line #25. www.geobliki.com
  • 5. Workflow Description: This workflow example shows the tasking request of the EO-1 satellite by a user who interacts with the system via XForms. The user enters a tasking request using some input (lat/long…). The workflow proceeds by calling the Sensor Planning System (SPS) to check for feasibilities. The user is prompted to select a feasibility and the task is submitted. Eventually, the task is completed onboard. The data is down-linked to the ground and published by the Sensor Observation Service (SOS). Finally the user is alerted that data is available via email by the Web Notification Service (WNS). Figure 1. “Simple” EO1 Satellite Tasking Workflow www.geobliki.com
  • 6. The various participants in this workflows are: XForms, SPS, SOS and WNS. They are represented as Pools. They perform various tasks for this workflow. Ideally, we would save this workflow in OpenWFERu XML format (or XPDL 2.0 and then translate it). This would be a possible outcome: Create a workflows directory in the public folder and then copy the following into flow.xml. /rails/public/workflows/flow.xml <process-definition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.openwfe.org/flowdef.xsd" name="EO1 Simple Tasking Workflow" revision="0.1" theme="n/a" security="restricted" > <sequence> <set field="msg" value="Workflow has been sequenced" /> <participant ref="WNS" task='Email' /> <participant ref='XForms' task='RequestTasking' comments='Enter EO-1 Tasking Parameters' /> <participant ref="SPS" task='GetFeasibilities' timeout="2d" comments='Check EO-1 Tasking Feasibilities'/> <participant ref='XForms' task='SelectFeasibility' comments='Select Desired Feasibility' /> <cancel-process if="${f:status} == 'cancelled'" /> <participant ref="SPS" task='Submit' comments='Submit Task to JPL'/> <cancel-process if="${f:status} == 'cancelled'" /> <participant ref="SOS" task='Publish' comments="SOS will make raw data file available"/> <set field="msg" value="You've got data" /> <participant ref="WNS" task='Email' /> </sequence> </process-definition> Implementation Details: Step 1: Tell OpenWFERu about those participants I created a small class to create the workflow engine and register the participants. Some of the participants are in-lined as examples. Major participants have their own classes. www.geobliki.com
  • 7. /rails/lib/wfe.rb require 'openwfe/engine/engine' require 'openwfe/expool/history' require 'openwfe/expool/journal' require 'openwfe/engine/file_persisted_engine' require 'rexml/document' class Wfe def self.create_wfe_engine_and_participants # # === the ENGINE itself as a global variable # $engine = OpenWFE::Engine.new # # dumps all the process history in a file name "history.log" # in the work directory $engine.init_service("history", FileHistory) # -- process journaling $engine.init_service("journal", Journal) $engine.application_context[:keep_journals] = true # # === some LISTENERS # # # === the PARTICIPANTS # $engine.register_participant :WPS do |workitem| puts "wps output file:"+workitem.processed_file end $engine.register_participant("XForms", XformParticipant.new ) $engine.register_participant("SPS", SpsParticipant.new ) $engine.register_participant :WNS do | flowexpression, workitem| # Check msg and email it puts "WNS Task:"+workitem.params['task'] puts "msg:"+workitem.msg end $engine.register_participant :SOS do | flowexpression, workitem| puts "SOS Task:"+workitem.params['task'] end puts "workflow engine started..." end end At the bottom of your environment file /rails/config/environment.rb, add these lines: require "wfe" Wfe.create_wfe_engine_and_participants www.geobliki.com
  • 8. Now we need to create our SPS participant. The Sensor Planning Service is a web service that requires the posting of specific XML snippets to a URL. This service has many methods and we will only use two of them: - GetFeasibilities, to return the imaging feasibilities for a specific latitude/longitude. - Submit, to package the requested parameters and request the tasking to happen. The various tasks of this participant will pick up the required parameters in the workitem. The user will have entered those parameters in previous steps (later for more information) Let’s create two stubbed participants, to get our first workflow working /rails/lib/sps_participant.rb require 'openwfe/participants/participant' class SpsParticipant include LocalParticipant def logger @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT) end # # Consume the workitem received from engine # def consume (workitem) fe = get_flow_expression(workitem) task = fe.attributes['task'] raise "request parameter is undefined" if task == nil logger.debug("SPS Participant Request: #{task}") reply_to_engine(workitem) end end www.geobliki.com
  • 9. and /rails/lib/xform_participant.rb require 'openwfe/participants/participant' class XformParticipant include LocalParticipant def logger @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT) end # # Consume the workitem received from engine # def consume (workitem) fe = get_flow_expression(workitem) task = fe.attributes['task'] raise "request parameter is undefined" if task == nil logger.debug("XForm Participant Request: #{task}") reply_to_engine(workitem) end end How Do I execute a Workflow? Somehow the user could discover what workflows are available, pick one from a list or a database. One could quickly create a rails controller and a launch method. Other methods can be written to view, add, delete workflows to the list… Let’s create a rails controller “Worklist” and 2 methods: intialize & launch. From the rails project directory:  ./script/generate controller Worklist initialize launch www.geobliki.com
  • 10. Let’s edit the file generated in geobpms/app/controller/worklist_controller.rb. We will complete the initialize and launch methods. class WorklistController < ApplicationController def initialize @workflows_dir = "#{RAILS_ROOT}/public/workflows/" end def launch workflow_name = params[:id] #get the process flow from file based on passed-in parameter flow = IO.read("#{@workflows_dir}#{workflow_name}.xml") launchitem = LaunchItem.new(flow) fei,t = $engine.launch(launchitem) puts "launching fei: #{fei.to_s}" puts "inspect:"+fei.inspect @wfid = fei.wfid end end Before running this, let’s quickly add a view to render the results Rails has created for us: /geobpms/app/views/worklist/launch.rhtml <h1>Worklist#launch</h1> <h2>Your workflow has been launched successfully!</h2> <h3> Flow id: <%= @wfid %></h3> Time to test it out to see what we have so far: Start your application  ./script/server => Booting Mongrel (use 'script/server webrick' to force WEBrick) => Rails application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... workflow engine started... ** Rails loaded. ** Loading any Rails specific GemPlugins ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart). ** Rails signals registered. HUP => reload (without restart). It might not work well. ** Mongrel available at 0.0.0.0:3000 ** Use CTRL-C to stop. www.geobliki.com
  • 11. and from your web browser, try this: http://localhost:3000/worklist/launch/flow You should see in your browser something like: The terminal window should show something like: launching fei: (fei 0.9.11 engine/engine field:__definition EO1_Simple_Tasking_Workflow 0.1 20070606-koyobibute process-definition 0) inspect:#<OpenWFE::FlowExpressionId:0x322cc7c @workflow_definition_revision="0.1", @engine_id="engine", @workflow_definition_name="EO1_Simple_Tasking_Workflow", @expression_name="process-definition", @expression_id="0", @initial_engine_id="engine", @workflow_instance_id="20070606-koyobibute", @workflow_definition_url="field:__definition", @owfe_version="0.9.11"> WNS Task:Email msg:Workflow has been sequenced SOS Task:Publish WNS Task:Email msg:You've got data Processing WorklistController#launch (for 127.0.0.1 at 2007-06-06 15:19:21) [GET] Session ID: cebe910aa8bbad3201d752b6d5ddde4c Parameters: {"action"=>"launch", "id"=>"flow", "controller"=>"worklist"} script/../config/../public/workflows/flow.xml Rendering worklist/launch Completed in 0.01020 (98 reqs/sec) | Rendering: 0.00111 (10%) | 200 OK [http://localhost/worklist/launch/flow] XForm Participant Request: RequestTasking SPS Participant Request: GetFeasibilities XForm Participant Request: SelectFeasibility SPS Participant Request: Submit Congratulations, you have successfully run your first workflow within Rails! In the tradition of Rails, we need to capture this milestone and create a test. [We should have written the test first …] Note: If you haven’t already stopped your application, do that now by pressing CTRL-C in the terminal window. www.geobliki.com
  • 12. First lets get the databases setup. Edit your database configuration file: geobpms/config/database.yml Set the username and password for each of the databases to what ever you would like to use. In MySQL create geobpms_development, geobpms_test, geobpms_production databases with the username and password you put in database.yml. Go to your application directory and type:  rake test (in /Users/linda/work/geobpms) workflow engine started... /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" "test/functional/worklist_controller_test.rb" workflow engine started... Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader Started . Finished in 0.038817 seconds. 1 tests, 1 assertions, 0 failures, 0 errors /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" and it should pass. Rails already created a test stub for your controller in: geobpms/test/functional/worklist_controller_test.rb Now we need to replace the test_truth method with something like: def test_launch_flow get :launch, :id=>"flow" assert_template 'launch' end Exercise the test:  rake test (in /Users/linda/work/geobpms) workflow engine started... /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" "test/functional/worklist_controller_test.rb" workflow engine started... Loaded suite /usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader Started www.geobliki.com
  • 13. launching fei: (fei 0.9.11 engine/engine field:__definition EO1_Simple_Tasking_Workflow 0.1 20070606-kusokadami process- definition 0) inspect:#<OpenWFE::FlowExpressionId:0x3216490 @expression_name="process-definition", @workflow_definition_url="field:__definition", @engine_id="engine", @initial_engine_id="engine", @workflow_instance_id="20070606- kusokadami", @owfe_version="0.9.11", @expression_id="0", @workflow_definition_revision="0.1", @workflow_definition_name="EO1_Simple_Tasking_Workflow"> . Finished in 0.082942 seconds. 1 tests, 1 assertions, 0 failures, 0 errors /usr/local/bin/ruby -Ilib:test "/usr/local/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake/rake_test_loader.rb" Congratulations, you have successfully run your first workflow test within Rails! TO BE CONTINUED. www.geobliki.com