servicemix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache ServiceMix: BeanFlow (page edited)
Date Mon, 14 Apr 2008 16:17:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence" />
    <style type="text/css">
    <!--
    body, p, td, table, tr, .bodytext, .stepfield {
	font-family: Verdana, arial, sans-serif;
	font-size: 11px;
	line-height: 16px;
	color: #000000;
	font-weight: normal;
}
#PageContent {
	text-align: left;
	background-color: #fff;
	padding: 0px;
	margin: 0px;
    padding-bottom:20px;
}
/*
** when this stylesheet is used for the Tiny MCE Wysiwyg editor's edit area, we can't
** use an id=PageContent or class=wiki-content, so we must
** set the body style to that used for PageContent, and p to that used for wiki-content.
*/

body {
	margin: 0px;
	padding: 0px;
	text-align: center;
    background-color: #f0f0f0;
}

@media print {

body {
    background-color: #fff;
}

}

.monospaceInput {
    font:12px monospace
}

.wiki-content p, .commentblock p {
    margin: 16px 0px 16px 0px;
    padding: 0px;
}

.wiki-content-preview {
    padding: 5px;
    border-left: 1px solid #3c78b5;
    border-right: 1px solid #3c78b5;
}

ul, ol {
    margin-top: 2px;
    margin-bottom: 2px;
    padding-top: 0px;
    padding-bottom: 0px;
}

pre {
    padding: 0px;
    margin-top: 5px;
    margin-left: 15px;
    margin-bottom: 5px;
    margin-right: 5px;
    text-align: left;
}

.helpheading {
    font-weight: bold;
    background-color: #D0D9BD;
        border-bottom: 1px solid #3c78b5;
        padding: 4px 4px 4px 4px;
        margin: 0px;
        margin-top: 10px;
}
.helpcontent {
        padding: 4px 4px 20px 4px;
    background-color: #f5f7f1;
}

.code {
 	border: 1px dashed #3c78b5;
    font-size: 11px;
	font-family: Courier;
    margin: 10px;
	line-height: 13px;
}

.focusedComment {
    background: #ffffce;
}

.commentBox, .focusedComment {
    padding: 10px;
    margin: 5px 0 5px 0;
    border: 1px #bbb solid;
}

.codeHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.codeContent {
    text-align: left;
    background-color: #f0f0f0;
    padding: 3px;
}

.preformatted {
 	border: 1px dashed #3c78b5;
    font-size: 11px;
	font-family: Courier;
    margin: 10px;
	line-height: 13px;
}

.preformattedHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.preformattedContent {
    background-color: #f0f0f0;
    padding: 3px;
}

.panel {
 	border: 1px dashed #3c78b5;
    margin: 10px;
    margin-top: 0px;
}

.panelHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.panelContent {
    background-color: #f0f0f0;
    padding: 5px;
}

.anonymousAlert {
    background-color: #f0f0f0;
 	border: 1px dashed red;
    font-size: 11px;
    padding: 10px 5px 10px 5px;
    margin: 4px;
	line-height: 13px;
}

.lockAlert {
    background-color: #f0f0f0;
    width: 50%;
 	border: 1px dashed red;
    font-size: 11px;
    padding: 10px 5px 10px 5px;
    margin: 4px;
	line-height: 13px;
}


.code-keyword {
  color: #000091;
  background-color: inherit;
}

.code-object {
  color: #910091;
  background-color: inherit;
}

.code-quote {
  color: #009100;
  background-color: inherit;
}

.code-comment {
  color: #808080;
  background-color: inherit;
}


.code-xml .code-keyword {
  color: inherit;
  font-weight: bold;
}

.code-tag {
  color: #000091;
  background-color: inherit;
}

.breadcrumbs {
    background-color: #f0f0f0;
 	border-color: #3c78b5;
	border-width: 1px 0px 1px 0px;
	border-style: solid;
    font-size: 11px;
    padding: 3px 0px 3px 0px;
}

.navmenu {
    border: 1px solid #ccc;
}

.menuheading {
    font-weight: bold;
    background-color: #f0f0f0;
 	border-bottom: 1px solid #3c78b5;
	padding: 4px 4px 2px 4px;
}

.menuitems {
	padding: 4px 4px 20px 4px;
}

.rightpanel {
    border-left: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
}

#helpheading {
    text-align: left;
    font-weight: bold;
    background-color: #D0D9BD;
 	border-bottom: 1px solid #3c78b5;
	padding: 4px 4px 4px 4px;
	margin: 0px;
}
#helpcontent {
	padding: 4px 4px 4px 4px;
    background-color: #f5f7f1;
}
.helptab-unselected {
    font-weight: bold;
	padding: 5px;
    background-color: #f5f7f1;
}
.helptab-selected {
    font-weight: bold;
    background-color: #D0D9BD;
	padding: 5px;
}
.helptabs {
    margin: 0px;
    background-color: #f5f7f1;
	padding: 5px;
}
.infopanel-heading {
    font-weight: bold;
	padding: 4px 0px 2px 0px;
}

.pagebody {
}

.pageheader {
	padding: 5px 5px 5px 0px;
 	border-bottom: 1px solid #3c78b5;
}

.pagetitle {
	font-size: 22px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
}

.newpagetitle {
    color: #ccc !important;
}

.steptitle {
	font-size: 18px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
	margin-bottom: 7px;
}

.substeptitle {
    font-size: 12px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
    margin: 2px 4px 4px 4px;
    padding: 2px 4px 1px 4px;
}

.stepdesc {
    font-family: Verdana, arial, sans-serif;
	font-size: 11px;
	line-height: 16px;
	font-weight: normal;
    color: #666666;
    margin-top: 7px;
    margin-bottom: 7px;
}

.steplabel {
    font-weight: bold;
    margin-right: 4px;
    color: black;
    float: left;
    width: 15%;
    text-align: right;
}

.stepfield {
    background: #f0f0f0;
    padding: 5px;
}

.submitButtons{
    margin-top:5px;
    text-align:right;
}

.formtitle {
	font-size: 12px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
}

.sectionbottom {
    border-bottom: 1px solid #3c78b5;
}

.topRow {
    border-top: 2px solid #3c78b5;
}

.tabletitle {
	font-size: 14px;
	font-weight: bold;
	font-family: Arial, sans-serif;
    padding: 3px 0px 2px 0px;
    margin: 8px 4px 2px 0px;
	color: #003366;
	border-bottom: 2px solid #3c78b5;
}
.pagesubheading {
    color: #666666;
    font-size: 10px;
    padding: 0px 0px 5px 0px;
}

HR {
	color: 3c78b5;
	height: 1;
}

