camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel: Aggregator (page edited)
Date Tue, 17 Feb 2009 16:55: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/CAMEL">CAMEL</a> :
            <a href="http://cwiki.apache.org/confluence/display/CAMEL/Aggregator">Aggregator</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/CAMEL/Aggregator">Aggregator</a>
        has been edited by             <a href="http://cwiki.apache.org/confluence/display/~davsclaus">Claus Ibsen</a>
            <span class="smallfont">(Feb 17, 2009)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=60867&originalVersion=30&revisedVersion=31">(View changes)</a>
     </p>

    <span class="label">Content:</span><br/>
    <div class="greybox wiki-content"><h3><a name="Aggregator-Aggregator"></a>Aggregator</h3>

<p>The <span class="nobr"><a href="http://www.enterpriseintegrationpatterns.com/Aggregator.html" title="Visit page outside Confluence" rel="nofollow">Aggregator<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> from the <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">EIP patterns</a> allows you to combine a number of messages together into a single message. </p>

<p><img src="http://www.enterpriseintegrationpatterns.com/img/Aggregator.gif" align="absmiddle" border="0" /></p>

<p>A correlation <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> is used to determine the messages which should be aggregated together. If you want to aggregate all messages into a single message, just use a constant expression. An AggregationStrategy is used to combine all the message exchanges for a single correlation key into a single message exchange. The default strategy just chooses the latest message; so its ideal for throttling messages. </p>

<p>For example, imagine a stock market data system; you are receiving 30,000 messages per second; you may want to throttle down the updates as, say, a GUI cannot cope with such massive update rates. So you may want to aggregate these messages together so that within a window (defined by a maximum number of messages or a timeout), messages for the same stock are aggregated together; by just choosing the latest message and discarding the older prices. (You could apply a delta processing algorithm if you prefer to capture some of the history).</p>

<p><b>Using the <a href="/confluence/display/CAMEL/Fluent+Builders" title="Fluent Builders">Fluent Builders</a></b></p>

<p>The following example shows how to aggregate messages so that only the latest message for a specific value of the <b>cheese</b> header are sent.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// in <span class="code-keyword">this</span> route we aggregate all from direct:state based on the header id cheese
</span>from(<span class="code-quote">"direct:start"</span>).aggregate(header(<span class="code-quote">"cheese"</span>)).to(<span class="code-quote">"mock:result"</span>);

