camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel: Book cookbook (page edited)
Date Wed, 10 Dec 2008 16:25: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/Book+cookbook">Book cookbook</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/CAMEL/Book+cookbook">Book cookbook</a>
        has been edited by             <a href="http://cwiki.apache.org/confluence/display/~janstey">Jonathan Anstey</a>
            <span class="smallfont">(Dec 10, 2008)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=99808&originalVersion=4&revisedVersion=5">(View changes)</a>
     </p>

    <span class="label">Content:</span><br/>
    <div class="greybox wiki-content"><div class="chapter" id="chapter-cook-book"></div>
<h1><a name="Bookcookbook-CookBook"></a>CookBook</h1>
<p>This document describes various recipes for working with Camel</p>
<ul>
	<li><a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a> describes how to work with beans and Camel in a loosely coupled way so that your beans do not have to depend on any Camel APIs</li>
	<li><a href="/confluence/display/CAMEL/Hiding+Middleware" title="Hiding Middleware">Hiding Middleware</a> describes how to avoid your business logic being coupled to any particular middleware APIs allowing you to easily switch from in JVM <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> to <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a>, <a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a>, <a href="/confluence/display/CAMEL/Hibernate" title="Hibernate">Hibernate</a>, <a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a>, <a href="/confluence/display/CAMEL/JDBC" title="JDBC">JDBC</a>, <a href="/confluence/display/CAMEL/iBATIS" title="iBATIS">iBatis</a> or <a href="/confluence/display/CAMEL/JavaSpace" title="JavaSpace">JavaSpace</a> etc.</li>
	<li><a href="/confluence/display/CAMEL/Visualisation" title="Visualisation">Visualisation</a> describes how to visualise your <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> to help you understand your routing rules</li>
	<li><a href="/confluence/display/CAMEL/BAM" title="BAM">Business Activity Monitoring (BAM)</a> for monitoring business processes across systems</li>
	<li><a href="/confluence/display/CAMEL/ETL" title="ETL">Extract Transform Load (ETL)</a> to load data into systems or databases</li>
	<li><a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a> for testing distributed and asynchronous systems using a messaging approach</li>
	<li><a href="/confluence/display/CAMEL/Templating" title="Templating">Templating</a> is a great way to create service stubs to be able to test your system without some back end system.</li>
	<li><a href="/confluence/display/CAMEL/Database" title="Database">Database</a> for working with databases</li>
	<li><a href="/confluence/display/CAMEL/Parallel+Processing+and+Ordering" title="Parallel Processing and Ordering">Parallel Processing and Ordering</a> on how using parallel processing and <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> or <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> based load balancing can be achieved.</li>
	<li><a href="/confluence/display/CAMEL/Asynchronous+Processing" title="Asynchronous Processing">Asynchronous Processing</a> in Camel Routes.</li>
	<li><a href="/confluence/display/CAMEL/Implementing+Virtual+Topics+on+other+JMS+providers" title="Implementing Virtual Topics on other JMS providers">Implementing Virtual Topics on other JMS providers</a> shows how to get the effect of Virtual Topics and avoid issues with JMS durable topics</li>
	<li><a href="/confluence/display/CAMEL/Camel+Transport+for+CXF" title="Camel Transport for CXF">Camel Transport for CXF</a> describes how to put the Camel context into the CXF transport layer.</li>
</ul>


<h2><a name="Bookcookbook-BeanIntegration"></a>Bean Integration</h2>

<p>Camel supports the integration of beans and POJOs in a number of ways</p>

<h3><a name="Bookcookbook-BeanBinding"></a><a href="/confluence/display/CAMEL/Bean+Binding" title="Bean Binding">Bean Binding</a></h3>
<p>Whenever Camel invokes a bean method, either via the <a href="/confluence/display/CAMEL/Bean" title="Bean">Bean</a> component, <a href="/confluence/display/CAMEL/Spring+Remoting" title="Spring Remoting">Spring Remoting</a> or <a href="/confluence/display/CAMEL/POJO+Consuming" title="POJO Consuming">POJO Consuming</a> then the <a href="/confluence/display/CAMEL/Bean+Binding" title="Bean Binding">Bean Binding</a> mechanism is used to figure out what method to use (if it is not explicit) and how to bind the <a href="/confluence/display/CAMEL/Message" title="Message">Message</a> to the parameters possibly using the <a href="/confluence/display/CAMEL/Parameter+Binding+Annotations" title="Parameter Binding Annotations">Parameter Binding Annotations</a></p>

<h3><a name="Bookcookbook-Annotations"></a>Annotations</h3>
<p>If a bean is defined in <a href="/confluence/display/CAMEL/Spring" title="Spring">Spring</a> XML or scanned using the Spring 2.5 component scanning mechanism and a <b>&lt;camelContext&gt;</b> is used or a CamelBeanPostProcessor then we process a number of Camel annotations to do various things such as injecting resources or producing, consuming or routing messages.</p>

<ul>
	<li><a href="/confluence/display/CAMEL/POJO+Consuming" title="POJO Consuming">POJO Consuming</a> to consume and possibly route messages from Camel</li>
	<li><a href="/confluence/display/CAMEL/POJO+Producing" title="POJO Producing">POJO Producing</a> to make it easy to produce camel messages from your POJOs</li>
	<li><a href="/confluence/display/CAMEL/RecipientList+Annotation" title="RecipientList Annotation">RecipientList Annotation</a> for creating a <a href="/confluence/display/CAMEL/Recipient+List" title="Recipient List">Recipient List</a> from a POJO method</li>
	<li><a href="/confluence/display/CAMEL/Bean+Injection" title="Bean Injection">Bean Injection</a> to inject Camel related resources into your POJOs</li>
	<li><a href="/confluence/display/CAMEL/Using+Exchange+Pattern+Annotations" title="Using Exchange Pattern Annotations">Using Exchange Pattern Annotations</a> describes how the pattern annotations can be used to change the behaviour of method invocations with <a href="/confluence/display/CAMEL/Spring+Remoting" title="Spring Remoting">Spring Remoting</a> or <a href="/confluence/display/CAMEL/POJO+Producing" title="POJO Producing">POJO Producing</a></li>
</ul>


<h3><a name="Bookcookbook-SpringRemoting"></a>Spring Remoting</h3>
<p>We support a <a href="/confluence/display/CAMEL/Spring+Remoting" title="Spring Remoting">Spring Remoting</a> provider which uses Camel as the underlying transport mechanism. The nice thing about this approach is we can use any of the Camel transport <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> to communicate between beans. It also means we can use <a href="/confluence/display/CAMEL/Content+Based+Router" title="Content Based Router">Content Based Router</a> and the other <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> in between the beans; in particular we can use <a href="/confluence/display/CAMEL/Message+Translator" title="Message Translator">Message Translator</a> to be able to convert what the on-the-wire messages look like in addition to adding various headers and so forth.</p>

<h3><a name="Bookcookbook-BeanComponent"></a>Bean Component</h3>
<p>The <a href="/confluence/display/CAMEL/Bean" title="Bean">Bean</a> component supports the creation of a proxy via <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/bean/ProxyHelper.html" title="Visit page outside Confluence" rel="nofollow">ProxyHelper<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to a Java interface; which the implementation just sends a message containing a <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/bean/BeanInvocation.html" title="Visit page outside Confluence" rel="nofollow">BeanInvocation<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to some Camel endpoint. </p>

<p>Then there is a server side implementation which consumes a message and uses the <a href="/confluence/display/CAMEL/Bean+Binding" title="Bean Binding">Bean Binding</a> to bind the message to invoke a method passing in its parameters.</p>
<p>When writing software these days, its important to try and decouple as much middleware code from your business logic as possible. </p>

<p>This provides a number of benefits...</p>
<ul>
	<li>you can choose the right middleware solution for your deployment and switch at any time</li>
	<li>you don't have to spend a large amount of time learning the specifics of any particular technology, whether its <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> or <a href="/confluence/display/CAMEL/JavaSpace" title="JavaSpace">JavaSpace</a> or <a href="/confluence/display/CAMEL/Hibernate" title="Hibernate">Hibernate</a> or <a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a> or <a href="/confluence/display/CAMEL/iBATIS" title="iBATIS">iBatis</a> whatever</li>
</ul>


<p>For example if you want to implement some kind of message passing, remoting, reliable load balancing or asynchronous processing in your application we recommend you use Camel annotations to bind your services and business logic to Camel <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> which means you can then easily switch between things like</p>
<ul>
	<li>in JVM messaging with <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a></li>
	<li>using JMS via <a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a> or other <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> providers for reliable load balancing, grid or publish and subscribe</li>
	<li>for low volume, but easier administration since you're probably already using a database you could use
	<ul>
		<li><a href="/confluence/display/CAMEL/Hibernate" title="Hibernate">Hibernate</a> or <a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a> to use an entity bean / table as a queue</li>
		<li><a href="/confluence/display/CAMEL/iBATIS" title="iBATIS">iBatis</a> to work with SQL</li>
		<li><a href="/confluence/display/CAMEL/JDBC" title="JDBC">JDBC</a> for raw SQL access</li>
	</ul>
	</li>
	<li>use <a href="/confluence/display/CAMEL/JavaSpace" title="JavaSpace">JavaSpace</a></li>
</ul>


<h3><a name="Bookcookbook-HowtodecouplefrommiddlewareAPIs"></a>How to decouple from middleware APIs</h3>

<p>The best approach when using remoting is to use <a href="/confluence/display/CAMEL/Spring+Remoting" title="Spring Remoting">Spring Remoting</a> which can then use any messaging or remoting technology under the covers. When using Camel's implementation you can then use any of the Camel <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> along with any of the <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a>.</p>

<p>Another approach is to bind Java beans to Camel endpoints via the <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a></p>
<h2><a name="Bookcookbook-Visualisation"></a>Visualisation</h2>

<p>Camel supports the visualisation of your <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> using the <span class="nobr"><a href="http://graphviz.org" title="Visit page outside Confluence" rel="nofollow">GraphViz<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> DOT files which can either be rendered directly via a suitable GraphViz tool or turned into HTML, PNG or SVG files via the <a href="/confluence/display/CAMEL/Camel+Maven+Plugin" title="Camel Maven Plugin">Camel Maven Plugin</a>.</p>

<p>Here is a <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-spring/cameldoc/index.html" title="Visit page outside Confluence" rel="nofollow">typical example<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> of the kind of thing we can generate</p>

<p><img src="/confluence/download/attachments/64021/ContentBasedRouter.png" align="absmiddle" border="0" /></p>

<p>If you click on <span class="nobr"><a href="http://activemq.apache.org/camel/maven/examples/camel-example-docs/cameldoc/main/routes.html" title="Visit page outside Confluence" rel="nofollow">the actual generated html<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>you will see that you can navigate from an EIP node to its pattern page, along with getting hover-over tool tips ec.</p>

<h3><a name="Bookcookbook-Howtogenerate"></a>How to generate</h3>
<p>See <a href="/confluence/display/CAMEL/Camel+Dot+Maven+Goal" title="Camel Dot Maven Goal">Camel Dot Maven Goal</a> or the other maven goals <a href="/confluence/display/CAMEL/Camel+Maven+Plugin" title="Camel Maven Plugin">Camel Maven Plugin</a></p>

<h3><a name="Bookcookbook-ForOSXusers"></a>For OS X users</h3>