A:link, A:visited, A:active, A:hover {
	color: #003366;
}

h1 A:link, h1 A:visited, h1 A:active {
	text-decoration: none;
}

h1 A:hover {
    border-bottom: 1px dotted #003366;
}

.wiki-content > :first-child, .commentblock > :first-child {
    margin-top: 3px;
}

.logocell {
    padding: 10px;
}

input {
	font-family: verdana, geneva, arial, sans-serif;
	font-size: 11px;
	color: #000000;
}

textarea, textarea.editor {
	font-family: verdana, geneva, arial, sans-serif;
	font-size: 11px;
	color: #333333;
}

/* use logoSpaceLink instead.
.spacenametitle {
	font: 21px/31px Impact, Arial, Helvetica;
    font-weight: 100;
    color: #999999;
	margin: 0px;
}
.spacenametitle img {
  margin: 0 0 -4px 0;
}
.spacenametitle a {
    text-decoration: none;
    color: #999999;
}
.spacenametitle a:visited {
    text-decoration: none;
    color: #999999;
}*/

.spacenametitle-printable {
	font: 20px/25px Impact, Arial, Helvetica;
    font-weight: 100;
    color: #999999;
	margin: 0px;
}
.spacenametitle-printable a {
    text-decoration: none;
    color: #999999;
}
.spacenametitle-printable a:visited {
    text-decoration: none;
    color: #999999;
}

.blogDate {
	font-weight: bold;
	text-decoration: none;
	color: black;
}