from(<span class="code-quote">"seda:header"</span>).setHeader(<span class="code-quote">"visited"</span>, constant(<span class="code-keyword">true</span>)).aggregate(header(<span class="code-quote">"cheese"</span>)).to(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">// in <span class="code-keyword">this</span> sample we aggregate using our own strategy with a completion predicate
</span><span class="code-comment">// stating that the aggregated header is equal to 5.
</span>from(<span class="code-quote">"direct:predicate"</span>).aggregate(header(<span class="code-quote">"cheese"</span>), <span class="code-keyword">new</span> MyAggregationStrategy()).
    completedPredicate(header(<span class="code-quote">"aggregated"</span>).isEqualTo(5)).to(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">// <span class="code-keyword">this</span> sample is similar to the one above but it also illustrates the use of outBatchSize 
</span><span class="code-comment">// to send exchanges to mock:endpoint in batches of 10.  
</span>from(<span class="code-quote">"direct:outBatchPredicate"</span>).aggregate(header(<span class="code-quote">"cheese"</span>), <span class="code-keyword">new</span> MyAggregationStrategy()).
    completedPredicate(header(<span class="code-quote">"aggregated"</span>).isEqualTo(5)).outBatchSize(10).to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<p>If you were using JMS then you may wish to use the JMSDestination header as the correlation key; or some custom header for the stock symbol (using the above stock market example).</p>

<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"activemq:someReallyFastTopic"</span>).aggregator(header(<span class="code-quote">"JMSDestination"</span>)).to(<span class="code-quote">"activemq:someSlowTopicForGuis"</span>);</pre>
</div></div>

<p>You can of course use many different <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> languages such as <a href="/confluence/display/CAMEL/XPath" title="XPath">XPath</a>, <a href="/confluence/display/CAMEL/XQuery" title="XQuery">XQuery</a>, <a href="/confluence/display/CAMEL/SQL" title="SQL">SQL</a> or various <a href="/confluence/display/CAMEL/Scripting+Languages" title="Scripting Languages">Scripting Languages</a>.  <br/>
Here is an example using <b>XPath</b>:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">//aggregate based on the message content using an XPath expression
</span><span class="code-comment">//example assumes an XML document starting with &lt;stockQuote symbol='...'&gt;
</span><span class="code-comment">//aggregate messages based on their symbol attribute within the &lt;stockQuote&gt; element
</span>from(<span class="code-quote">"seda:start"</span>).aggregate().xpath(<span class="code-quote">"/stockQuote/@symbol"</span>, <span class="code-object">String</span>.class).batchSize(5).to(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">//<span class="code-keyword">this</span> example will aggregate all messages starting with &lt;stockQuote symbol='APACHE'&gt; into 
</span><span class="code-comment">//one exchange and all the other messages (different symbol or different root element) into another exchange.
</span>from(<span class="code-quote">"seda:start"</span>).aggregate().xpath(<span class="code-quote">"name(/stockQuote[@symbol='APACHE'])"</span>, <span class="code-object">String</span>.class).batchSize(5).to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<p>For further examples of this pattern in use you could look at the <span class="nobr"><a href="http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/AggregatorTest.java?view=markup" title="Visit page outside Confluence" rel="nofollow">junit test case<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<p><b>Using the <a href="/confluence/display/CAMEL/Spring+XML+Extensions" title="Spring XML Extensions">Spring XML Extensions</a></b></p>

<table cellpadding='5' width='85%' cellspacing='8px' class='infoMacro' border="0" align='center'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>
<p>The correlationExpression element is in Camel 2.0. For earliler versions of Camel you will need to specify your expression without the enclosing correlationExpression element.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">&lt;aggregator&gt;
  &lt;simple&gt;header.cheese&lt;/simple&gt;
  &lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;
&lt;/aggregator&gt;</pre>
</div></div> </td></tr></table>

<p>The following example shows how to create a simple aggregator using the XML notation; using an <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> for the correlation value used to aggregate messages together.</p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext id=<span class="code-quote">"camel"</span> xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:start"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>

  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"seda:header"</span>/&gt;</span>
    <span class="code-tag">&lt;process ref=<span class="code-quote">"setHeaderProcessor"</span>/&gt;</span>
    <span class="code-tag">&lt;to uri=<span class="code-quote">"direct:temp"</span>/&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>

  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:temp"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>      
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>

  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:predicate"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate strategyRef=<span class="code-quote">"myAggregatorStrategy"</span>&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
      <span class="code-tag">&lt;completedPredicate&gt;</span>
        <span class="code-tag">&lt;method bean=<span class="code-quote">"myAggregatorStrategy"</span> method=<span class="code-quote">"isCompleted"</span>/&gt;</span>
      <span class="code-tag">&lt;/completedPredicate&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>
  
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:outBatchPredicate"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate strategyRef=<span class="code-quote">"myAggregatorStrategy"</span> outBatchSize=<span class="code-quote">"10"</span>&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
      <span class="code-tag">&lt;completedPredicate&gt;</span>
        <span class="code-tag">&lt;method bean=<span class="code-quote">"myAggregatorStrategy"</span> method=<span class="code-quote">"isCompleted"</span>/&gt;</span>
      <span class="code-tag">&lt;/completedPredicate&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>
  
  &lt;!--  This route turns off in batching by setting batchSize to 1 to run unit test for out batching.
        Normal use cases may not want to disable in batching
  --&gt;
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:outBatchNoInBatching"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate strategyRef=<span class="code-quote">"myAggregatorStrategy"</span> batchSize=<span class="code-quote">"1"</span> outBatchSize=<span class="code-quote">"10"</span>&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
      <span class="code-tag">&lt;completedPredicate&gt;</span>
        <span class="code-tag">&lt;method bean=<span class="code-quote">"myAggregatorStrategy"</span> method=<span class="code-quote">"isCompleted"</span>/&gt;</span>
      <span class="code-tag">&lt;/completedPredicate&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>
<span class="code-tag">&lt;/camelContext&gt;</span></pre>
</div></div>

<p>You can specify your own AggregationStrategy if you prefer as shown in the following example</p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext id=<span class="code-quote">"camel"</span> xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:start"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate strategyRef=<span class="code-quote">"aggregatorStrategy"</span>&gt;</span>
      <span class="code-tag">&lt;correlationExpression&gt;</span>
        <span class="code-tag">&lt;simple&gt;</span>header.cheese<span class="code-tag">&lt;/simple&gt;</span>
      <span class="code-tag">&lt;/correlationExpression&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>
<span class="code-tag">&lt;/camelContext&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"aggregatorStrategy"</span> class=<span class="code-quote">"org.apache.camel.spring.processor.MyAggregator"</span>/&gt;</span></pre>
</div></div>

<p>Notice how the <b>strategyRef</b> attribute is used on the <b>&lt;aggregator&gt;</b> element to refer to the custom strategy in Spring.</p>

<h3><a name="Aggregator-Batchoptions"></a>Batch options</h3>
<p>The aggregator supports the following batch options:</p>
<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Option </th>
<th class='confluenceTh'> Default </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> batchSize </td>
<td class='confluenceTd'> 100 </td>
<td class='confluenceTd'> The <b>in</b> batch size. This is the number of incoming exchanges that is processed by the aggregator and when this threshold is reached the batch is completed and send. </td>
</tr>
<tr>
<td class='confluenceTd'> outBatchSize </td>
<td class='confluenceTd'> 0 </td>
<td class='confluenceTd'> <b>Available as of Camel 1.5</b>. The <b>out</b> batch size. This is the number of exchanges currently aggregated in the <tt>AggregationCollection</tt>. When this threshold is reached the batch is completed and send. By default this option is disabled. The difference to the <tt>batchSize</tt> options is that this is for outgoing, so setting this size to e.g. 50 ensures that this batch will at maximum contain 50 exchanges when its sent. </td>
</tr>
<tr>
<td class='confluenceTd'> batchTimeout </td>
<td class='confluenceTd'> 1000L </td>
<td class='confluenceTd'> Timeout in millis. How long should the aggregator wait before its completed and sends whatever it has currently aggregated. </td>
</tr>
<tr>
<td class='confluenceTd'> groupExchanges </td>
<td class='confluenceTd'> false </td>
<td class='confluenceTd'> <b>Camel 2.-0</b>: If enabled then Camel will group all aggregated Exchanges into a single combined <tt>org.apache.camel.impl.GroupedExchange</tt> holder class that holds all the aggregated Exchanges. And as a result only one Exchange is being sent out from the aggregator. Can be used to combine many incomming Exchanges into a single output Exchange without coding a custom AggregationStrategy yourself. </td>
</tr>
</tbody></table>

<h3><a name="Aggregator-AggregationCollectionandAggregationStrategy"></a>AggregationCollection and AggregationStrategy</h3>

<p>This aggregator uses a AggregationCollection to store the exchanges that is currently aggregated. The AggregationCollection uses a correlation <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> and an AggregationStrategy.</p>
<ul class="alternate" type="square">
	<li>The correlation <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> is used to correlate the incoming exchanges. The default implementation will group messages based on the correlation expression. Other implementations could for instance just add all exchanges as a batch.</li>
	<li>The strategy is used for aggregate the old (lookup by its correlation id) and the new exchanges together into a single exchange. Possible implementations include performing some kind of combining or delta processing, such as adding line items together into an invoice or just using the newest exchange and removing old exchanges such as for state tracking or market data prices; where old values are of little use.</li>
</ul>


<p>Camel provides these implementations:</p>
<ul class="alternate" type="square">
	<li>DefaultAggregationCollection</li>
	<li>PredicateAggregationCollection</li>
	<li>UseLatestAggregationStrategy</li>
</ul>


<h3><a name="Aggregator-Examples"></a>Examples</h3>

<h4><a name="Aggregator-Defaultexample"></a>Default example</h4>
<p>By default Camel uses <tt>DefaultAggregationCollection</tt> and <tt>UseLatestAggregationStrategy</tt>, so this simple example will just keep the latest received exchange for the given correlation <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a>:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// our route is aggregating from the direct queue and sending the response to the mock
</span>from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// aggregated by header id
</span>    <span class="code-comment">// as we have not configured more on the aggregator it will <span class="code-keyword">default</span> to aggregate the
</span>    <span class="code-comment">// latest exchange only
</span>    .aggregate().header(<span class="code-quote">"id"</span>)
    <span class="code-comment">// wait <span class="code-keyword">for</span> 0.5 seconds to aggregate
</span>    .batchTimeout(500L)
    .to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<h4><a name="Aggregator-UsingPredicateAggregationCollection"></a>Using PredicateAggregationCollection</h4>
<p>The PredicateAggregationCollection is an extension to DefaultAggregationCollection that uses a <a href="/confluence/display/CAMEL/Predicate" title="Predicate">Predicate</a> as well to determine the completion. For instance the <a href="/confluence/display/CAMEL/Predicate" title="Predicate">Predicate</a> can test for a special header value, a number of maximum aggregated so far etc. To use this the routing is a bit more complex as we need to create our AggregationCollection object as follows:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// create the aggregation collection we will use.
</span><span class="code-comment">// - we will correlate the received message based on the id header
</span><span class="code-comment">// - as we will just keep the latest message we use the latest strategy
</span><span class="code-comment">// - and <span class="code-keyword">finally</span> we stop aggregate <span class="code-keyword">if</span> we receive 2 or more messages
</span>AggregationCollection ag = <span class="code-keyword">new</span> PredicateAggregationCollection(header(<span class="code-quote">"id"</span>),
    <span class="code-keyword">new</span> UseLatestAggregationStrategy(),
    header(Exchange.AGGREGATED_COUNT).isEqualTo(3));

<span class="code-comment">// our route is aggregating from the direct queue and sending the response to the mock
</span>from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// we use the collection based aggregator we already have configured
</span>    .aggregate(ag)
    <span class="code-comment">// wait <span class="code-keyword">for</span> 0.5 seconds to aggregate
</span>    .batchTimeout(500L)
    .to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>
<p>In this sample we use the predicate that we want at most 3 exchanges aggregated by the same correlation id, this is defined as:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">header(Exchange.AGGREGATED_COUNT).isEqualTo(3)</pre>
</div></div>
<p>Using this the aggregator will complete if we receive 3 exchanges with the same correlation id or when the specified timeout of 500 msecs has elapsed (whichever criteria is met first).</p>

<h4><a name="Aggregator-Usingcustomaggregationstrategy"></a>Using custom aggregation strategy</h4>
<p>In this example we will aggregate incoming bids and want to aggregate the highest bid. So we provide our own strategy where we implement the code logic:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">private</span> <span class="code-keyword">static</span> class MyAggregationStrategy <span class="code-keyword">implements</span> AggregationStrategy {

    <span class="code-keyword">public</span> Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        <span class="code-object">int</span> oldPrice = oldExchange.getIn().getBody(<span class="code-object">Integer</span>.class);
        <span class="code-object">int</span> newPrice = newExchange.getIn().getBody(<span class="code-object">Integer</span>.class);
        <span class="code-comment">// <span class="code-keyword">return</span> the <span class="code-quote">"winner"</span> that has the highest price
</span>        <span class="code-keyword">return</span> newPrice &gt; oldPrice ? newExchange : oldExchange;
    }
}</pre>
</div></div>