<p>If you are using OS X then you can open the DOT file using <span class="nobr"><a href="http://www.pixelglow.com/graphviz/" title="Visit page outside Confluence" rel="nofollow">graphviz<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which will then automatically re-render if it changes, so you end up with a real time graphical representation of the topic and queue hierarchies!</p>

<p>Also if you want to edit the layout a little before adding it to a wiki to distribute to your team, open the DOT file with <span class="nobr"><a href="http://www.omnigroup.com/applications/omnigraffle/" title="Visit page outside Confluence" rel="nofollow">OmniGraffle<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> then just edit away <img class="emoticon" src="/confluence/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/></p>
<h2><a name="Bookcookbook-BusinessActivityMonitoring"></a>Business Activity Monitoring </h2>

<p>The <b>Camel BAM</b> module provides a Business Activity Monitoring (BAM) framework for testing business processes across multiple message exchanges on different <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> instances.</p>

<p>For example if you have a simple system which you submit Purchase Orders into system A and then receive Invoices from system B, you might want to test that for a specific Purchase Order you receive a matching Invoice from system B within a specific time period.</p>

<h3><a name="Bookcookbook-HowCamelBAMWorks"></a>How Camel BAM Works</h3>

<p>What Camel BAM does is use a <a href="/confluence/display/CAMEL/Correlation+Identifier" title="Correlation Identifier">Correlation Identifier</a> on an input message to determine which <em>Process Instance</em> a message belongs to. The process instance is an entity bean which can maintain state for each <em>Activity</em> (where an activity typically maps to a single endpoint, such as the receipt of Purchase orders, or the receipt of Invoices).</p>

<p>You can then add rules which are fired when a message is received on any activity such as to set time expectations, or to perform real time reconciliation of values across activities etc.</p>

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

<p>The following example shows how to perform some time based rules on a simple business process of 2 activities A and B (which maps to the Purchase Order and Invoice example above). If you want to experiment with this scenario you could edit the <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-bam/src/test/java/org/apache/camel/bam/BamRouteTest.java" title="Visit page outside Confluence" rel="nofollow">Test Case<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which defines the activities and rules, then tests that they work.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">return</span> <span class="code-keyword">new</span> ProcessBuilder(jpaTemplate, transactionTemplate) {
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span> Exception {

        <span class="code-comment">// lets define some activities, correlating on an XPath on the message bodies
</span>        ActivityBuilder a = activity(<span class="code-quote">"seda:a"</span>).name(<span class="code-quote">"a"</span>)
                .correlate(xpath(<span class="code-quote">"/hello/@id"</span>));

        ActivityBuilder b = activity(<span class="code-quote">"seda:b"</span>).name(<span class="code-quote">"b"</span>)
                .correlate(xpath(<span class="code-quote">"/hello/@id"</span>));

        <span class="code-comment">// now lets add some rules
</span>        b.starts().after(a.completes())
                .expectWithin(seconds(1))
                .errorIfOver(seconds(errorTimeout)).to(<span class="code-quote">"mock:overdue"</span>);
    }
};</pre>
</div></div>

<p>As you can see in the above example, we define two activities first, then we define rules on when we expect the activities on an individual process instance to complete by along with the time at which we should assume there is an error. The ProcessBuilder is-a <a href="/confluence/display/CAMEL/RouteBuilder" title="RouteBuilder">RouteBuilder</a> and can be added to any <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a></p>

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

<p>For a complete example please see the <a href="/confluence/display/CAMEL/BAM+Example" title="BAM Example">BAM Example</a> which is part of the standard Camel <a href="/confluence/display/CAMEL/Examples" title="Examples">Examples</a></p>

<h3><a name="Bookcookbook-UseCases"></a>Use Cases</h3>

<p>In the world of finance a common requirement is tracking financial trades. Often a trader will submit a Front Office Trade which then flows through the Middle Office and Back Office through various systems to settle the trade so that money is exchanged. You may wish to add tests that front and back office trades match up within a time period; if they don't match or a back office trade does not arrive within a required amount of time, you might want to fire off an alarm.</p>
<h2><a name="Bookcookbook-ExtractTransformLoad%28ETL%29"></a>Extract Transform Load (ETL)</h2>

<p>The <span class="nobr"><a href="http://en.wikipedia.org/wiki/Extract,_transform,_load" title="Visit page outside Confluence" rel="nofollow">ETL<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> (Extract, Transform, Load) is a mechanism for loading data into systems or databases using some kind of <a href="/confluence/display/CAMEL/Data+Format" title="Data Format">Data Format</a> from a variety of sources; often files then using <a href="/confluence/display/CAMEL/Pipes+and+Filters" title="Pipes and Filters">Pipes and Filters</a>, <a href="/confluence/display/CAMEL/Message+Translator" title="Message Translator">Message Translator</a> and possible other <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a>.</p>

<p>So you could query data from various Camel <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> such as <a href="/confluence/display/CAMEL/File" title="File">File</a>, <a href="/confluence/display/CAMEL/HTTP" title="HTTP">HTTP</a> or <a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a>, perform multiple patterns such as <a href="/confluence/display/CAMEL/Splitter" title="Splitter">Splitter</a> or <a href="/confluence/display/CAMEL/Message+Translator" title="Message Translator">Message Translator</a> then send the messages to some other <a href="/confluence/display/CAMEL/Component" title="Component">Component</a>.</p>

<p>To show how this all fits together, try the <a href="/confluence/display/CAMEL/ETL+Example" title="ETL Example">ETL Example</a> </p>
<h2><a name="Bookcookbook-MockComponent"></a>Mock Component</h2>

<p><a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a> of distributed and asynchronous processing is notoriously difficult. The <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a>, <a href="/confluence/display/CAMEL/Test" title="Test">Test</a> and <a href="/confluence/display/CAMEL/DataSet" title="DataSet">DataSet</a> endpoints work great with the <a href="/confluence/display/CAMEL/Testing" title="Testing">Camel Testing Framework</a> to simplify your unit and integration testing using <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> and Camel's large range of <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> together with the powerful <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a>.</p>

<p>The Mock component provides a powerful declarative testing mechanism which is similar to <span class="nobr"><a href="http://jmock.org" title="Visit page outside Confluence" rel="nofollow">jMock<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> in that it allows declarative expectations to be created on any Mock endpoint before a test begins. Then the test is ran which typically fires messages to one or more endpoints and finally the expectations can be asserted in a test case to ensure the system  worked as expected. </p>

<p>This allows you to test various things like:</p>
<ul>
	<li>the correct number of messages are received on each endpoint</li>
	<li>that the correct payloads are received, in the right order</li>
	<li>that messages arrive on an endpoint in order, using some <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> to create an order testing function</li>
	<li>that messages arrive match some kind of <a href="/confluence/display/CAMEL/Predicate" title="Predicate">Predicate</a> such as that specific headers have certain values, or that parts of the messages match some predicate such as by evaluating an <a href="/confluence/display/CAMEL/XPath" title="XPath">XPath</a> or <a href="/confluence/display/CAMEL/XQuery" title="XQuery">XQuery</a> <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a></li>
</ul>


<p><b>Note</b> that there is also the <a href="/confluence/display/CAMEL/Test" title="Test">Test endpoint</a> which is-a Mock endpoint but which also uses a second endpoint to provide the list of expected message bodies and automatically sets up the Mock endpoint assertions. i.e. its a Mock endpoint which automatically sets up its assertions from some sample messages in a <a href="/confluence/display/CAMEL/File" title="File">File</a> or <a href="/confluence/display/CAMEL/JPA" title="JPA">database</a> for example.</p>

<h3><a name="Bookcookbook-URIformat"></a>URI format</h3>

<div class="code"><div class="codeContent">
<pre class="code-java">mock:someName?options</pre>
</div></div>

<p>Where <b>someName</b> can be any string to uniquely identify the endpoint</p>

<h3><a name="Bookcookbook-Options"></a>Options</h3>

<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'> reportGroup </td>
<td class='confluenceTd'> null </td>
<td class='confluenceTd'> A size to use a <a href="/confluence/display/CAMEL/Log" title="Log">throughput logger</a> for reporting </td>
</tr>
</tbody></table>

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

<p>Here's a simple example of MockEndpoint in use. First the endpoint is resolved on the context. Then we set an expectation, then after the test has run we assert our expectations are met.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">MockEndpoint resultEndpoint = context.resolveEndpoint(<span class="code-quote">"mock:foo"</span>, MockEndpoint.class);

resultEndpoint.expectedMessageCount(2);

<span class="code-comment">// send some messages
</span>...

<span class="code-comment">// now lets <span class="code-keyword">assert</span> that the mock:foo endpoint received 2 messages
</span>resultEndpoint.assertIsSatisfied();</pre>
</div></div>

<p>You typically always call the <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#assertIsSatisfied()" title="Visit page outside Confluence" rel="nofollow">assertIsSatisfied() method<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to test that the expectations were met after running a test.</p>

<p>Camel will by default wait 20 seconds when the <tt>assertIsSatisfied()</tt> is invoked. This can be configured by setting the <tt>setResultWaitTime(millis)</tt> method.</p>

<h3><a name="Bookcookbook-Settingexpectations"></a>Setting expectations</h3>

<p>You can see from the javadoc of <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html" title="Visit page outside Confluence" rel="nofollow">MockEndpoint<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> the various helper methods you can use to set expectations. The main methods available are as follows: </p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Method </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectedMessageCount(int)" title="Visit page outside Confluence" rel="nofollow">expectedMessageCount(int)<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'> to define the expected message count on the endpoint </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectedMinimumMessageCount(int)" title="Visit page outside Confluence" rel="nofollow">expectedMinimumMessageCount(int)<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'> to define the minimum number of expected messages on the endpoint </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectedBodiesReceived(java.lang.Object...)" title="Visit page outside Confluence" rel="nofollow">expectedBodiesReceived(...)<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'> to define the expected bodies that should be received (in order) </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectedHeaderReceived(java.lang.String,%20java.lang.String)" title="Visit page outside Confluence" rel="nofollow">expectedHeaderReceived(...)<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'> to define the expected header that should be received </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectsAscending(org.apache.camel.Expression)" title="Visit page outside Confluence" rel="nofollow">expectsAscending(Expression)<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'> to add an expectation that messages are received in order using the given <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> to compare messages </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectsDescending(org.apache.camel.Expression)" title="Visit page outside Confluence" rel="nofollow">expectsDescending(Expression)<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'> to add an expectation that messages are received in order using the given <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> to compare messages </td>
</tr>
<tr>
<td class='confluenceTd'> <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#expectsNoDuplicates(org.apache.camel.Expression)" title="Visit page outside Confluence" rel="nofollow">expectsNoDuplicates(Expression)<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'> to add an expectation that no duplicate messages are received; using an <a href="/confluence/display/CAMEL/Expression" title="Expression">Expression</a> to calculate a unique identifier for each message. This could be something like the JMSMessageID if using JMS, or some unique reference number within the message. </td>
</tr>
</tbody></table>

<p>Here's another example:</p>

<div class="code"><div class="codeContent">
<pre class="code-java">resultEndpoint.expectedBodiesReceived(<span class="code-quote">"firstMessageBody"</span>, <span class="code-quote">"secondMessageBody"</span>, <span class="code-quote">"thirdMessageBody"</span>);</pre>
</div></div>