.blogSurtitle {
    background: #f0f0f0;
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.blogHeading {
    font-size: 20px;
    line-height: normal;
    font-weight: bold;
    padding: 0px;
    margin: 0px;
}

.blogHeading a {
   text-decoration: none;
   color: black;
}

.endsection {
	align: right;
	color: #666666;
	margin-top: 10px;
}
.endsectionleftnav {
	align: right;
	color: #666666;
	margin-top: 10px;
}

h1 {
	font-size: 24px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	color: #003366;
 	border-bottom: 1px solid #3c78b5;
	padding: 2px;
	margin: 36px 0px 4px 0px;
}

h2 {
	font-size: 18px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
 	border-bottom: 1px solid #3c78b5;
	padding: 2px;
	margin: 27px 0px 4px 0px;
}

h3 {
	font-size: 14px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 21px 0px 4px 0px;
}

h4 {
	font-size: 12px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 18px 0px 4px 0px;
}

h4.search {
	font-size: 12px;
	line-height: normal;
	font-weight: normal;
	background-color: #f0f0f0;
	padding: 4px;
	margin: 18px 0px 4px 0px;
}

h5 {
	font-size: 10px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 14px 0px 4px 0px;
}

h6 {
	font-size: 8px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 14px 0px 4px 0px;
}

.smallfont {
    font-size: 10px;
}
.descfont {
    font-size: 10px;
    color: #666666;
}
.smallerfont {
    font-size: 9px;
}
.smalltext {
    color: #666666;
    font-size: 10px;
}
.smalltext a {
    color: #666666;
}
.smalltext-blue {
    color: #3c78b5;
    font-size: 10px;
}
.surtitle {
    margin-left: 1px;
    margin-bottom: 5px;
    font-size: 14px;
    color: #666666;
}

/* css hack found here:  http://www.fo3nix.pwp.blueyonder.co.uk/tutorials/css/hacks/ */
.navItemOver { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #003366; cursor: hand; voice-family: '\'}\''; voice-family:inherit; cursor: pointer;}
.navItemOver a { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItemOver a:visited { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItemOver a:hover { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItem { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #3c78b5; }
.navItem a { color: #ffffff; text-decoration: none; }
.navItem a:hover { color: #ffffff; text-decoration: none; }
.navItem a:visited { color: #ffffff; text-decoration: none; }

div.padded { padding: 4px; }
div.thickPadded { padding: 10px; }
h3.macrolibrariestitle {
    margin: 0px 0px 0px 0px;
}

div.centered { text-align: center; margin: 10px; }
div.centered table {margin: 0px auto; text-align: left; }

.tableview table {
    margin: 0;
}

.tableview th {
    text-align: left;
    color: #003366;
    font-size: 12px;
    padding: 5px 0px 0px 5px;
    border-bottom: 2px solid #3c78b5;
}
.tableview td {
    text-align: left;
    border-color: #ccc;
    border-width: 0px 0px 1px 0px;
    border-style: solid;
    margin: 0;
    padding: 4px 10px 4px 5px;
}

.grid {
    margin: 2px 0px 5px 0px;
    border-collapse: collapse;
}
.grid th  {
    border: 1px solid #ccc;
    padding: 2px 4px 2px 4px;
    background: #f0f0f0;
    text-align: center;
}
.grid td  {
    border: 1px solid #ccc;
    padding: 3px 4px 3px 4px;
}
.gridHover {
	background-color: #f9f9f9;
}

td.infocell {
    background-color: #f0f0f0;
}
.label {
	font-weight: bold;
	color: #003366;
}

label {
	font-weight: bold;
	color: #003366;
}

.error {
	background-color: #fcc;
}

.errorBox {
	background-color: #fcc;
    border: 1px solid #c00;
    padding: 5px;
    margin: 5px;
}

.errorMessage {
	color: #c00;
}

.success {
	background-color: #dfd;
}

.successBox {
	background-color: #dfd;
    border: 1px solid #090;
    padding: 5px;
    margin-top:5px;
    margin-bottom:5px;
}

blockquote {
	padding-left: 10px;
	padding-right: 10px;
	margin-left: 5px;
	margin-right: 0px;
	border-left: 1px solid #3c78b5;
}

table.confluenceTable
{
    margin: 5px;
    border-collapse: collapse;
}

/* Added as a temporary fix for CONF-4223. The table elements appear to be inheriting the border: none attribute from the sectionMacro class */
table.confluenceTable td.confluenceTd
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
}

/* Added as a temporary fix for CONF-4223. The table elements appear to be inheriting the border: none attribute from the sectionMacro class */
table.confluenceTable th.confluenceTh
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
    background-color: #f0f0f0;
    text-align: center;
}

td.confluenceTd
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
}

th.confluenceTh
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
    background-color: #f0f0f0;
    text-align: center;
}

DIV.small {
	font-size: 9px;
}

H1.pagename {
	margin-top: 0px;
}

IMG.inline  {}

.loginform {
    margin: 5px;
    border: 1px solid #ccc;
}

/* The text how the "This is a preview" comment should be shown. */
.previewnote { text-align: center;
                font-size: 11px;
                    color: red; }

/* How the preview content should be shown */
.previewcontent { background: #E0E0E0; }

/* How the system messages should be shown (DisplayMessage.jsp) */
.messagecontent { background: #E0E0E0; }

/* How the "This page has been modified..." -comment should be shown. */
.conflictnote { }

.createlink {
    color: maroon;
}
a.createlink {
    color: maroon;
}
.templateparameter {
    font-size: 9px;
    color: darkblue;
}

.diffadded {
    background: #ddffdd;
    padding: 1px 1px 1px 4px;
	border-left: 4px solid darkgreen;
}
.diffdeleted {
    color: #999;
    background: #ffdddd;
    padding: 1px 1px 1px 4px;
	border-left: 4px solid darkred;
}
.diffnochange {
    padding: 1px 1px 1px 4px;
	border-left: 4px solid lightgrey;
}
.differror {
    background: brown;
}
.diff {
    font-family: lucida console, courier new, fixed-width;
	font-size: 12px;
	line-height: 14px;
}
.diffaddedchars {
    background-color:#99ff99;
    font-weight:bolder;
}
.diffremovedchars {
    background-color:#ff9999;
    text-decoration: line-through;
    font-weight:bolder;
}

.greybackground {
    background: #f0f0f0
}

.greybox {
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.borderedGreyBox {
    border: 1px solid #cccccc;
    background-color: #f0f0f0;
    padding: 10px;
}

.greyboxfilled {
 	border: 1px solid #ddd;
    background: #f0f0f0;
    padding: 3px;
	margin: 1px 1px 10px 1px;
}

.navBackgroundBox {
    padding: 5px 5px 5px 5px;
    font-size: 22px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: white;
    background: #3c78b5;
    text-decoration: none;
}

.previewBoxTop {
	background-color: #f0f0f0;
    border-width: 1px 1px 0px 1px;
    border-style: solid;
    border-color: #3c78b5;
    padding: 5px;
    margin: 5px 0px 0px 0px;
    text-align: center;
}
.previewContent {
    background-color: #fff;
 	border-color: #3c78b5;
	border-width: 0px 1px 0px 1px;
	border-style: solid;
	padding: 10px;
	margin: 0px;
}
.previewBoxBottom {
	background-color: #f0f0f0;
    border-width: 0px 1px 1px 1px;
    border-style: solid;
    border-color: #3c78b5;
    padding: 5px;
    margin: 0px 0px 5px 0px;
    text-align: center;
}

.functionbox {
    background-color: #f0f0f0;
 	border: 1px solid #3c78b5;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.functionbox-greyborder {
    background-color: #f0f0f0;
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.search-highlight {
    background-color: #ffffcc;
}

/* normal (white) background */
.rowNormal {
    background-color: #ffffff;
 }

/* alternate (pale yellow) background */
.rowAlternate {
    background-color: #f7f7f7;
}

/* used in the list attachments table */
.rowAlternateNoBottomColor {
    background-color: #f7f7f7;
}

.rowAlternateNoBottomNoColor {
}

.rowAlternateNoBottomColor td {
    border-bottom: 0px;
}

.rowAlternateNoBottomNoColor td {
    border-bottom: 0px;
}

/* row highlight (grey) background */
.rowHighlight {
    background-color: #f0f0f0;

}

TD.greenbar {FONT-SIZE: 2px; BACKGROUND: #00df00; BORDER: 1px solid #9c9c9c; PADDING: 0px; }
TD.redbar {FONT-SIZE: 2px; BACKGROUND: #df0000; BORDER: 1px solid #9c9c9c; PADDING: 0px; }
TD.darkredbar {FONT-SIZE: 2px; BACKGROUND: #af0000; BORDER: 1px solid #9c9c9c; PADDING: 0px; }

TR.testpassed {FONT-SIZE: 2px; BACKGROUND: #ddffdd; PADDING: 0px; }
TR.testfailed {FONT-SIZE: 2px; BACKGROUND: #ffdddd; PADDING: 0px; }

.toolbar  {
    margin: 0px;
    border-collapse: collapse;
}

.toolbar td  {
    border: 1px solid #ccc;
    padding: 2px 2px 2px 2px;
    color: #ccc;
}

td.noformatting {
    border-width: 0px;
    border-style: none;
    text-align: center;
	padding: 0px;
}

.commentblock {
    margin: 12px 0 12px 0;
}

/*
 * Divs displaying the license information, if necessary.
 */
.license-eval, .license-none, .license-nonprofit {
    border-top: 1px solid #bbbbbb;
    text-align: center;
    font-size: 10px;
    font-family: Verdana, Arial, Helvetica, sans-serif;
}

.license-eval, .license-none {
    background-color: #ffcccc;
}

.license-eval b, .license-none b {
    color: #990000
}

.license-nonprofit {
    background-color: #ffffff;
}

/*
 * The shadow at the bottom of the page between the main content and the
 * "powered by" section.
 */
.bottomshadow {
    height: 12px;
    background-image: url("$req.contextPath/images/border/border_bottom.gif");
    background-repeat: repeat-x;
}

/*
 * Styling of the operations box
 */
.navmenu .operations li, .navmenu .operations ul {
    list-style: none;
    margin-left: 0;
    padding-left: 0;
}

.navmenu .operations ul {
    margin-bottom: 9px;
}

.navmenu .label {
    font-weight: inherit;
}

/*
 * Styling of ops as a toolbar
 */
.toolbar div {
    display: none;
}

.toolbar .label {
    display: none;
}

.toolbar .operations {
    display: block;
}

.toolbar .operations ul {
    display: inline;
    list-style: none;
    margin-left: 10px;
    padding-left: 0;
}

.toolbar .operations li {
    list-style: none;
    display: inline;
}

/* list page navigational tabs */
#foldertab {
padding: 3px 0px 3px 8px;
margin-left: 0;
border-bottom: 1px solid #3c78b5;
font: bold 11px Verdana, sans-serif;
}

#foldertab li {
list-style: none;
margin: 0;
display: inline;
}

#foldertab li a {
padding: 3px 0.5em;
margin-left: 3px;
border: 1px solid #3c78b5;
border-bottom: none;
background: #3c78b5;
text-decoration: none;
}

#foldertab li a:link { color: #ffffff; }
#foldertab li a:visited { color: #ffffff; }

#foldertab li a:hover {
color: #ffffff;
background: #003366;
border-color: #003366;
}

#foldertab li a.current {
background: white;
border-bottom: 1px solid white;
color: black;
}

#foldertab li a.current:link { color: black; }
#foldertab li a.current:visited { color: black; }
#foldertab li a.current:hover {
background: white;
border-bottom: 1px solid white;
color: black;
}

/* alphabet list */
ul#squaretab {
margin-left: 0;
padding-left: 0;
white-space: nowrap;
font: bold 8px Verdana, sans-serif;
}

#squaretab li {
display: inline;
list-style-type: none;
}

#squaretab a {
padding: 2px 6px;
border: 1px solid #3c78b5;
}

#squaretab a:link, #squaretab a:visited {
color: #fff;
background-color: #3c78b5;
text-decoration: none;
}

#squaretab a:hover {
color: #ffffff;
background-color: #003366;
border-color: #003366;
text-decoration: none;
}

#squaretab li a#current {
background: white;
color: black;
}

.blogcalendar * {
    font-family:verdana, arial, sans-serif;
    font-size:x-small;
    font-weight:normal;
    line-height:140%;
    padding:2px;
}


table.blogcalendar {
    border: 1px solid #3c78b5;
}

.blogcalendar th.calendarhead, a.calendarhead {
    font-size:x-small;
    font-weight:bold;
    padding:2px;
    text-transform:uppercase;
    background-color: #3c78b5;
    color: #ffffff;
    letter-spacing: .3em;
    text-transform: uppercase;
}

.calendarhead:visited {color: white;}
.calendarhead:active {color: white;}
.calendarhead:hover {color: white;}

.blogcalendar th {
    font-size:x-small;
    font-weight:bold;
    padding:2px;
    background-color:#f0f0f0;
}

.blogcalendar td {
    font-size:x-small;
    font-weight:normal;
}

.searchGroup { padding: 0 0 10px 0; background: #f0f0f0; }
.searchGroupHeading { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #3c78b5; padding: 2px 4px 1px 4px; }
.searchItem { padding: 1px 4px 1px 4px; }
.searchItemSelected { padding: 1px 4px 1px 4px; font-weight: bold; background: #ddd; }

/* permissions page styles */
.permissionHeading {
    border-bottom: #bbb; border-width: 0 0 1px 0; border-style: solid; font-size: 16px; text-align: left;
}
.permissionTab {
    border-width: 0 0 0 1px; border-style: solid; background: #3c78b5; color: #ffffff; font-size: 10px;
}
.permissionSuperTab {
    border-width: 0 0 0 1px; border-style: solid; background: #003366; color: #ffffff;
}
.permissionCell {
    border-left: #bbb; border-width: 0 0 0 1px; border-style: solid;
}

/* warning panel */
.warningPanel { background: #FFFFCE; border:#F0C000 1px solid; padding: 8px; margin: 10px; }
/* alert panel */
.alertPanel { background: #FFCCCC; border:#C00 1px solid; padding: 8px; margin: 10px; }
/* info panel */
.infoPanel { background: #D8E4F1; border:#3c78b5 1px solid; padding: 8px; margin: 10px; }

/* side menu highlighting (e.g. space content screen) */
.optionPadded { padding: 2px; }
.optionSelected { background-color: #ffffcc; padding: 2px; border: 1px solid #ddd; margin: -1px; }
.optionSelected a { font-weight: bold; text-decoration: none; color: black; }

/* information macros */
.noteMacro { border-style: solid; border-width: 1px; border-color: #F0C000; background-color: #FFFFCE; text-align:left; margin-top: 5px; margin-bottom: 5px}
.warningMacro { border-style: solid; border-width: 1px; border-color: #c00; background-color: #fcc; text-align:left; margin-top: 5px; margin-bottom: 5px}
.infoMacro { border-style: solid; border-width: 1px; border-color: #3c78b5; background-color: #D8E4F1; text-align:left; margin-top: 5px; margin-bottom: 5px}
.tipMacro { border-style: solid; border-width: 1px; border-color: #090; background-color: #dfd; text-align:left; margin-top: 5px; margin-bottom: 5px}
.informationMacroPadding { padding: 5px 0 0 5px; }

table.infoMacro td, table.warningMacro td, table.tipMacro td, table.noteMacro td, table.sectionMacro td {
    border: none;
}

table.sectionMacroWithBorder td.columnMacro { border-style: dashed; border-width: 1px; border-color: #cccccc;}

.pagecontent
{
    padding: 10px;
    text-align: left;
}

/* styles for links in the top bar */
.topBarDiv a:link {color: #ffffff;}
.topBarDiv a:visited {color: #ffffff;}
.topBarDiv a:active {color: #ffffff;}
.topBarDiv a:hover {color: #ffffff;}
.topBarDiv {color: #ffffff;}

.topBar {
    background-color: #003366;
}


/* styles for extended operations */
.greyLinks a:link {color: #666666; text-decoration:underline;}
.greyLinks a:visited {color: #666666; text-decoration:underline;}
.greyLinks a:active {color: #666666; text-decoration:underline;}
.greyLinks a:hover {color: #666666; text-decoration:underline;}
.greyLinks {color: #666666; display:block; padding: 10px}

.logoSpaceLink {color: #999999; text-decoration: none}
.logoSpaceLink a:link {color: #999999; text-decoration: none}
.logoSpaceLink a:visited {color: #999999; text-decoration: none}
.logoSpaceLink a:active {color: #999999; text-decoration: none}
.logoSpaceLink a:hover {color: #003366; text-decoration: none}

/* basic panel (basicpanel.vmd) style */
.basicPanelContainer {border: 1px solid #3c78b5; margin-top: 2px; margin-bottom: 8px; width: 100%}
.basicPanelTitle {padding: 5px; margin: 0px; background-color: #f0f0f0; color: black; font-weight: bold;}
.basicPanelBody {padding: 5px; margin: 0px}

.separatorLinks a:link {color: white}
.separatorLinks a:visited {color: white}
.separatorLinks a:active {color: white}

.greynavbar {background-color: #f0f0f0; border-top: 1px solid #3c78b5; margin-top: 2px}

div.headerField {
    float: left;
    width: auto;
    height: 100%;
}

.headerFloat {
    margin-left: auto;
    width: 50%;
}

.headerFloatLeft {
    float: left;
    margin-right: 20px;
    margin-bottom: 10px;
}

#headerRow {
    padding: 10px;
}

div.license-personal {
   background-color: #003366;
   color: #ffffff;
}

div.license-personal a {
   color: #ffffff;
}

.greyFormBox {
    border: 1px solid #cccccc;
    padding: 5px;
}

/* IE automatically adds a margin before and after form tags. Use this style to remove that */
.marginlessForm {
    margin: 0px;
}

.openPageHighlight {
    background-color: #ffffcc;
    padding: 2px;
    border: 1px solid #ddd;
}

.editPageInsertLinks, .editPageInsertLinks a
{
    color: #666666;
    font-weight: bold;
    font-size: 10px;
}

/* Style for label heatmap. */
.top10 a {
    font-weight: bold;
    font-size: 2em;
    color: #003366;
}
.top25 a {
    font-weight: bold;
    font-size: 1.6em;
    color: #003366;
}
.top50 a {
    font-size: 1.4em;
    color: #003366;
}
.top100 a {
    font-size: 1.2em;
    color: #003366;
}

.heatmap {
    list-style:none;
    width: 95%;
    margin: 0px auto;
}

.heatmap a {
    text-decoration:none;
}

.heatmap a:hover {
    text-decoration:underline;
}

.heatmap li {
    display: inline;
}

.minitab {
padding: 3px 0px 3px 8px;
margin-left: 0;
margin-top: 1px;
margin-bottom: 0px;
border-bottom: 1px solid #3c78b5;
font: bold 9px Verdana, sans-serif;
text-decoration: none;
float:none;
}
.selectedminitab {
padding: 3px 0.5em;
margin-left: 3px;
margin-top: 1px;
border: 1px solid #3c78b5;
background: white;
border-bottom: 1px solid white;
color: #000000;
text-decoration: none;
}
.unselectedminitab {
padding: 3px 0.5em;
margin-left: 3px;
margin-top: 1px;
border: 1px solid #3c78b5;
border-bottom: none;
background: #3c78b5;
color: #ffffff;
text-decoration: none;
}

a.unselectedminitab:hover {
color: #ffffff;
background: #003366;
border-color: #003366;
}

a.unselectedminitab:link { color: white; }
a.unselectedminitab:visited { color: white; }

a.selectedminitab:link { color: black; }
a.selectedminitab:visited { color: black; }

.linkerror { background-color: #fcc;}

a.labelOperationLink:link {text-decoration: underline}
a.labelOperationLink:active {text-decoration: underline}
a.labelOperationLink:visited {text-decoration: underline}
a.labelOperationLink:hover {text-decoration: underline}

a.newLabel:link {background-color: #ddffdd}
a.newLabel:active {background-color: #ddffdd}
a.newLabel:visited {background-color: #ddffdd}
a.newLabel:hover {background-color: #ddffdd}

ul.square {list-style-type: square}

.inline-control-link {
    background: #ffc;
    font-size: 9px;
    color: #666;
    padding: 2px;
    text-transform: uppercase;
    text-decoration: none;
}


.inline-control-link a:link {text-decoration: none}
.inline-control-link a:active {text-decoration: none}
.inline-control-link a:visited {text-decoration: none}
.inline-control-link a:hover {text-decoration: none}

.inline-control-link {
    background: #ffc;
    font-size: 9px;
    color: #666;
    padding: 2px;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
}

div.auto_complete {
    width: 350px;
    background: #fff;
}
div.auto_complete ul {
    border: 1px solid #888;
    margin: 0;
    padding: 0;
    width: 100%;
    list-style-type: none;
}
div.auto_complete ul li {
    margin: 0;
    padding: 3px;
}
div.auto_complete ul li.selected {
    background-color: #ffb;
}
div.auto_complete ul strong.highlight {
    color: #800;
    margin: 0;
    padding: 0;
}

/******* Edit Page Styles *******/
.toogleFormDiv{
    border:1px solid #A7A6AA;
    background-color:white;
    padding:5px;
    margin-top: 5px;
}

.toogleInfoDiv{
    border:1px solid #A7A6AA;
    background-color:white;
    display:none;
    padding:5px;
    margin-top: 10px;
}

.inputSection{
    margin-bottom:20px;
}

#editBox{
   border:1px solid lightgray;
   background-color:#F0F0F0;
}

/******* Left Navigation Theme Styles ********/
.leftnav li a {
    text-decoration:none;
    color:white;
    margin:0px;
    display:block;
    padding:2px;
    padding-left:5px;
    background-color: #3c78b5;
    border-top:1px solid #3c78b5;
}

.leftnav li a:active {color:white;}
.leftnav li a:visited {color:white;}
.leftnav li a:hover {background-color: #003366; color:white;}

/* Added by Shaun during i18n */
.replaced
{
    background-color: #33CC66;
}

.topPadding
{
    margin-top: 20px;
}

/* new form style */
.form-block {
    padding: 6px;
}
.form-error-block {
    padding: 6px;
    background: #fcc;
    border-top: #f0f0f0 1px solid;
    border-bottom: #f0f0f0 1px solid;
    margin-bottom: 6px;
    padding: 0 12px 0 12px;
}
.form-element-large {
    font-size: 16px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
}

.form-element-small {
    font-size: 12px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
}

.form-header {
    background: lightyellow;
    border-top: #f0f0f0 1px solid;
    border-bottom: #f0f0f0 1px solid;
    margin-bottom: 6px;
    padding: 0 12px 0 12px;
}
.form-header p, .form-block p, .form-error-block p {
    line-height: normal;
    margin: 12px 0 12px 0;
}
.form-example {
    color: #888;
    font-size: 11px;
}
.form-divider {
    border-bottom: #ccc 1px solid;
    margin-bottom: 6px;
}
.form-buttons {
    margin-top: 6px;
    border-top: #ccc 1px solid;
    border-bottom: #ccc 1px solid;
    background: #f0f0f0;
    padding: 10px;
    text-align: center;
}
.form-buttons input {
    width: 100px;
}
.form-block .error {
    padding: 6px;
    margin-bottom: 6px;
}
    -->
    </style>
</head>
<body>

<div id="PageContent">
<table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%"><tr>
<td valign="top" class="pagebody">

    <div class="pageheader">
        <span class="pagetitle">
            Page Edited :
            <a href="http://cwiki.apache.org/confluence/display/SM">SM</a> :
            <a href="http://cwiki.apache.org/confluence/display/SM/BeanFlow">BeanFlow</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/SM/BeanFlow">BeanFlow</a>
        has been edited by             <a href="http://cwiki.apache.org/confluence/display/~gnodet">Guillaume Nodet</a>
            <span class="smallfont">(Apr 14, 2008)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=39135&originalVersion=46&revisedVersion=47">(View changes)</a>
     </p>

    <span class="label">Content:</span><br/>
    <div class="greybox wiki-content"><p><b>BeanFlow</b> is a lightweight Java library for building workflows using beans to orchestrate events. You can think of BeanFlow as a simple alternative to <a href="/confluence/display/SM/BPEL" title="BPEL">BPEL</a> where the workflows are all specified and implemented using Java code rather than declarative XML.</p>

<h3><a name="BeanFlow-QuickLinks"></a>Quick Links</h3>

<ul>
	<li><span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/" title="Visit page outside Confluence" rel="nofollow">BeanFlow JavaDoc<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
	<li><a href="/confluence/display/SM/BeanFlow+Patterns" title="BeanFlow Patterns">BeanFlow Patterns</a></li>
	<li><span class="nobr"><a href="http://svn.apache.org/repos/asf/servicemix/smx3/trunk/common/servicemix-beanflow/" title="Visit page outside Confluence" rel="nofollow">BeanFlow Source Code<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
</ul>


<h3><a name="BeanFlow-Motivation"></a>Motivation</h3>

<p>When building highly concurrent or distributed applications it is very common for there to be many events happening; often asynchronously and in different threads and its very common to need to perform kinds of workflow or orchestration across these events.</p>

<p>Now you certainly can use things like <a href="/confluence/display/SM/BPEL" title="BPEL">BPEL</a> to solve these kinds of problems. However often this is a bit heavy weight &amp; complex and you just want to have a bean based workflow using regular Java code to represent the activities involved in the workflow.</p>

<h3><a name="BeanFlow-Transformingthetraditionalworkflowapproach"></a>Transforming the traditional workflow approach</h3>

<p>One of the main goals of BeanFlow is to reuse what the Java platform is good for in the workflow space; then supplement it with missing abstractions rather than inventing the wheel in a sub-optimal way.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Traditional approach</th>
<th class='confluenceTh'>BeanFlow approach</th>
</tr>
<tr>
<td class='confluenceTd'> use a declarative workflow language to specify a workflow </td>
<td class='confluenceTd'> write a Java class </td>
</tr>
<tr>
<td class='confluenceTd'> use XML markup or pictures to define loops and flows </td>
<td class='confluenceTd'> use regular Java code (if/for/while) </td>
</tr>
<tr>
<td class='confluenceTd'> implement a generic state and persistence framework for workflow instances </td>
<td class='confluenceTd'> use regular Java fields in your workflow class, then use JDBC/DAO/JPA to deal with persistence </td>
</tr>
</tbody></table>

<h3><a name="BeanFlow-Usecases"></a>Use cases</h3>

<p>When working with concurrent or distributed applications there are many use cases for needing to orchestrate among multiple concurrent events. Here are a few examples from our use cases implementing <a href="/confluence/display/SM/Home" title="Home">ServiceMix</a> and <span class="nobr"><a href="http://activemq.org" title="Visit page outside Confluence" rel="nofollow">ActiveMQ<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<ul>
	<li>starting dependent services; where a parent component is dependent on the child components starting; where the start process may be asynchronous in different threads. e.g. there may be a recovery process on startup which you need to wait for.</li>
	<li>implementing master-slave type protocols where you need to monitor the state of the master and slave to make decisions on what to do; together with dealing with transitions from <em>Started</em> to <em>Recovering</em> to <em>Running</em> then maybe to <em>FailingOver</em> etc.</li>
	<li>implementing message orchestration. You may want to implement some simple orchestrations, waiting for either a response to arrive or a timeout to fire etc</li>
</ul>


<h2><a name="BeanFlow-Codeoverview"></a>Code overview</h2>

<p>First we'll give an overview of the two main interfaces in BeanFlow then we'll progress to concepts like timeouts and composing activities.</p>

<h3><a name="BeanFlow-Stateclass"></a>State class</h3>

<p>We have a <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/State.html" title="Visit page outside Confluence" rel="nofollow">State&lt;T&gt;<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> interface which is identical to the <span class="nobr"><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/atomic/AtomicReference.html" title="Visit page outside Confluence" rel="nofollow">AtomicReference&lt;T&gt;<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> interface included in java.util.concurrent in Java 5 apart from that it allows you to register listeners to the state. This makes it easy to respond to the changes in state.</p>

<p>One added detail is the that State&lt;T&gt; allows you to specify the <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/support/Notifier.html" title="Visit page outside Confluence" rel="nofollow">Notifier<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> implementation used to perform the notifications (which always occur outside of the semaphore to allow things to be re-entrant).</p>

<p>The default notifier used is the <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/support/SynchronousNotifier.html" title="Visit page outside Confluence" rel="nofollow">SynchronousNotifier<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> but its easy to switch to an <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/support/AsynchronousNotifier.html" title="Visit page outside Confluence" rel="nofollow">AsynchronousNotifier<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> by just passing it into the constructor of the State&lt;T&gt; object.</p>

<h3><a name="BeanFlow-Activityclass"></a>Activity class</h3>

<p>An activity is just a POJO which implements the <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/Activity.html" title="Visit page outside Confluence" rel="nofollow">Activity<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> interface; it has a simple lifecycle, you can start them and stop them and ask their status.</p>

<p>Once a flow has been started via the <b>start()</b> method it can take an arbitrarily long time to complete; you can see if the flow has completed via the <b>isStopped()</b> method. You can explicitly complete a flow using the <b>stop()</b> method whenever you like; typically when you are responding to state changes.</p>

<p>An activity could fail for some reason (such as it timed out or some error occurred) so there is a method <b>isFailed()</b> which can be used to easily inspect the activity. Rather like the <b>stop()</b> method, you can call <b>fail(reason)</b> if you wish to terminate an activity with the activity marked as the Failed rather than Stopped state.</p>

<h3><a name="BeanFlow-Usingtimeouts"></a>Using timeouts</h3>

<p>Its very common to add timeouts onto activities so that if the activity is not complete by a certain time then the activity is stopped &amp; failed; often another parent activity may then do something differently if one of its child activities fails.</p>

<p>There is a useful base activity called <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/TimeoutActivity.html" title="Visit page outside Confluence" rel="nofollow">TimeoutActivity<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which you can derive from to make your own activity which can be started/stopped/failed and which can be timed out.</p>

<p>You can explicitly register the activity with a timer and call the <b>onTimedOut()</b> method yourself or just call the <b>startWithTimeout()</b> method to start the activity registering the timeout.</p>

<h3><a name="BeanFlow-Composingactivities"></a>Composing activities</h3>

<p>One of the main reasons for using an object orientated language is to make composition and reuse possible; similarly BeanFlow allows you to compose activities together to make modular and reusable workflow constructs easily. So BeanFlow attempts to create a collection of reusable activities which you can then use to derive from or aggregate to make whatever activities you need.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Composition Activities</th>
<th class='confluenceTh'>Description</th>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/JoinAll.html" title="Visit page outside Confluence" rel="nofollow">JoinAll<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> </td>
<td class='confluenceTd'>Performs a join on all the given child activities. So the activity waits until all the child activities have completed, then it completes itself. You can add additional constraints to the activity using derivation. The default is to wait for all the child activities to complete; though you can enable fast-fail mode so that the activity fails as soon as a child activity fails</td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/JoinQuorum.html" title="Visit page outside Confluence" rel="nofollow">JoinQuorum<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> </td>
<td class='confluenceTd'>This activity is useful for implementing clustering style activities where you want a quorum of activities to complete. e.g. if you have 5 child activities you want to wait for at least 3 activities to complete succesfully before continuing</td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/AsynchronousActivity.html" title="Visit page outside Confluence" rel="nofollow">AsynchronousActivity<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> </td>
<td class='confluenceTd'>Executes any Runnable or Callable on an Executor and complete the activity when it has completed so that it can be used in joins</td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/ParallelActivity.html" title="Visit page outside Confluence" rel="nofollow">ParallelActivity<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> </td>
<td class='confluenceTd'>Allows a collection of parallel Runnable or Callable objects to be performed on an Executor then performing some kind of join on them completing</td>
</tr>
</tbody></table>

<p>Here is an example of performing joins using collections of child workflows</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// lets create a join on a number of child flows completing
</span>JoinAll flow = <span class="code-keyword">new</span> JoinAll(child1, child2, child3);
flow.startWithTimeout(timer, timeout);

<span class="code-comment">// now lets test the flow
</span>child1.stop();
assertStarted(flow);

child2.stop();
assertStarted(flow);

child3.stop();
assertStopped(flow);</pre>
</div></div>

<h3><a name="BeanFlow-Joinconditions"></a>Join conditions</h3>

<p>In workflows you often want to fork parallel steps and then join on certain events. You often have complex logic to decide on what the join condition is. e.g. in pseudo code</p>

<div class="code"><div class="codeContent">
<pre class="code-java">fork steps A, B, C
join on A and (B or C)</pre>
</div></div>

<p>In BeanFlow we implement join conditions using regular Java code. The basic idea is that a Activity will listen to changes in a number of different <b>State</b> objects such as fields a, b and c. You can then write an activity bean to perform the join condition you need. When the condition is met you can then perform whatever logic you wish such as</p>

<ul>
	<li>stopping the activity</li>
	<li>forking off a new child activity</li>
	<li>changing your state</li>
	<li>changing the state of some other bean</li>
	<li>calling arbitrary Java code</li>
</ul>


<p>Here is an example activity implemented in Java code for the above code.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// lets create some child workflows
</span><span class="code-keyword">final</span> Activity a = <span class="code-keyword">new</span> TimeoutActivity();
<span class="code-keyword">final</span> Activity b = <span class="code-keyword">new</span> TimeoutActivity();
<span class="code-keyword">final</span> Activity c = <span class="code-keyword">new</span> TimeoutActivity();

<span class="code-comment">// lets create the activity with a custom join condition
</span>Activity activity = <span class="code-keyword">new</span> JoinSupport(a, b, c) {
    @Override
    <span class="code-keyword">protected</span> void onChildStateChange(<span class="code-object">int</span> childCount, <span class="code-object">int</span> stoppedCount, <span class="code-object">int</span> failedCount) {

        <span class="code-keyword">if</span> (a.isStopped() &amp;&amp; (b.isStopped() || c.isStopped())) {
            <span class="code-comment">// lets stop the activity we're done
</span>            stop();
        }
    }
};

<span class="code-comment">// lets start the activities
</span>activity.startWithTimeout(timer, timeout);

<span class="code-comment">// now lets test things behave properly
</span>assertStarted(activity);

a.stop();
assertStarted(activity);

b.stop();
assertStopped(activity);</pre>
</div></div>

<h2><a name="BeanFlow-Buildingworkflows"></a>Building workflows</h2>

<p>So we've been over the basics of activities and showed how we can perform joins along with compose them. Remember they are just Java bean so you can implement them however you wish.</p>

<p>However often folks think of workflows as a number of discrete steps; using a kind of state machine to move from step to step. One real simple approach to<br/>
writing workflows in this model is to use a specific method for each workflow step.</p>

<p>So we have a base class called <span class="nobr"><a href="http://servicemix.apache.org/maven/servicemix-beanflow/apidocs/org/apache/servicemix/beanflow/Workflow.html" title="Visit page outside Confluence" rel="nofollow">Workflow<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which adds a new State object for the current step (which allows actvities to listen to the step changing) together with helper methods for moving to different steps, for suspending and so forth.</p>

<h3><a name="BeanFlow-Movingsteps"></a>Moving steps</h3>

<p>Inside a step you can call any Java methods on any objects. However to move from step to step in a declarative fashion you can call the <b>setNextStep()</b> method.<br/>
Another option is to use a method which returns a String or enum value; a non-null value is then interpreted as being the next step that is navigated to next.</p>

<p>Note that the movement to the next step always takes place outside of the step method to avoid deeply recursive methods.</p>

<h3><a name="BeanFlow-Suspendingworkflows"></a>Suspending workflows</h3>

<p>Often in a workflow you have to wait for some external event such as</p>
<ul>
	<li>a user enters some text</li>
	<li>a message is received</li>
</ul>


<p>Once that happens you re-awaken the workflow and commence execution at some step. To implement this just call the setNextStep() method to cause the workflow to resume at the given step</p>

<h3><a name="BeanFlow-SimpleExample"></a>Simple Example</h3>

<p>There now follows a simple workflow example...</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class SimpleWorkflow <span class="code-keyword">extends</span> Workflow&lt;SimpleWorkflow.Step&gt; {

    <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">enum</span> Step {
        stepA, stepB, stepC, stop
    };

    <span class="code-keyword">public</span> SimpleWorkflow() {
        <span class="code-keyword">super</span>(Step.stepA);
    }

    <span class="code-comment">// Workflow steps
</span>    <span class="code-comment">// -------------------------------------------------------------------------
</span>    <span class="code-keyword">public</span> Step stepA() {
        <span class="code-keyword">return</span> Step.stepB;
    }
    
    <span class="code-keyword">public</span> Step stepB() {
        <span class="code-keyword">return</span> Step.stepC;
    }
    
    <span class="code-keyword">public</span> Step stepC() {
        <span class="code-keyword">return</span> Step.stop;
    }
}</pre>
</div></div>

<p>As you can see the step is defined by an enumeration <b>Step</b> and we have a regular Java method to implement each step. The <em>step method</em> can then return the step to go to next after the current method terminates. If you return null or use a void method then the workflow suspends. </p>

<h3><a name="BeanFlow-CompleteExample"></a>Complete Example</h3>

<p>The following example is a fairly large one, but it shows a variety of different concepts</p>

<ul>
	<li>suspending workflows (such as when they wait for external events such as user input or an asynchronous message to arrive)</li>
	<li>looping &amp; using predicates</li>
	<li>forking and joining child activities</li>
	<li>declaratively moving from one step to another</li>
</ul>


<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class ExampleWorkflow <span class="code-keyword">extends</span> Workflow&lt;ExampleWorkflow.Step&gt; {
    <span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> Log log = LogFactory.getLog(ExampleWorkflow.class);

    <span class="code-keyword">private</span> <span class="code-object">int</span> loopCount;
    <span class="code-keyword">private</span> <span class="code-object">long</span> timeout = 500;
    <span class="code-keyword">private</span> <span class="code-object">String</span> userEmailAddress;

    <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">enum</span> Step {
        startStep, afterEnteredEmailStep, loopStep, waitForUserInputStep, forkStep, 
        aCompletedStep, abcCompletedStep, stop
    };

    <span class="code-keyword">public</span> ExampleWorkflow() {
        <span class="code-keyword">super</span>(Step.startStep);
    }

    <span class="code-comment">// Workflow steps
</span>    <span class="code-comment">// -------------------------------------------------------------------------
</span>
    <span class="code-keyword">public</span> void startStep() {
        <span class="code-comment">// lets use an explicit goTo() to tell the workflow
</span>        <span class="code-comment">// which step to go to next; though we can just <span class="code-keyword">return</span> Strings
</span>        addStep(Step.loopStep);
    }

    <span class="code-comment">// lets use the <span class="code-keyword">return</span> value to specify the next step
</span>    <span class="code-keyword">public</span> Step loopStep() {
        <span class="code-keyword">if</span> (++loopCount &gt; 3) {
            <span class="code-keyword">return</span> Step.waitForUserInputStep;
        }
        <span class="code-comment">// lets keep looping
</span>        <span class="code-keyword">return</span> Step.loopStep;
    }

    <span class="code-keyword">public</span> void waitForUserInputStep() {
        <span class="code-comment">// we are going to park here until a user
</span>        <span class="code-comment">// enters a valid email address
</span>        <span class="code-comment">// so lets park the workflow engine
</span>    }

    <span class="code-keyword">public</span> Step afterEnteredEmailStep() {
        <span class="code-comment">// we are going to park here until a user
</span>        <span class="code-comment">// enters a valid email address
</span>        log.info(<span class="code-quote">"User entered email address: "</span> + userEmailAddress);
        <span class="code-keyword">return</span> Step.forkStep;
    }

    <span class="code-keyword">public</span> void forkStep() {
        <span class="code-comment">// lets fork some child flows
</span>        TimeoutActivity a = <span class="code-keyword">new</span> TimeoutActivity();
        TimeoutActivity b = <span class="code-keyword">new</span> TimeoutActivity();
        TimeoutActivity c = <span class="code-keyword">new</span> TimeoutActivity();

        log.info(<span class="code-quote">"Forking off processes a, b, c"</span>);
        fork(a, b, c);

        <span class="code-comment">// now lets add some joins
</span>        joinAll(Step.aCompletedStep, timeout, a);
        joinAll(Step.abcCompletedStep, timeout, a, b, c);
    }

    <span class="code-keyword">public</span> void aCompletedStep() {
        log.info(<span class="code-quote">"child flow A completed!"</span>);
    }

    <span class="code-keyword">public</span> Step abcCompletedStep() {
        log.info(<span class="code-quote">"child flows A, B and C completed!"</span>);

        <span class="code-comment">// we are completely done now
</span>        <span class="code-keyword">return</span> Step.stop;
    }

    <span class="code-comment">// External events
</span>    <span class="code-comment">// -------------------------------------------------------------------------
</span>    <span class="code-keyword">public</span> void userEntered(<span class="code-object">String</span> emailAddress) {
        <span class="code-keyword">if</span> (emailAddress != <span class="code-keyword">null</span> &amp;&amp; emailAddress.indexOf(<span class="code-quote">"@"</span>) &gt; 0) {
            <span class="code-keyword">this</span>.userEmailAddress = emailAddress;

            log.info(<span class="code-quote">"Lets re-start the suspended workflow"</span>);
            addStep(Step.afterEnteredEmailStep);
        }
    }
}</pre>
</div></div>

<p>In the above example, each workflow step is implemented as a method. If the method returns a String it is interpreted as the next step which will be executed. Returning null (or using a void return type) will suspend the workflow.</p>

<p>You can also explicitly call suspend() or stop() yourself.</p>

<p>The setNextStep(step) will instruct the workflow engine to move to the given step.</p>

<h3><a name="BeanFlow-ValidatingWorkflows"></a>Validating Workflows</h3>

<p>To avoid typos between the workflow step enum and the methods in the workflow class, on startup we check that there are suitable methods available for the enum. Many thanks to <span class="nobr"><a href="http://www.javarants.com/" title="Visit page outside Confluence" rel="nofollow">Sam<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> for this idea! <img class="emoticon" src="/confluence/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/> e.g. the following bad workflow is automatically caught and a useful error is generated.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class BadWorkflow <span class="code-keyword">extends</span> Workflow&lt;BadWorkflow.Step&gt; {
    
    <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">enum</span> Step {
        startStep, fooStep, doesNotExistStep
    };

    <span class="code-keyword">public</span> BadWorkflow() {
        <span class="code-keyword">super</span>(Step.startStep);
    }

    <span class="code-comment">// Workflow steps
</span>    <span class="code-comment">// -------------------------------------------------------------------------
</span>    <span class="code-keyword">public</span> Step startStep() {
        <span class="code-keyword">return</span> Step.fooStep;
    }
    
    <span class="code-keyword">public</span> Step fooStep() {
        <span class="code-keyword">return</span> Step.doesNotExistStep;
    }
}</pre>
</div></div></div>


</td></tr></table></div>
<p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tr>
        <td height="12" background="http://cwiki.apache.org/confluence/images/border/border_bottom.gif"><img src="http://cwiki.apache.org/confluence/images/border/spacer.gif" width="1" height="1" border="0"/></td>
    </tr>
</table>

<div class="smalltext">
    Powered by
    <a href="http://www.atlassian.com/software/confluence/default.jsp?clicked=footer" class="smalltext">Atlassian Confluence</a>
    (Version: 2.2.9 Build:#527 Sep 07, 2006)
    -
    <a href="http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470" class="smalltext">Bug/feature request</a><br/>
    <br>
    <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action">Unsubscribe or edit your notifications preferences</a>

</div>

</body>
</html>


Mime
View raw message