<p>Then we setup the routing as follows:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// our route is aggregating from the direct queue and sending the response to the mock
</span>from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// aggregated by header id and use our own strategy how to aggregate
</span>    .aggregate(<span class="code-keyword">new</span> MyAggregationStrategy()).header(<span class="code-quote">"id"</span>)
    <span class="code-comment">// wait <span class="code-keyword">for</span> 0.5 seconds to aggregate
</span>    .batchTimeout(500L)
    .to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<p>And since this is based on an unit test we show the test code that send the bids and what is expected as the <b>winners</b>:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">MockEndpoint result = getMockEndpoint(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">// we expect to find the two winners with the highest bid
</span>result.expectedMessageCount(2);
result.expectedBodiesReceived(<span class="code-quote">"200"</span>, <span class="code-quote">"150"</span>);

<span class="code-comment">// then we sent all the message at once
</span>template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"100"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"150"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"2"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"130"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"2"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"200"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"190"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);

assertMockEndpointsSatisfied();</pre>
</div></div>

<h4><a name="Aggregator-Usingcustomaggregationcollection"></a>Using custom aggregation collection</h4>
<p>In this example we will aggregate incoming bids and want to aggregate the bids in reverse order (this is just an example). So we provide our own collection where we implement the code logic:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">class MyReverseAggregationCollection <span class="code-keyword">extends</span> AbstractCollection&lt;Exchange&gt; <span class="code-keyword">implements</span> AggregationCollection {

    <span class="code-keyword">private</span> List&lt;Exchange&gt; collection = <span class="code-keyword">new</span> ArrayList&lt;Exchange&gt;();
    <span class="code-keyword">private</span> Expression correlation;
    <span class="code-keyword">private</span> AggregationStrategy strategy;

    <span class="code-keyword">public</span> Expression getCorrelationExpression() {
        <span class="code-keyword">return</span> correlation;
    }

    <span class="code-keyword">public</span> void setCorrelationExpression(Expression correlationExpression) {
        <span class="code-keyword">this</span>.correlation = correlationExpression;
    }

    <span class="code-keyword">public</span> AggregationStrategy getAggregationStrategy() {
        <span class="code-keyword">return</span> strategy;
    }

    <span class="code-keyword">public</span> void setAggregationStrategy(AggregationStrategy aggregationStrategy) {
        <span class="code-keyword">this</span>.strategy = aggregationStrategy;
    }

    <span class="code-keyword">public</span> <span class="code-object">boolean</span> add(Exchange exchange) {
        <span class="code-keyword">return</span> collection.add(exchange);
    }

    <span class="code-keyword">public</span> Iterator&lt;Exchange&gt; iterator() {
        <span class="code-comment">// demonstrate the we can <span class="code-keyword">do</span> something with <span class="code-keyword">this</span> collection, so we reverse it
</span>        Collections.reverse(collection);

        <span class="code-keyword">return</span> collection.iterator();
    }

    <span class="code-keyword">public</span> <span class="code-object">int</span> size() {
        <span class="code-keyword">return</span> collection.size();
    }

    <span class="code-keyword">public</span> void clear() {
        collection.clear();
    }

    <span class="code-keyword">public</span> void onAggregation(<span class="code-object">Object</span> correlationKey, Exchange newExchange) {
        add(newExchange);
    }
}</pre>
</div></div>