<h4><a name="Bookcookbook-Addingexpectationstospecificmessages"></a>Adding expectations to specific messages</h4>

<p>In addition you can use the <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#message(int)" title="Visit page outside Confluence" rel="nofollow">message(int messageIndex)<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> method to add assertions about a specific message that is received.</p>

<p>For example to add expectations of the headers or body of the first message (using zero based indexing like java.util.List), you can use this code</p>

<div class="code"><div class="codeContent">
<pre class="code-java">resultEndpoint.message(0).header(<span class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>);</pre>
</div></div>


<p>There are some examples of the Mock endpoint in use in the <span class="nobr"><a href="http://svn.apache.org/viewvc/activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/" title="Visit page outside Confluence" rel="nofollow">camel-core processor tests<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<h3><a name="Bookcookbook-ASpringExample"></a>A Spring Example</h3>

<p>First here's the <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/mock/spring.xml" title="Visit page outside Confluence" rel="nofollow">spring.xml file<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext xmlns=<span class="code-quote">"http://activemq.apache.org/camel/schema/spring"</span>&gt;</span>
  <span class="code-tag">&lt;route&gt;</span>
    <span class="code-tag">&lt;from uri=<span class="code-quote">"file:src/test/data?noop=true"</span>/&gt;</span>
    <span class="code-tag">&lt;filter&gt;</span>
      <span class="code-tag">&lt;xpath&gt;</span>/person/city = 'London'<span class="code-tag">&lt;/xpath&gt;</span>
      <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:matched"</span>/&gt;</span>
    <span class="code-tag">&lt;/filter&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">"myBean"</span> class=<span class="code-quote">"org.apache.camel.spring.mock.MyAssertions"</span> scope=<span class="code-quote">"singleton"</span>/&gt;</span></pre>
</div></div>

<p>As you can see it defines a simple routing rule which consumes messages from the local <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/data/" title="Visit page outside Confluence" rel="nofollow">src/test/data directory<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. The <b>noop</b> flag just means not to delete or move the file after its been processed.</p>

<p>Also note we instantiate a bean called <b>myBean</b>, here is the <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/mock/MyAssertions.java" title="Visit page outside Confluence" rel="nofollow">source of the MyAssertions bean<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. </p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyAssertions <span class="code-keyword">implements</span> InitializingBean {
    @EndpointInject(uri = <span class="code-quote">"mock:matched"</span>)
    <span class="code-keyword">private</span> MockEndpoint matched;

    @EndpointInject(uri = <span class="code-quote">"mock:notMatched"</span>)
    <span class="code-keyword">private</span> MockEndpoint notMatched;

    <span class="code-keyword">public</span> void afterPropertiesSet() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// lets add some expectations
</span>        matched.expectedMessageCount(1);
        notMatched.expectedMessageCount(0);
    }

    <span class="code-keyword">public</span> void assertEndpointsValid() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// now lets perform some assertions that the test worked as we expect
</span>        Assert.assertNotNull(<span class="code-quote">"Should have a matched endpoint"</span>, matched);
        Assert.assertNotNull(<span class="code-quote">"Should have a notMatched endpoint"</span>, notMatched);
        MockEndpoint.assertIsSatisfied(matched, notMatched);
    }
}</pre>
</div></div>

<p>The bean is injected with a bunch of Mock endpoints using the <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">@EndpointInject annotation</a>, it then sets a bunch of expectations on startup (using Spring's InitializingBean interface and afterPropertiesSet() method) before the CamelContext starts up. </p>

<p>Then in our test case (which could be JUnit or TesNG) we lookup <b>myBean</b> in Spring (or have it injected into our test) and then invoke the <b>assertEndpointsValid()</b> method on it to verify that the mock endpoints have their assertions met. You could then inspect the message exchanges that were delivered to any of the endpoints using the <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#getReceivedExchanges()" title="Visit page outside Confluence" rel="nofollow">getReceivedExchanges()<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> method on the Mock endpoint and perform further assertions or debug logging.</p>

<p>Here is the <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/mock/BeanMockTest.java" title="Visit page outside Confluence" rel="nofollow">actual JUnit test case we use<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<h3><a name="Bookcookbook-SeeAlso"></a>See Also</h3>
<ul>
	<li><a href="/confluence/display/CAMEL/Configuring+Camel" title="Configuring Camel">Configuring Camel</a></li>
	<li><a href="/confluence/display/CAMEL/Component" title="Component">Component</a></li>
	<li><a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a></li>
	<li><a href="/confluence/display/CAMEL/Getting+Started" title="Getting Started">Getting Started</a></li>
</ul>

<ul>
	<li><a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a></li>
</ul>

<h2><a name="Bookcookbook-Testing"></a>Testing</h2>

<p>Testing is a crucial activity in any piece of software development or integration. Typically Camel Riders use various different <a href="/confluence/display/CAMEL/Components" title="Components">technologies</a> wired together in a variety of <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">patterns</a> with different <a href="/confluence/display/CAMEL/Languages" title="Languages">expression languages</a> together with different forms of <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a> and <a href="/confluence/display/CAMEL/Dependency+Injection" title="Dependency Injection">Dependency Injection</a> so its very easy for things to go wrong! <img class="emoticon" src="/confluence/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/>. Testing is the crucial weapon to ensure that things work as you would expect.</p>

<p>Camel is a Java library so you can easily wire up tests in whatever unit testing framework you use (JUnit 3.x, 4.x or TestNG). However the Camel project has tried to make the testing of Camel as easy and powerful as possible so we have introduced the following features.</p>

<h3><a name="Bookcookbook-Testingmechanisms"></a>Testing mechanisms</h3>

<p>The following mechanisms are supported</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Camel+Test" title="Camel Test">Camel Test</a> </td>
<td class='confluenceTd'> is a library letting you easily create Camel test cases using a single Java class for all your configuration and routing without using <a href="/confluence/display/CAMEL/Spring" title="Spring">Spring</a> or <a href="/confluence/display/CAMEL/Guice" title="Guice">Guice</a> for <a href="/confluence/display/CAMEL/Dependency+Injection" title="Dependency Injection">Dependency Injection</a> which does not require an in depth knowledge of Spring+SpringTest or Guice </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a> </td>
<td class='confluenceTd'> uses Spring Test together with either XML or Java Config to dependency inject your test classes </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Guice" title="Guice">Guice</a> </td>
<td class='confluenceTd'> uses <a href="/confluence/display/CAMEL/Guice" title="Guice">Guice</a> to dependency inject your test classes </td>
</tr>
</tbody></table>

<p>In all approaches the test classes look pretty much the same in that they all reuse the <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Camel binding and injection annotations</a>.</p>

<h4><a name="Bookcookbook-CamelTestExample"></a>Camel Test Example</h4>

<p>Here is the <a href="/confluence/display/CAMEL/Camel+Test" title="Camel Test">Camel Test</a> <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-test/src/test/java/org/apache/camel/test/patterns/FilterTest.java" title="Visit page outside Confluence" rel="nofollow">example<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. </p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class FilterTest <span class="code-keyword">extends</span> CamelTestSupport {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    <span class="code-keyword">public</span> void testSendMatchingMessage() <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    <span class="code-keyword">public</span> void testSendNotMatchingMessage() <span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Override
    <span class="code-keyword">protected</span> RouteBuilder createRouteBuilder() {
        <span class="code-keyword">return</span> <span class="code-keyword">new</span> RouteBuilder() {
            <span class="code-keyword">public</span> void configure() {
                from(<span class="code-quote">"direct:start"</span>).filter(header(<span class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span class="code-quote">"mock:result"</span>);
            }
        };
    }
}</pre>
</div></div>

<p>Notice how it derives from the Camel helper class <b>CamelTestSupport</b> but has no Spring or Guice dependency injection configuration but instead overrides the <b>createRouteBuilder()</b> method.</p>

<h4><a name="Bookcookbook-SpringTestwithXMLConfigExample"></a>Spring Test with XML Config Example</h4>

<p>Here is the <a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a> <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/patterns/FilterTest.java" title="Visit page outside Confluence" rel="nofollow">example using XML Config<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">@ContextConfiguration
<span class="code-keyword">public</span> class FilterTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendMatchingMessage() <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendNotMatchingMessage() <span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }
}</pre>
</div></div>

<p>Notice that we use <b>@DirtiesContext</b> on the test methods to force <a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a> to automatically reload the <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a> after each test method - this ensures that the tests don't clash with each other (e.g. one test method sending to an endpoint that is then reused in another test method).</p>

<p>Also notice the use of <b>@ContextConfiguration</b> to indicate that by default we should look for the <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/patterns/FilterTest-context.xml" title="Visit page outside Confluence" rel="nofollow">FilterTest-context.xml on the classpath<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to configure the test case which looks like this</p>

<div class="code"><div class="codeContent">
<pre class="code-xml">&lt;beans xmlns=<span class="code-quote">"http://www.springframework.org/schema/beans"</span>
       <span class="code-keyword">xmlns:xsi</span>=<span class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span>
       <span class="code-keyword">xmlns:context</span>=<span class="code-quote">"http://www.springframework.org/schema/context"</span>
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
    "&gt;

  <span class="code-tag">&lt;camelContext xmlns=<span class="code-quote">"http://activemq.apache.org/camel/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;filter&gt;</span>
        <span class="code-tag">&lt;xpath&gt;</span>$foo = 'bar'<span class="code-tag">&lt;/xpath&gt;</span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
      <span class="code-tag">&lt;/filter&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>
  <span class="code-tag">&lt;/camelContext&gt;</span>

<span class="code-tag">&lt;/beans&gt;</span></pre>
</div></div>

<h4><a name="Bookcookbook-SpringTestwithJavaConfigExample"></a>Spring Test with Java Config Example</h4>

<p>Here is the <a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a> <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring-javaconfig/src/test/java/org/apache/camel/spring/javaconfig/patterns/FilterTest.java" title="Visit page outside Confluence" rel="nofollow">example using Java Config<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. For more information see <a href="/confluence/display/CAMEL/Spring+Java+Config" title="Spring Java Config">Spring Java Config</a>.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">@ContextConfiguration(
        locations = <span class="code-quote">"org.apache.camel.spring.javaconfig.patterns.FilterTest$ContextConfig"</span>,
        loader = JavaConfigContextLoader.class)
<span class="code-keyword">public</span> class FilterTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendMatchingMessage() <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendNotMatchingMessage() <span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Configuration
    <span class="code-keyword">public</span> <span class="code-keyword">static</span> class ContextConfig <span class="code-keyword">extends</span> SingleRouteCamelConfiguration {
        @Bean
        <span class="code-keyword">public</span> RouteBuilder route() {
            <span class="code-keyword">return</span> <span class="code-keyword">new</span> RouteBuilder() {
                <span class="code-keyword">public</span> void configure() {
                    from(<span class="code-quote">"direct:start"</span>).filter(header(<span class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span class="code-quote">"mock:result"</span>);
                }
            };
        }
    }
}</pre>
</div></div>

<p>This is similar to the XML Config example above except that there is no XML file and instead the nested <b>ContextConfig</b> class does all of the configuration; so your entire test case is contained in a single Java class. We currently have to reference by class name this class in the <b>@ContextConfiguration</b> which is a bit ugly. Please vote for <span class="nobr"><a href="http://jira.springframework.org/browse/SJC-238" title="Visit page outside Confluence" rel="nofollow">SJC-238<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to address this and make Spring Test work more cleanly with Spring JavaConfig.</p>