<p>Then we setup the routing as follows:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// our route is aggregating from the direct queue and sending the response to the mock
</span>from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// use our own collection <span class="code-keyword">for</span> aggregation
</span>    .aggregate(<span class="code-keyword">new</span> MyReverseAggregationCollection())
    <span class="code-comment">// wait <span class="code-keyword">for</span> 0.5 seconds to aggregate
</span>    .batchTimeout(500L)
    .to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<p>And since this is based on an unit test we show the test code that send the bids and what is expected as the expected reverse order:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">MockEndpoint result = getMockEndpoint(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">// we expect 5 messages since our custom aggregation collection just gets it all
</span><span class="code-comment">// but returns them in reverse order
</span>result.expectedMessageCount(5);
result.expectedBodiesReceived(<span class="code-quote">"190"</span>, <span class="code-quote">"200"</span>, <span class="code-quote">"130"</span>, <span class="code-quote">"150"</span>, <span class="code-quote">"100"</span>);

<span class="code-comment">// then we sent all the message at once
</span>template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"100"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"150"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"2"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"130"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"2"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"200"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);
template.sendBodyAndHeader(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"190"</span>, <span class="code-quote">"id"</span>, <span class="code-quote">"1"</span>);

assertMockEndpointsSatisfied();</pre>
</div></div>