<p>Its totally optional but for the ContextConfig implementation we derive from <b>SingleRouteCamelConfiguration</b> which is a helper Spring Java Config class which will configure the CamelContext for us and then register the RouteBuilder we create.</p>

<h3><a name="Bookcookbook-Testingendpoints"></a>Testing endpoints</h3>

<p>Camel provides a number of endpoints which can make testing easier.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/DataSet" title="DataSet">DataSet</a> </td>
<td class='confluenceTd'> For load &amp; soak testing this endpoint provides a way to create huge numbers of messages for sending to <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> and asserting that they are consumed correctly </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> </td>
<td class='confluenceTd'> For testing routes and mediation rules using mocks and allowing assertions to be added to an endpoint  </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Test" title="Test">Test</a> </td>
<td class='confluenceTd'> Creates a <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> endpoint which expects to receive all the message bodies that could be polled from the given underlying endpoint </td>
</tr>
</tbody></table>

<p>The main endpoint is the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> endpoint which allows expectations to be added to different endpoints; you can then run your tests and assert that your expectations are met at the end.</p>

<h3><a name="Bookcookbook-Stubbingoutphysicaltransporttechnologies"></a>Stubbing out physical transport technologies</h3>

<p>If you wish to test out a route but want to avoid actually using a real physical transport (for example to unit test a transformation route rather than performing a full integration test) then the following endpoints can be useful.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'> Name </th>
<th class='confluenceTh'> Description </th>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/Direct" title="Direct">Direct</a> </td>
<td class='confluenceTd'>  Direct invocation of the consumer from the producer so that single threaded (non-SEDA) in VM invocation is performed which can be useful to mock out physical transports </td>
</tr>
<tr>
<td class='confluenceTd'> <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> </td>
<td class='confluenceTd'> Delivers messages asynchonously to consumers via a <span class="nobr"><a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html" title="Visit page outside Confluence" rel="nofollow">java.util.concurrent.BlockingQueue<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which is good for testing asynchronous transports </td>
</tr>
</tbody></table>

<h2><a name="Bookcookbook-CamelTest"></a>Camel Test</h2>

<p>As a simple alternative to using <a href="/confluence/display/CAMEL/Spring+Testing" title="Spring Testing">Spring Testing</a> or <a href="/confluence/display/CAMEL/Guice" title="Guice">Guice</a> the <b>camel-test</b> module was introduced into the Camel 2.0 trunk so you can perform powerful <a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a> of your <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> easily.</p>

<h3><a name="Bookcookbook-Addingtoyourpom.xml"></a>Adding to your pom.xml</h3>

<p>To get started using Camel Test you will need to add an entry to your pom.xml</p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>org.apache.camel<span class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>camel-test<span class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;version&gt;</span>${camel-version}<span class="code-tag">&lt;/version&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span></pre>
</div></div>

<p>You might also want to add commons-logging and log4j to ensure nice logging messages (and maybe adding a <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-test/src/test/resources/log4j.properties" title="Visit page outside Confluence" rel="nofollow">log4j.properties<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> file into your src/test/resources directory).</p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>commons-logging<span class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>commons-logging<span class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span>
<span class="code-tag">&lt;dependency&gt;</span>
  <span class="code-tag">&lt;groupId&gt;</span>log4j<span class="code-tag">&lt;/groupId&gt;</span>
  <span class="code-tag">&lt;artifactId&gt;</span>log4j<span class="code-tag">&lt;/artifactId&gt;</span>
  <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
<span class="code-tag">&lt;/dependency&gt;</span></pre>
</div></div>

<h3><a name="Bookcookbook-Writingyourtest"></a>Writing your test</h3>

<p>You firstly need to derive from the class <b>CamelTestSupport</b> and typically you will need to override the <b>createRouteBuilder()</b> method to create routes to be tested.</p>

<p>Here is an <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-test/src/test/java/org/apache/camel/test/patterns/FilterTest.java" title="Visit page outside Confluence" rel="nofollow">example<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. </p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class FilterTest <span class="code-keyword">extends</span> CamelTestSupport {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    <span class="code-keyword">public</span> void testSendMatchingMessage() <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    <span class="code-keyword">public</span> void testSendNotMatchingMessage() <span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Override
    <span class="code-keyword">protected</span> RouteBuilder createRouteBuilder() {
        <span class="code-keyword">return</span> <span class="code-keyword">new</span> RouteBuilder() {
            <span class="code-keyword">public</span> void configure() {
                from(<span class="code-quote">"direct:start"</span>).filter(header(<span class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span class="code-quote">"mock:result"</span>);
            }
        };
    }
}</pre>
</div></div>

<p>Notice how you can use the various <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Camel binding and injection annotations</a> to inject individual <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> objects - particularly the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock endpoints</a> which are very useful for <a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a>. Also you can inject <a href="/confluence/display/CAMEL/POJO+Producing" title="POJO Producing">producer objects such as ProducerTemplate or some application code interface</a> for sending messages or invoking services.</p>


<h3><a name="Bookcookbook-JNDI"></a>JNDI</h3>

<p>Camel uses a <a href="/confluence/display/CAMEL/Registry" title="Registry">Registry</a> to allow you to configure <a href="/confluence/display/CAMEL/Component" title="Component">Component</a> or <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> instances or <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Beans used in your routes</a>. If you are not using <a href="/confluence/display/CAMEL/Spring" title="Spring">Spring</a> or <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=CAMEL&amp;title=OSGi&amp;linkCreation=true&amp;fromPageId=104074" title="Create Page: OSGi" class="createlink">OSGi<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> then <a href="/confluence/display/CAMEL/JNDI" title="JNDI">JNDI</a> is used as the default registry implementation.</p>

<p>So you will also need to create a <b>jndi.properties</b> file in your <b>src/test/resources</b> directory so that there is a default registry available to initialise the <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a>.</p>

<p>Here is <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-test/src/test/resources/jndi.properties" title="Visit page outside Confluence" rel="nofollow">an example jndi.properties file<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<div class="code"><div class="codeContent">
<pre class="code-java">java.naming.factory.initial = org.apache.camel.util.jndi.CamelInitialContextFactory</pre>
</div></div>


<h3><a name="Bookcookbook-SeeAlso"></a>See Also</h3>

<ul>
	<li><a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a></li>
	<li><a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a></li>
</ul>



<h2><a name="Bookcookbook-SpringTesting"></a>Spring Testing</h2>

<p><a href="/confluence/display/CAMEL/Testing" title="Testing">Testing</a> is a crucial part of any development or integration work. The Spring Framework offers a number of features that makes it easy to test while using Spring for Inversion of Control which works with JUnit 3.x, JUnit 4.x or <span class="nobr"><a href="http://testng.org" title="Visit page outside Confluence" rel="nofollow">TestNG<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<p>We can reuse Spring for IoC and the Camel <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> and <a href="/confluence/display/CAMEL/Test" title="Test">Test</a> endpoints to create sophisticated integration tests that are easy to run and debug inside your IDE.</p>

<p>For example here is a simple unit test</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">import</span> org.apache.camel.CamelContext;
<span class="code-keyword">import</span> org.apache.camel.component.mock.MockEndpoint;
<span class="code-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="code-keyword">import</span> org.springframework.test.context.ContextConfiguration;
<span class="code-keyword">import</span> org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;

@ContextConfiguration
<span class="code-keyword">public</span> class MyCamelTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @Autowired
    <span class="code-keyword">protected</span> CamelContext camelContext;

    <span class="code-keyword">public</span> void testMocksAreValid() <span class="code-keyword">throws</span> Exception {
        MockEndpoint.assertIsSatisfied(camelContext);
    }
}</pre>
</div></div>

<p>This test will load a Spring XML configuration file called <b>MyCamelTest-context.xml</b> from the classpath in the same package structure as the MyCamelTest class and initialize it along with any Camel routes we define inside it, then inject the <a href="/confluence/display/CAMEL/CamelContext" title="CamelContext">CamelContext</a> instance into our test case.</p>

<p>For instance, like this maven folder layout:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">src/main/java/com/mycompany/MyCamelTest.class
src/main/resources/com/mycompany/MyCamelTest-context.xml</pre>
</div></div>

<p>You can overload the method <tt>createApplicationContext</tt> to provide the Spring ApplicationContext that isn't following the above default. For instance:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">protected</span> AbstractXmlApplicationContext createApplicationContext() {
    <span class="code-keyword">return</span> <span class="code-keyword">new</span> ClassPathXmlApplicationContext(<span class="code-quote">"/config/MySpringConfig.xml"</span>);
  }</pre>
</div></div>

<p>Then the test method will then run which invokes the <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-core/apidocs/org/apache/camel/component/mock/MockEndpoint.html#assertIsSatisfied(org.apache.camel.CamelContext)" title="Visit page outside Confluence" rel="nofollow">MockEndpoint.assertIsSatisfied(camelContext) method<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which asserts that all of the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> and <a href="/confluence/display/CAMEL/Test" title="Test">Test</a> endpoints have their expectations met.</p>

<p>xml}</p>

<h3><a name="Bookcookbook-SpringTestwithJavaConfigExample"></a>Spring Test with Java Config Example</h3>

<p>You can completely avoid using an XML configuration file by using <a href="/confluence/display/CAMEL/Spring+Java+Config" title="Spring Java Config">Spring Java Config</a>.</p>

<p>Here is an <span class="nobr"><a href="http://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring-javaconfig/src/test/java/org/apache/camel/spring/javaconfig/patterns/FilterTest.java" title="Visit page outside Confluence" rel="nofollow">example using Java Config<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">@ContextConfiguration(
        locations = <span class="code-quote">"org.apache.camel.spring.javaconfig.patterns.FilterTest$ContextConfig"</span>,
        loader = JavaConfigContextLoader.class)
<span class="code-keyword">public</span> class FilterTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @EndpointInject(uri = <span class="code-quote">"mock:result"</span>)
    <span class="code-keyword">protected</span> MockEndpoint resultEndpoint;

    @Produce(uri = <span class="code-quote">"direct:start"</span>)
    <span class="code-keyword">protected</span> ProducerTemplate template;

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendMatchingMessage() <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> expectedBody = <span class="code-quote">"&lt;matched/&gt;"</span>;

        resultEndpoint.expectedBodiesReceived(expectedBody);

        template.sendBodyAndHeader(expectedBody, <span class="code-quote">"foo"</span>, <span class="code-quote">"bar"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @DirtiesContext
    <span class="code-keyword">public</span> void testSendNotMatchingMessage() <span class="code-keyword">throws</span> Exception {
        resultEndpoint.expectedMessageCount(0);

        template.sendBodyAndHeader(<span class="code-quote">"&lt;notMatched/&gt;"</span>, <span class="code-quote">"foo"</span>, <span class="code-quote">"notMatchedHeaderValue"</span>);

        resultEndpoint.assertIsSatisfied();
    }

    @Configuration
    <span class="code-keyword">public</span> <span class="code-keyword">static</span> class ContextConfig <span class="code-keyword">extends</span> SingleRouteCamelConfiguration {
        @Bean
        <span class="code-keyword">public</span> RouteBuilder route() {
            <span class="code-keyword">return</span> <span class="code-keyword">new</span> RouteBuilder() {
                <span class="code-keyword">public</span> void configure() {
                    from(<span class="code-quote">"direct:start"</span>).filter(header(<span class="code-quote">"foo"</span>).isEqualTo(<span class="code-quote">"bar"</span>)).to(<span class="code-quote">"mock:result"</span>);
                }
            };
        }
    }
}</pre>
</div></div>

<p>This is similar to the XML Config example above except that there is no XML file and instead the nested <b>ContextConfig</b> class does all of the configuration; so your entire test case is contained in a single Java class. We currently have to reference by class name this class in the <b>@ContextConfiguration</b> which is a bit ugly. Please vote for <span class="nobr"><a href="http://jira.springframework.org/browse/SJC-238" title="Visit page outside Confluence" rel="nofollow">SJC-238<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to address this and make Spring Test work more cleanly with Spring JavaConfig.</p>

<h3><a name="Bookcookbook-AddingmoreMockexpectations"></a>Adding more Mock expectations</h3>

<p>If you wish to programmatically add any new assertions to your test you can easily do so with the following. Notice how we use @EndpointInject to inject a Camel endpoint into our code then the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> API to add an expectation on a specific message.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">@ContextConfiguration
<span class="code-keyword">public</span> class MyCamelTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @Autowired
    <span class="code-keyword">protected</span> CamelContext camelContext;

    @EndpointInject(uri = <span class="code-quote">"mock:foo"</span>)
    <span class="code-keyword">protected</span> MockEndpoint foo;
    
    <span class="code-keyword">public</span> void testMocksAreValid() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// lets add more expectations
</span>        foo.message(0).header(<span class="code-quote">"bar"</span>).isEqualTo(<span class="code-quote">"ABC"</span>);
    
        MockEndpoint.assertIsSatisfied(camelContext);
    }
}</pre>
</div></div>

<h3><a name="Bookcookbook-Furtherprocessingthereceivedmessages"></a>Further processing the received messages</h3>

<p>Sometimes once a <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> endpoint has received some messages you want to then process them further to add further assertions that your test case worked as you expect.</p>

<p>So you can then process the received message exchanges if you like...</p>

<div class="code"><div class="codeContent">
<pre class="code-java">@ContextConfiguration
<span class="code-keyword">public</span> class MyCamelTest <span class="code-keyword">extends</span> AbstractJUnit38SpringContextTests {

    @Autowired
    <span class="code-keyword">protected</span> CamelContext camelContext;

    @EndpointInject(uri = <span class="code-quote">"mock:foo"</span>)
    <span class="code-keyword">protected</span> MockEndpoint foo;
    
    <span class="code-keyword">public</span> void testMocksAreValid() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// lets add more expectations...
</span>    
        MockEndpoint.assertIsSatisfied(camelContext);

		<span class="code-comment">// now lets <span class="code-keyword">do</span> some further assertions
</span>        List&lt;Exchange&gt; list = foo.getReceivedExchanges();
        <span class="code-keyword">for</span> (Exchange exchange : list) {
            Message in = exchange.getIn();
            ...
        }		
    }
}</pre>
</div></div>

<h3><a name="Bookcookbook-Sendingandreceivingmessages"></a>Sending and receiving messages</h3>

<p>It might be that the <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">Enterprise Integration Patterns</a> you have defined in either <a href="/confluence/display/CAMEL/Spring" title="Spring">Spring</a> XML or using the Java <a href="/confluence/display/CAMEL/DSL" title="DSL">DSL</a> do all of the sending and receiving and you might just  work with the <a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> endpoints as described above. However sometimes in a test case its useful to explicitly send or receive messages directly.</p>

<p>To send or receive messages you should use the <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a> mechanism. For example to send messages inject a ProducerTemplate using the @EndpointInject annotation then call the various send methods on this object to send a message to an endpoint. To consume messages use the @MessageDriven annotation on a method to have the method invoked when a message is received.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class Foo {
  @EndpointInject(uri=<span class="code-quote">"activemq:foo.bar"</span>)
  ProducerTemplate producer;

  <span class="code-keyword">public</span> void doSomething() {
    <span class="code-comment">// lets send a message!
</span>    producer.sendBody(<span class="code-quote">"&lt;hello&gt;world!&lt;/hello&gt;"</span>);
  }

  <span class="code-comment">// lets consume messages from the 'cheese' queue
</span>  @MessageDriven(uri=<span class="code-quote">"activemq:cheese"</span>)
  <span class="code-keyword">public</span> void onCheese(<span class="code-object">String</span> name) {
    ...
  }
}</pre>
</div></div>

<h3><a name="Bookcookbook-SeeAlso"></a>See Also</h3>

<ul>
	<li>a <span class="nobr"><a href="http://svn.apache.org/viewvc/activemq/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/component/test/TestEndpointTest.java?view=markup" title="Visit page outside Confluence" rel="nofollow">real example test case using Mock and Spring<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> along with its <span class="nobr"><a href="https://svn.apache.org/repos/asf/activemq/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/component/test/TestEndpointTest-context.xml" title="Visit page outside Confluence" rel="nofollow">Spring XML<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/CAMEL/Bean+Integration" title="Bean Integration">Bean Integration</a></li>
	<li><a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> endpoint</li>
	<li><a href="/confluence/display/CAMEL/Test" title="Test">Test</a> endpoint</li>
</ul>

<h2><a name="Bookcookbook-CamelGuice"></a>Camel Guice</h2>

<p>As of 1.5 we now have support for <span class="nobr"><a href="http://code.google.com/p/google-guice/" title="Visit page outside Confluence" rel="nofollow">Google Guice<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> as a dependency injection framework. To use it just be dependent on <b>camel-guice.jar</b> which also depends on <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-guice/dependencies.html" title="Visit page outside Confluence" rel="nofollow">the following jars<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<h3><a name="Bookcookbook-DependencyInjectingCamelwithGuice"></a>Dependency Injecting Camel with Guice</h3>

<p>The <span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-guice/apidocs/org/apache/camel/guice/GuiceCamelContext.html" title="Visit page outside Confluence" rel="nofollow">GuiceCamelContext<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> is designed to work nicely inside Guice. You then need to bind it using some Guice Module.</p>

<p>The camel-guice library comes with a number of reusable Guice Modules you can use if you wish - or you can bind the GuiceCamelContext yourself in your own module.</p>

<ul>
	<li><span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-guice/apidocs/org/apache/camel/guice/CamelModule.html" title="Visit page outside Confluence" rel="nofollow">CamelModule<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> is the base module which binds the GuiceCamelContext but leaves it up you to bind the RouteBuilder instances</li>
	<li><span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-guice/apidocs/org/apache/camel/guice/CamelModuleWithRouteTypes.html" title="Visit page outside Confluence" rel="nofollow">CamelModuleWithRouteTypes<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> extends CamelModule so that in the constructor of the module you specify the RouteBuilder classes or instances to use</li>
	<li><span class="nobr"><a href="http://activemq.apache.org/camel/maven/camel-guice/apidocs/org/apache/camel/guice/CamelModuleWithMatchingRoutes.html" title="Visit page outside Confluence" rel="nofollow">CamelModuleWithMatchingRoutes<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> extends CamelModule so that all bound RouteBuilder instances will be injected into the CamelContext or you can supply an optional Matcher to find RouteBuilder instances matching some kind of predicate.</li>
</ul>


<p>So you can specify the exact <a href="/confluence/display/CAMEL/RouteBuilder" title="RouteBuilder">RouteBuilder</a> instances you want</p>

<div class="code"><div class="codeContent">
<pre class="code-java">Injector injector = Guice.createInjector(<span class="code-keyword">new</span> CamelModuleWithRouteTypes(MyRouteBuilder.class, AnotherRouteBuilder.class));
<span class="code-comment">// <span class="code-keyword">if</span> required you can lookup the CamelContext
</span>CamelContext camelContext = injector.getInstance(CamelContext.class);</pre>
</div></div>

<p>Or inject them all</p>

<div class="code"><div class="codeContent">
<pre class="code-java">Injector injector = Guice.createInjector(<span class="code-keyword">new</span> CamelModuleWithRouteTypes());
<span class="code-comment">// <span class="code-keyword">if</span> required you can lookup the CamelContext
</span>CamelContext camelContext = injector.getInstance(CamelContext.class);</pre>
</div></div>

<p>You can then use Guice in the usual way to inject the route instances or any other dependent objects.</p>

<h3><a name="Bookcookbook-BootstrappingwithJNDI"></a>Bootstrapping with JNDI</h3>

<p>A common pattern used in J2EE is to bootstrap your application or root objects by looking them up in JNDI. This has long been the approach when working with JMS for example - looking up the JMS ConnectionFactory in JNDI for example.</p>

<p>You can follow a similar pattern with Guice using the <span class="nobr"><a href="http://code.google.com/p/guiceyfruit/wiki/GuiceyJndi" title="Visit page outside Confluence" rel="nofollow">GuiceyFruit JNDI Provider<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which lets you bootstrap Guice from a <b>jndi.properties</b> file which can include the Guice Modules to create along with environment specific properties you can inject into your modules and objects.</p>

<h3><a name="Bookcookbook-ConfiguringComponent%2CEndpointorRouteBuilderinstances"></a>Configuring Component, Endpoint or RouteBuilder instances</h3>

<p>You can use <a href="/confluence/display/CAMEL/Guice" title="Guice">Guice</a> to dependency inject whatever objects you need to create, be it an <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a>, <a href="/confluence/display/CAMEL/Component" title="Component">Component</a>, <a href="/confluence/display/CAMEL/RouteBuilder" title="RouteBuilder">RouteBuilder</a> or arbitrary <a href="/confluence/display/CAMEL/Bean+Integration" title="Bean Integration">bean used within a route</a>. </p>

<p>The easiest way to do this is to create your own Guice Module class which extends one of the above module classes and add a provider method for each object you wish to create. A provider method is annotated with <b>@Provides</b> as follows</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class MyModule <span class="code-keyword">extends</span> CamelModuleWithMatchingRoutes {

    @Provides
    @JndiBind(<span class="code-quote">"jms"</span>)
    JmsComponent jms(@Named(<span class="code-quote">"activemq.brokerURL"</span>) <span class="code-object">String</span> brokerUrl) {
        <span class="code-keyword">return</span> JmsComponent.jmsComponent(<span class="code-keyword">new</span> ActiveMQConnectionFactory(brokerUrl));
    }
}</pre>
</div></div>

<p>You can optionally annotate the method with <b>@JndiBind</b> to bind the object to JNDI at some name if the object is a component, endpoint or bean you wish to refer to by name in your routes.</p>

<p>You can inject any environment specific properties (such as URLs, machine names, usernames/passwords and so forth) from the jndi.properties file easily using the <b>@Named</b> annotation as shown above. This allows most of your configuration to be in Java code which is typesafe and easily refactorable - then leaving some properties to be environment specific (the jndi.properties file) which you can then change based on development, testing, production etc.</p>


<h3><a name="Bookcookbook-CreatingmultipleRouteBuilderinstancespertype"></a>Creating multiple RouteBuilder instances per type</h3>

<p>It is sometimes useful to create multiple instances of a particular <a href="/confluence/display/CAMEL/RouteBuilder" title="RouteBuilder">RouteBuilder</a> with different configurations.</p>

<p>To do this just create multiple provider methods for each configuration; or create a single provider method that returns a collection of RouteBuilder instances.</p>