<h5><a name="Aggregator-CustomaggregationcollectioninSpringDSL"></a>Custom aggregation collection in Spring DSL</h5>

<p>You can also specify a custom aggregation collection in the Spring DSL. Here is an example for Camel 2.0</p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext id=<span class="code-quote">"camel"</span> xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:start"</span>/&gt;</span>
    <span class="code-tag">&lt;aggregate batchTimeout=<span class="code-quote">"500"</span> collectionRef=<span class="code-quote">"aggregatorCollection"</span>&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/aggregate&gt;</span>
  <span class="code-tag">&lt;/route&gt;</span>
<span class="code-tag">&lt;/camelContext&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"aggregatorCollection"</span> class=<span class="code-quote">"org.apache.camel.processor.aggregator.MyReverseAggregationCollection"</span>/&gt;</span></pre>
</div></div>

<p>In Camel 1.5.1 you will need to specify the aggregator as</p>

<div class="code"><div class="codeContent">
<pre class="code-java">&lt;aggregator batchTimeout=<span class="code-quote">"500"</span> collectionRef=<span class="code-quote">"aggregatorCollection"</span>&gt;
  &lt;expression/&gt;
  &lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;
&lt;/aggregator&gt;</pre>
</div></div>

<h4><a name="Aggregator-UsingGroupedExchanges"></a>Using Grouped Exchanges</h4>
<p><b>Available as of Camel 2.0</b></p>

<p>You can enable grouped exchanges to combine all aggregated exchanges into a single <tt>org.apache.camel.impl.GroupedExchange</tt> holder class that contains all the individual aggregated exchanges. This allows you to process a single Exchange containing all the aggregated exchange. Lets start with how to configure this in the router:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-comment">// our route is aggregating from the direct queue and sending the response to the mock
</span>from(<span class="code-quote">"direct:start"</span>)
    <span class="code-comment">// aggregated using id as correlation so each is unqiue and thus we batch everything
</span>    .aggregate().simple(<span class="code-quote">"id"</span>)
    <span class="code-comment">// wait <span class="code-keyword">for</span> 0.5 seconds to aggregate
</span>    .batchTimeout(500L)
    <span class="code-comment">// group the exchanges so we get one single exchange containing all the others
</span>    .groupExchanges()
    .to(<span class="code-quote">"mock:result"</span>);</pre>
</div></div>

<p>And the next part is part of an unit code that demonstrates this feature as we send in 5 exchanges each with a different value in the body.<br/>
And we will only get 1 exchange out of the aggregator, but we can access all the individual aggregated exchanges using the <tt>GroupedExchange#get</tt> method.</p>
<div class="code"><div class="codeContent">
<pre class="code-java">MockEndpoint result = getMockEndpoint(<span class="code-quote">"mock:result"</span>);

<span class="code-comment">// we expect 1 messages since we group all we get in using the same correlation key
</span>result.expectedMessageCount(1);

<span class="code-comment">// then we sent all the message at once
</span>template.sendBody(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"100"</span>);
template.sendBody(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"150"</span>);
template.sendBody(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"130"</span>);
template.sendBody(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"200"</span>);
template.sendBody(<span class="code-quote">"direct:start"</span>, <span class="code-quote">"190"</span>);

assertMockEndpointsSatisfied();

Exchange out = result.getExchanges().get(0);
assertTrue(out <span class="code-keyword">instanceof</span> GroupedExchange);
GroupedExchange grouped = (GroupedExchange)out;
assertEquals(5, grouped.size());

assertEquals(<span class="code-quote">"100"</span>, grouped.get(0).getIn().getBody(<span class="code-object">String</span>.class));
assertEquals(<span class="code-quote">"150"</span>, grouped.get(1).getIn().getBody(<span class="code-object">String</span>.class));
assertEquals(<span class="code-quote">"130"</span>, grouped.get(2).getIn().getBody(<span class="code-object">String</span>.class));
assertEquals(<span class="code-quote">"200"</span>, grouped.get(3).getIn().getBody(<span class="code-object">String</span>.class));
assertEquals(<span class="code-quote">"190"</span>, grouped.get(4).getIn().getBody(<span class="code-object">String</span>.class));</pre>
</div></div>


<h4><a name="Aggregator-UsingThisPattern"></a>Using This Pattern</h4>

<p>If you would like to use this EIP Pattern then please read the <a href="/confluence/display/CAMEL/Getting+Started" title="Getting Started">Getting Started</a>, you may also find the <a href="/confluence/display/CAMEL/Architecture" title="Architecture">Architecture</a> useful particularly the description of <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> and <a href="/confluence/display/CAMEL/URIs" title="URIs">URIs</a>. Then you could try out some of the <a href="/confluence/display/CAMEL/Examples" title="Examples">Examples</a> first before trying this pattern out.</p>

<h3><a name="Aggregator-Seealso"></a>See also</h3>
<ul class="alternate" type="square">
	<li>The <a href="/confluence/display/CAMEL/Loan+Broker+Example" title="Loan Broker Example">Loan Broker Example</a> which uses an aggregator</li>
</ul>
</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