<p>For example</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">import</span> org.apache.camel.guice.CamelModuleWithMatchingRoutes;
<span class="code-keyword">import</span> com.google.common.collect.Lists;

<span class="code-keyword">public</span> class MyModule <span class="code-keyword">extends</span> CamelModuleWithMatchingRoutes {

    @Provides
    @JndiBind(<span class="code-quote">"foo"</span>)
    Collection&lt;RouteBuilder&gt; foo(@Named(<span class="code-quote">"fooUrl"</span>) <span class="code-object">String</span> fooUrl) {
        <span class="code-keyword">return</span> Lists.newArrayList(<span class="code-keyword">new</span> MyRouteBuilder(fooUrl), <span class="code-keyword">new</span> MyRouteBuilder(<span class="code-quote">"activemq:CheeseQueue"</span>));
    }
}</pre>
</div></div>

<h3><a name="Bookcookbook-SeeAlso"></a>See Also</h3>

<ul>
	<li>there are a number of <a href="/confluence/display/CAMEL/Examples" title="Examples">Examples</a> you can look at to see Guice and Camel being used such as <a href="/confluence/display/CAMEL/Guice+JMS+Example" title="Guice JMS Example">Guice JMS Example</a></li>
	<li><a href="/confluence/display/CAMEL/Guice+Maven+Plugin" title="Guice Maven Plugin">Guice Maven Plugin</a> for running your Guice based routes via Maven</li>
</ul>

<h2><a name="Bookcookbook-Templating"></a>Templating</h2>

<p>When you are testing distributed systems its a very common requirement to have to stub out certain external systems with some stub so that you can test other parts of the system until a specific system is available or written etc.</p>

<p>A great way to do this is using some kind of Template system to generate responses to requests generating a dynamic message using a mostly-static body.</p>

<p>There are a number of templating components you could use</p>

<ul>
	<li><a href="/confluence/display/CAMEL/StringTemplate" title="StringTemplate">StringTemplate</a></li>
	<li><a href="/confluence/display/CAMEL/Velocity" title="Velocity">Velocity</a></li>
	<li><a href="/confluence/display/CAMEL/XQuery" title="XQuery">XQuery</a></li>
	<li><a href="/confluence/display/CAMEL/XSLT" title="XSLT">XSLT</a></li>
</ul>


<h3><a name="Bookcookbook-Example"></a>Example</h3>

<p>Here's a simple example showing how we can respond to InOut requests on the <b>My.Queue</b> queue on <a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a> with a template generated response. The reply would be sent back to the JMSReplyTo Destination.</p>

<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"activemq:My.Queue"</span>).
  to(<span class="code-quote">"velocity:com/acme/MyResponse.vm"</span>);</pre>
</div></div>

<p>If you want to use InOnly and consume the message and send it to another destination you could use</p>

<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"activemq:My.Queue"</span>).
  to(<span class="code-quote">"velocity:com/acme/MyResponse.vm"</span>).
  to(<span class="code-quote">"activemq:Another.Queue"</span>);</pre>
</div></div>

<h3><a name="Bookcookbook-SeeAlso"></a>See Also</h3>

<ul>
	<li><a href="/confluence/display/CAMEL/Mock" title="Mock">Mock</a> for details of mock endpoint testing (as opposed to template based stubs).</li>
</ul>

<h2><a name="Bookcookbook-Database"></a>Database</h2>

<p>Camel can work with databases in a number of different ways. This document tries to outline the most common approaches.</p>

<h3><a name="Bookcookbook-Databaseendpoints"></a>Database endpoints</h3>

<p>Camel provides a number of different endpoints for working with databases</p>

<ul>
	<li><a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a> for working with hibernate, openjpa or toplink. When consuming from the endpoints entity beans are read (and deleted/updated to mark as processed) then when producing to the endpoints they are written to the database (via insert/update).</li>
	<li><a href="/confluence/display/CAMEL/iBATIS" title="iBATIS">iBatis</a> similar to the above but using <span class="nobr"><a href="http://ibatis.apache.org/" title="Visit page outside Confluence" rel="nofollow">Apache iBATIS<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/CAMEL/JDBC" title="JDBC">JDBC</a> similar though using explicit SQL</li>
</ul>


<h3><a name="Bookcookbook-Databasepatternimplementations"></a>Database pattern implementations</h3>

<p>Various patterns can work with databases as follows</p>

<ul>
	<li><a href="/confluence/display/CAMEL/Idempotent+Consumer" title="Idempotent Consumer">Idempotent Consumer</a></li>
	<li><a href="/confluence/display/CAMEL/Aggregator" title="Aggregator">Aggregator</a></li>
	<li><a href="/confluence/display/CAMEL/BAM" title="BAM">BAM</a> for business activity monitoring</li>
</ul>

<h2><a name="Bookcookbook-ParallelProcessingandOrdering"></a>Parallel Processing and Ordering </h2>

<p>It is a common requirement to want to use parallel processing of messages for throughput and load balancing, while at the same time process certain kinds of messages in order.</p>

<h3><a name="Bookcookbook-Howtoachieveparallelprocessing"></a>How to achieve parallel processing</h3>

<p>You can send messages to a number of Camel <a href="/confluence/display/CAMEL/Components" title="Components">Components</a> to achieve parallel processing and load balancing such as</p>

<ul>
	<li><a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> for in-JVM load balancing across a thread pool</li>
	<li><a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a> or <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> for distributed load balancing and parallel processing</li>
	<li><a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a> for using the database as a poor mans message broker</li>
</ul>


<p>When processing messages concurrently, you should consider ordering and concurrency issues. These are described below</p>

<h4><a name="Bookcookbook-Concurrencyissues"></a>Concurrency issues</h4>

<p>Note that there is no concurrency or locking issue when using <a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a>, <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> or <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> by design; they are designed for highly concurrent use. However there are possible concurrency issues in the <a href="/confluence/display/CAMEL/Processor" title="Processor">Processor</a> of the messages i.e. what the processor does with the message? </p>

<p>For example if a processor of a message transfers money from one account to another account; you probably want to use a database with pessimistic locking to ensure that operation takes place atomically. </p>

<h4><a name="Bookcookbook-Orderingissues"></a>Ordering issues</h4>

<p>As soon as you send multiple messages to different threads or processes you will end up with an unknown ordering across the entire message stream as each thread is going to process messages concurrently. </p>

<p>For many use cases the order of messages is not too important. However for some applications this can be crucial. e.g. if a customer submits a purchase order version 1, then amends it and sends version 2; you don't want to process the first version last (so that you loose the update). Your <a href="/confluence/display/CAMEL/Processor" title="Processor">Processor</a> might be clever enough to ignore old messages. If not you need to preserve order.</p>

<h3><a name="Bookcookbook-Recommendations"></a>Recommendations</h3>

<p>This topic is large and diverse with lots of different requirements; but from a high level here are our recommendations on parallel processing, ordering and concurrency</p>

<ul>
	<li>for distributed locking, use a database by default, they are very good at it <img class="emoticon" src="/confluence/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/></li>
	<li>to preserve ordering across a JMS queue consider using <span class="nobr"><a href="http://activemq.apache.org/exclusive-consumer.html" title="Visit page outside Confluence" rel="nofollow">Exclusive Consumers<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> in the <a href="/confluence/display/CAMEL/ActiveMQ" title="ActiveMQ">ActiveMQ</a> component</li>
	<li>even better are <span class="nobr"><a href="http://activemq.apache.org/message-groups.html" title="Visit page outside Confluence" rel="nofollow">Message Groups<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> which allows you to preserve ordering across messages while still offering parallelisation via the <b>JMSXGrouopID</b> header to determine what can be parallelized</li>
	<li>if you receive messages out of order you could use the <a href="/confluence/display/CAMEL/Resequencer" title="Resequencer">Resequencer</a> to put them back together again</li>
</ul>


<p>A good rule of thumb to help reduce ordering problems is to make sure each single can be processed as an atomic unit in parallel (either without concurrency issues or using say, database locking); or if it can't, use a <span class="nobr"><a href="http://activemq.apache.org/message-groups.html" title="Visit page outside Confluence" rel="nofollow">Message Group<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to relate the messages together which need to be processed in order by a single thread.</p>

<h3><a name="Bookcookbook-UsingMessageGroupswithCamel"></a>Using Message Groups with Camel</h3>

<p>To use a Message Group with Camel you just need to add a header to the output JMS message based on some kind of <a href="/confluence/display/CAMEL/Correlation+Identifier" title="Correlation Identifier">Correlation Identifier</a> to correlate messages which should be processed in order by a single thread - so that things which don't correlate together can be processed concurrently.</p>

<p>For example the following code shows how to create a message group using an XPath expression taking an invoice's product code as the <a href="/confluence/display/CAMEL/Correlation+Identifier" title="Correlation Identifier">Correlation Identifier</a></p>

<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"activemq:a"</span>).setHeader(<span class="code-quote">"JMSXGroupID"</span>, xpath(<span class="code-quote">"/invoice/productCode"</span>)).to(<span class="code-quote">"activemq:b"</span>);</pre>
</div></div>

<p>You can of course use the <a href="/confluence/display/CAMEL/Xml+Configuration" title="Xml Configuration">Xml Configuration</a> if you prefer</p>
<h1><a name="Bookcookbook-AsynchronousProcessing"></a>Asynchronous Processing</h1>

<h2><a name="Bookcookbook-Overview"></a>Overview</h2>

<p>Camel supports a more complex asynchronous processing model.  The asynchronous processors implement the AsyncProcessor interface which is derived from the more synchronous Processor interface.  There are advantages and disadvantages when using asynchronous processing when compared to using the standard synchronous processing model.</p>

<p>Advantages:</p>
<ul>
	<li>Processing routes that are composed fully of asynchronous processors do not use up threads waiting for processors to complete on blocking calls.  This can increase the scalability of your system by reducing the number of threads needed to process the same workload.</li>
	<li>Processing routes can be broken up into <a href="/confluence/display/CAMEL/SEDA" title="SEDA">SEDA</a> processing stages where different thread pools can process the different stages.  This means that your routes can be processed concurrently.</li>
</ul>


<p>Disadvantages:</p>
<ul>
	<li>Implementing asynchronous processors is more complex than implementing the synchronous versions.</li>
</ul>


<h2><a name="Bookcookbook-WhentoUse"></a>When to Use</h2>

<p>We recommend that processors and components be implemented the more simple synchronous APIs unless you identify a performance of scalability requirement that dictates otherwise.  A Processor whose process() method blocks for a long time would be good candidates for being converted into an asynchronous processor.</p>

<h2><a name="Bookcookbook-InterfaceDetails"></a>Interface Details</h2>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-keyword">interface</span> AsyncProcessor <span class="code-keyword">extends</span> Processor {
   <span class="code-object">boolean</span> process(Exchange exchange, AsyncCallback callback);
}</pre>
</div></div>

<p>The AsyncProcessor defines a single <tt>process()</tt> method which is very similar to it's synchronous Processor.process() brethren.  Here are the differences:</p>
<ul>
	<li>A non-null AsyncCallback <b>MUST</b> be supplied which will be notified when the exchange processing is completed.</li>
	<li>It <b>MUST</b> not throw any exceptions that occurred while processing the exchange.  Any such exceptions must be stored on the exchange's Exception property.</li>
	<li>It <b>MUST</b> know if it will complete the processing synchronously or asynchronously.  The method will return <tt>true</tt> if it does complete synchronously, otherwise it returns <tt>false</tt>.</li>
	<li>When the processor has completed processing the exchange, it must call the <tt>callback.done(boolean sync)</tt> method.  The sync parameter <b>MUST</b> match the value returned by the <tt>process()</tt> method.</li>
</ul>


<h2><a name="Bookcookbook-ImplementingProcessorsthatUsetheAsyncProcessorAPI"></a>Implementing Processors that Use the AsyncProcessor API</h2>

<p>All processors, even synchronous processors that do not implement the AsyncProcessor interface, can be coerced to implement the AsyncProcessor interface.  This is usually done when you are implementing a Camel component consumer that supports asynchronous completion of the exchanges that it is pushing through the Camel routes.  Consumers are provided a Processor object when created.  All Processor object can be coerced to a AsyncProcessor using the following API:</p>

<div class="code"><div class="codeContent">
<pre class="code-java">Processor processor = ...
AsyncProcessor asyncProcessor = AsyncProcessorTypeConverter.convert(processor);</pre>
</div></div>

<p>For a route to be fully asynchronous and reap the benefits to lower Thread usage, it must start with the consumer implementation making use of the asynchronous processing API.  If it called the synchronous process() method instead, the consumer's thread would be forced to be blocked and in use for the duration that it takes to process the exchange.</p>

<p>It is important to take note that just because you call the asynchronous API, it does not mean that the processing will take place asynchronously.  It only allows the possibility that it can be done without tying up the caller's thread.  If the processing happens asynchronously is dependent on the configuration of the Camel route.</p>

<p>Normally, the the process call is passed in an inline inner AsyncCallback class instance which can reference the exchange object that was declared final.  This allows it  to finish up any post processing that is needed when the called processor is done processing the exchange.  See below for an example.</p>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">final</span> Exchange exchange = ...
AsyncProcessor asyncProcessor = ...
asyncProcessor.process(exchange, <span class="code-keyword">new</span> AsyncCallback() {
    <span class="code-keyword">public</span> void done(<span class="code-object">boolean</span> sync) {
        <span class="code-keyword">if</span> (exchange.isFailed()) {
            ... <span class="code-comment">// <span class="code-keyword">do</span> failure processing.. perhaps rollback etc.
</span>        } <span class="code-keyword">else</span> {
            ... <span class="code-comment">// processing completed successfully, finish up 
</span>                <span class="code-comment">// perhaps commit etc.
</span>        }
    }
});</pre>
</div></div>


<h2><a name="Bookcookbook-AsynchronousRouteSequenceScenarios"></a>Asynchronous Route Sequence Scenarios</h2>

<p>Now that we have understood the interface contract of the AsyncProcessor, and have seen how to make use of it when calling processors, lets looks a what the thread model/sequence scenarios will look like for some sample routes.</p>

<p>The Jetty component's consumers support async processing by using continuations.  Suffice to say it can take a http request and pass it to a camel route for async processing.  If the processing is indeed async, it uses Jetty continuation so that the http request is 'parked' and the thread is released.  Once the camel route finishes processing the request, the jetty component uses the AsyncCallback to tell Jetty to 'un-park' the request.  Jetty un-parks the request, the http response returned using the result of the exchange processing.</p>

<p>Notice that the jetty continuations feature is only used "If the processing is indeed async".  This is why AsyncProcessor.process() implementations MUST accurately report if request is completed synchronously or not.  </p>

<p>The jhc component's producer allows you to make HTTP requests and implement the AsyncProcessor interface.  A route that uses both the jetty asynchronous consumer and the jhc asynchronous producer will be a fully asynchronous route and has some nice attributes that can be seen if we take a look at a sequence diagram of the processing route.  For the route:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"jetty:http:<span class="code-comment">//localhost:8080/service"</span>).to(<span class="code-quote">"jhc:http://localhost/service-impl"</span>);</span></pre>
</div></div>

<p>The sequence diagram would look something like this:</p>

<p><img src="/confluence/download/attachments/68592/simple-async-route.png" align="absmiddle" border="0" /></p>

<p>The diagram simplifies things by making it looks like processors implement the AsyncCallback interface when in reality the AsyncCallback interfaces are inline inner classes, but it illustrates the processing flow and shows how 2 separate threads are used to complete the processing of the original http request.  The first thread is synchronous up until processing hits the jhc producer which issues the http request.  It then reports that the exchange processing will complete async since it will use a NIO to complete getting the response back.  Once the jhc component has received a full response it uses <tt>AsyncCallback.done()</tt> method to notify the caller.  These callback notifications continue up until it reaches the original jetty consumer which then un-parks the http request and completes it by providing the response.</p>

<h2><a name="Bookcookbook-MixingSynchronousandAsynchronousProcessors"></a>Mixing Synchronous and Asynchronous Processors</h2>

<p>It is totally possible and reasonable to mix the use of synchronous and asynchronous processors/components.  The pipeline processor is the backbone of a Camel processing route.  It glues all the processing steps together.  It is implemented as an AsyncProcessor and supports interleaving synchronous and asynchronous processors as the processing steps in the pipeline.  </p>

<p>Lets say we have 2 custom processors, MyValidator and MyTransformation, both of which are synchronous processors.  Lets say we want to load file from the data/in directory validate them with the MyValidator() processor, Transform them into JPA java objects using MyTransformation and then insert them into the database using the <a href="/confluence/display/CAMEL/JPA" title="JPA">JPA</a> component.  Lets say that the transformation process takes quite a bit of time and we want to allocate 20 threads to do parallel transformations of the input files.  The solution is to make use of the thread processor. The thread is AsyncProcessor that forces subsequent processing in asynchronous thread from a thread pool.</p>

<p>The route might look like:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"file:data/in"</span>).process(<span class="code-keyword">new</span> MyValidator()).thread(20).process(<span class="code-keyword">new</span> MyTransformation()).to(<span class="code-quote">"jpa:PurchaseOrder"</span>);</pre>
</div></div>

<p>The sequence diagram would look something like this:</p>

<p><img src="/confluence/download/attachments/68592/camel-mixed-processors.png" align="absmiddle" border="0" /></p>

<p>You would actually have multiple threads executing the 2nd part of the thread sequence.</p>


<h2><a name="Bookcookbook-StayingsynchronousinanAsyncProcessor"></a>Staying synchronous in an AsyncProcessor</h2>

<p>Generally speaking you get better throughput processing when you process things synchronously.  This is due to the fact that starting up an asynchronous thread and doing a context switch to it adds a little bit of of overhead.  So it is generally encouraged that AsyncProcessors do as much work as they can synchronously.  When they get to a step that would block for a long time, at that point they should return from the process call and let the caller know that it will be completing the call asynchronously.</p>

<h2><a name="Bookcookbook-ImplementingVirtualTopicsonotherJMSproviders"></a>Implementing Virtual Topics on other JMS providers</h2>

<p><span class="nobr"><a href="http://activemq.apache.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> supports <span class="nobr"><a href="http://activemq.apache.org/virtual-destinations.html" title="Visit page outside Confluence" rel="nofollow">Virtual Topics<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> since durable topic subscriptions kinda suck (see <span class="nobr"><a href="http://activemq.apache.org/virtual-destinations.html" title="Visit page outside Confluence" rel="nofollow">this page for more detail<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>) mostly since they don't support <a href="/confluence/display/CAMEL/Competing+Consumers" title="Competing Consumers">Competing Consumers</a>.</p>

<p>Most folks want Queue semantics when consuming messages; so that you can support <a href="/confluence/display/CAMEL/Competing+Consumers" title="Competing Consumers">Competing Consumers</a> for load balancing along with things like <span class="nobr"><a href="http://activemq.apache.org/message-groups.html" title="Visit page outside Confluence" rel="nofollow">Message Groups<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> and <span class="nobr"><a href="http://activemq.apache.org/exclusive-consumer.html" title="Visit page outside Confluence" rel="nofollow">Exclusive Consumers<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to preserve ordering or partition the queue across consumers.</p>

<p>However if you are using another JMS provider you can implement Virtual Topics by switching to ActiveMQ <img class="emoticon" src="/confluence/images/icons/emoticons/smile.gif" height="20" width="20" align="absmiddle" alt="" border="0"/> or you can use the following Camel pattern.</p>

<p>First here's the ActiveMQ approach.</p>

<ul>
	<li>send to <b>activemq:topic:VirtualTopic.Orders</b></li>
	<li>for consumer A consume from <b>activemq:Consumer.A.VirtualTopic.Orders</b></li>
</ul>


<p>When using another message broker use the following pattern</p>

<ul>
	<li>send to <b>jms:Orders</b></li>
	<li>add this route with a to() for each logical durable topic subscriber <div class="code"><div class="codeContent">
<pre class="code-java">from(<span class="code-quote">"jms:Orders"</span>).to(<span class="code-quote">"jms:Consumer.A"</span>, <span class="code-quote">"jms:Consumer.B"</span>, ...);</pre>
</div></div></li>
	<li>for consumer A consume from <b>jms:Consumer.A</b></li>
</ul>


<h2><a name="Bookcookbook-What%27stheCamelTransportforCXF"></a>What's the Camel Transport for CXF</h2>

<p>In CXF you offer or consume a webservice by defining it´s address. The first part of the address specifies the protocol to use. For example address="http://localhost:90000" in an endpoint configuration means your service will be offered using the http protocol on port 9000 of localhost. When you integrate Camel Tranport into CXF you get a new transport "camel". So you can specify address="camel://direct:MyEndpointName" to bind the CXF service address to a camel direct endpoint.</p>

<p>Technically speaking Camel transport for CXF is a component which implements the <span class="nobr"><a href="http://cwiki.apache.org/CXF20DOC/cxf-architecture.html#CXFArchitecture-Transports" title="Visit page outside Confluence" rel="nofollow">CXF transport API<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> with the Camel core library. This allows you to use camel´s routing engine and integration patterns support smoothly together with your CXF services.</p>


<h2><a name="Bookcookbook-IntegrateCamelintoCXFtransportlayer"></a>Integrate Camel into CXF transport layer</h2>

<p>To include the Camel Tranport into your CXF bus you use the CamelTransportFactory. You can do this in Java as well as in Spring.</p>

<h3><a name="Bookcookbook-SettinguptheCamelTransportinSpring"></a>Setting up the Camel Transport in Spring</h3>

<p>You can use the following snippet in your applicationcontext if you want to configure anything special. If you only want to activate the camel transport you do not have to do anything in your application context. As soon as you include the camel-cxf jar in your app cxf will scan the jar and load a CamelTransportFactory for you. </p>

<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;bean class=<span class="code-quote">"org.apache.camel.component.cxf.transport.CamelTransportFactory"</span>&gt;</span>
  <span class="code-tag">&lt;property name=<span class="code-quote">"bus"</span> ref=<span class="code-quote">"cxf"</span> /&gt;</span>
  <span class="code-tag">&lt;property name=<span class="code-quote">"camelContext"</span> ref=<span class="code-quote">"camelContext"</span> /&gt;</span>
  <span class="code-tag">&lt;property name=<span class="code-quote">"transportIds"</span>&gt;</span>
    <span class="code-tag">&lt;list&gt;</span>
      <span class="code-tag">&lt;value&gt;</span>http://cxf.apache.org/transports/camel<span class="code-tag">&lt;/value&gt;</span>
    <span class="code-tag">&lt;/list&gt;</span>
  <span class="code-tag">&lt;/property&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span></pre>
</div></div>

<h3><a name="Bookcookbook-IntegratingtheCamelTransportinaprogrammaticway"></a>Integrating the Camel Transport in a programmatic way</h3>

<p>Camel transport provides a setContext method that you could use to set the Camel context into the transport factory. If you want this factory take effect, you need to register the factory into the CXF bus. Here is a full example for you.</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">import</span> org.apache.cxf.Bus;
<span class="code-keyword">import</span> org.apache.cxf.BusFactory;
<span class="code-keyword">import</span> org.apache.cxf.transport.ConduitInitiatorManager;
<span class="code-keyword">import</span> org.apache.cxf.transport.DestinationFactoryManager;
...

BusFactory bf = BusFactory.newInstance();
Bus bus = bf.createBus();
CamelTransportFactory camelTransportFactory = <span class="code-keyword">new</span> CamelTransportFactory();
camelTransportFactory.setCamelContext(context)
<span class="code-comment">// register the conduit initiator
</span>ConduitInitiatorManager cim = bus.getExtension(ConduitInitiatorManager.class);
cim.registerConduitInitiator(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory);
<span class="code-comment">// register the destination factory
</span>DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
dfm.registerDestinationFactory(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory);
<span class="code-comment">// set or bus as the <span class="code-keyword">default</span> bus <span class="code-keyword">for</span> cxf
</span>BusFactory.setDefaultBus(bus);</pre>
</div></div>

<h2><a name="Bookcookbook-Configurethedestinationandconduit"></a>Configure the destination and conduit</h2>

<h3><a name="Bookcookbook-Namespace"></a>Namespace</h3>

<p>The elements used to configure an Camel transport endpoint are defined in the namespace <tt><span class="nobr"><a href="http://cxf.apache.org/transports/camel" title="Visit page outside Confluence" rel="nofollow">http://cxf.apache.org/transports/camel<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></tt>. It is commonly referred to using the prefix <tt>camel</tt>. In order to use the Camel transport configuration elements you will need to add the lines shown below to the beans element of your endpoint's configuration file. In addition, you will need to add the configuration elements' namespace to the <tt>xsi:schemaLocation</tt> attribute.</p>

<div class="code"><div class="codeHeader"><b>Adding the Configuration Namespace</b></div><div class="codeContent">
<pre class="code-java">&lt;beans ...
       xmlns:camel="http:<span class="code-comment">//cxf.apache.org/transports/camel
</span>       ...
       xsi:schemaLocation="...
                           http:<span class="code-comment">//cxf.apache.org/transports/camel
</span>                           http:<span class="code-comment">//cxf.apache.org/transports/camel.xsd
</span>                          ...&gt;</pre>
</div></div>

<h3><a name="Bookcookbook-The%7B%7Bdestination%7D%7Delement"></a>The <tt>destination</tt> element</h3>

<p>You configure an Camel transport server endpoint using the <tt>camel:destination</tt> element and its children. The <tt>camel:destination</tt> element takes a single attribute, <tt>name</tt>, the specifies the WSDL port element that corresponds to the endpoint. The value for the <tt>name</tt> attribute takes the form <em>portQName</em><tt>.camel-destination</tt>. The example below shows the <tt>camel:destination</tt> element that would be used to add configuration for an endpoint that was specified by the WSDL fragment <tt>&lt;port binding="widgetSOAPBinding" name="widgetSOAPPort&gt;</tt> if the endpoint's target namespace was <tt><span class="nobr"><a href="http://widgets.widgetvendor.net" title="Visit page outside Confluence" rel="nofollow">http://widgets.widgetvendor.net<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></tt>.</p>

<div class="code"><div class="codeHeader"><b>camel:destination Element</b></div><div class="codeContent">
<pre class="code-java">...
  &lt;camel:destination name="{http:<span class="code-comment">//widgets/widgetvendor.net}widgetSOAPPort.http-destination&gt;
</span>    &lt;camelContext id=<span class="code-quote">"context"</span> xmlns=<span class="code-quote">"http:<span class="code-comment">//activemq.apache.org/camel/schema/spring"</span>&gt;
</span>         &lt;route&gt;
           &lt;from uri=<span class="code-quote">"direct:EndpointC"</span> /&gt;
           &lt;to uri=<span class="code-quote">"direct:EndpointD"</span> /&gt;
         &lt;/route&gt;
     &lt;/camelContext&gt;
  &lt;/camel:destination&gt;
...</pre>
</div></div>

<p>The <tt>camel:destination</tt> element has a number of child elements that specify configuration information. They are described below.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Element</th>
<th class='confluenceTh'>Description</th>
</tr>
<tr>
<td class='confluenceTd'><tt>camel-spring:camelContext</tt></td>
<td class='confluenceTd'>You can specify the camel context in the camel destination</td>
</tr>
<tr>
<td class='confluenceTd'><tt>camel:camelContextRef</tt></td>
<td class='confluenceTd'>The camel context id which you want inject into the camel destination</td>
</tr>
</tbody></table>


<h3><a name="Bookcookbook-The%7B%7Bconduit%7D%7Delement"></a>The <tt>conduit</tt> element</h3>

<p>You configure an Camel transport client using the <tt>camel:conduit</tt> element and its children. The <tt>camel:conduit</tt> element takes a single attribute, <tt>name</tt>, that specifies the WSDL port element that corresponds to the endpoint. The value for the <tt>name</tt> attribute takes the form <em>portQName</em><tt>.camel-conduit</tt>. For example, the code below shows the <tt>camel:conduit</tt> element that would be used to add configuration for an endpoint that was specified by the WSDL fragment <tt>&lt;port binding="widgetSOAPBinding" name="widgetSOAPPort&gt;</tt> if the endpoint's target namespace was <tt><span class="nobr"><a href="http://widgets.widgetvendor.net" title="Visit page outside Confluence" rel="nofollow">http://widgets.widgetvendor.net<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></tt>.</p>
<div class="code"><div class="codeHeader"><b>http-conf:conduit Element</b></div><div class="codeContent">
<pre class="code-xml">...
  <span class="code-tag">&lt;camelContext id=<span class="code-quote">"conduit_context"</span> xmlns=<span class="code-quote">"http://activemq.apache.org/camel/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:EndpointA"</span> /&gt;</span>
           <span class="code-tag">&lt;to uri=<span class="code-quote">"direct:EndpointB"</span> /&gt;</span>
       <span class="code-tag">&lt;/route&gt;</span>
   <span class="code-tag">&lt;/camelContext&gt;</span>

  <span class="code-tag">&lt;camel:conduit name=<span class="code-quote">"{http://widgets/widgetvendor.net}widgetSOAPPort.camel-conduit"</span>&gt;</span>
     <span class="code-tag">&lt;camel:camelContextRef&gt;</span>conduit_context<span class="code-tag">&lt;/camel:camelContextRef&gt;</span>
  <span class="code-tag">&lt;/camel:conduit&gt;</span>

  <span class="code-tag">&lt;camel:conduit name=<span class="code-quote">"*.camel-conduit"</span>&gt;</span>
  <span class="code-tag"><span class="code-comment">&lt;!-- you can also using the wild card to specify the camel-conduit that you want to configure --&gt;</span></span>
    ...
  <span class="code-tag">&lt;/camel:conduit&gt;</span>
...</pre>
</div></div>

<p>The <tt>camel:conduit</tt> element has a number of child elements that specify configuration information. They are described below.</p>

<table class='confluenceTable'><tbody>
<tr>
<th class='confluenceTh'>Element</th>
<th class='confluenceTh'>Description</th>
</tr>
<tr>
<td class='confluenceTd'><tt>camel-spring:camelContext</tt></td>
<td class='confluenceTd'>You can specify the camel context in the camel conduit</td>
</tr>
<tr>
<td class='confluenceTd'><tt>camel:camelContextRef</tt></td>
<td class='confluenceTd'>The camel context id which you want inject into the camel conduit</td>
</tr>
</tbody></table>


<h2><a name="Bookcookbook-ExampleUsingCamelasaloadbalancerforCXF"></a>Example Using Camel as a load balancer for CXF</h2>

<p>This example show how to use the camel load balance feature in CXF, and you need load the configuration file in CXF and publish the endpoints on the address "camel://direct:EndpointA" and "camel://direct:EndpointB"</p>
<div class="code"><div class="codeContent">
<pre class="code-xml">&lt;beans xmlns=<span class="code-quote">"http://www.springframework.org/schema/beans"</span>
       <span class="code-keyword">xmlns:xsi</span>=<span class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span>
       <span class="code-keyword">xmlns:camel</span>=<span class="code-quote">"http://cxf.apache.org/transports/camel"</span>
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://cxf.apache.org/transports/camel http://cxf.apache.org/transports/camel.xsd
       http://activemq.apache.org/camel/schema/cxfEndpoint
       http://activemq.apache.org/camel/schema/cxf/cxfEndpoint.xsd
       http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
    "&gt;

   <span class="code-tag">&lt;bean id = <span class="code-quote">"roundRobinRef"</span> class=<span class="code-quote">"org.apache.camel.processor.loadbalancer.RoundRobinLoadBalancer"</span> /&gt;</span>

   <span class="code-tag">&lt;camelContext id=<span class="code-quote">"dest_context"</span> xmlns=<span class="code-quote">"http://activemq.apache.org/camel/schema/spring"</span>&gt;</span>
       <span class="code-tag">&lt;route&gt;</span>
            <span class="code-tag">&lt;from uri=<span class="code-quote">"jetty:http://localhost:9090/GreeterContext/GreeterPort"</span>/&gt;</span>
            <span class="code-tag">&lt;loadBalance ref=<span class="code-quote">"roundRobinRef"</span>&gt;</span>
              <span class="code-tag">&lt;to uri=<span class="code-quote">"direct:EndpointA"</span>/&gt;</span>
              <span class="code-tag">&lt;to uri=<span class="code-quote">"direct:EndpointB"</span>/&gt;</span>
            <span class="code-tag">&lt;/loadBalance&gt;</span>
        <span class="code-tag">&lt;/route&gt;</span>
   <span class="code-tag">&lt;/camelContext&gt;</span>

   <span class="code-tag"><span class="code-comment">&lt;!-- Inject the camel context to the Camel transport's destination --&gt;</span></span>
   <span class="code-tag">&lt;camel:destination name=<span class="code-quote">"{http://apache.org/hello_world_soap_http}CamelPort.camel-destination"</span>&gt;</span>
        <span class="code-tag">&lt;camel:camelContextRef&gt;</span>dest_context<span class="code-tag">&lt;/camel:camelContextRef&gt;</span>
   <span class="code-tag">&lt;/camel:destination&gt;</span>

<span class="code-tag">&lt;/beans&gt;</span></pre>
</div></div>

<h2><a name="Bookcookbook-CompleteHowtoandExampleforattachingCameltoCXF"></a>Complete Howto and Example for attaching Camel to CXF</h2>

<p><a href="/confluence/display/CAMEL/Better+JMS+Transport+for+CXF+Webservice+using+Apache+Camel" title="Better JMS Transport for CXF Webservice using Apache Camel">Better JMS Transport for CXF Webservice using Apache Camel</a>&nbsp;</p></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