Skip to content

Latest commit

 

History

History
 
 

ejb-txn-remote-call

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<meta name="author" content="Ondra Chaloupka">
<title>ejb-txn-remote-call: Demonstrates remote EJB calls and transaction propagation</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment @import statement to use as custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite::before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
:not(pre)>code.nobreak{word-wrap:normal}
:not(pre)>code.nowrap{white-space:nowrap}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details>summary:first-of-type{cursor:pointer;display:list-item;outline:none;margin-bottom:.75em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class="highlight"],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos{border-right:1px solid currentColor;opacity:.35;padding-right:.5em}
pre.pygments .lineno{border-right:1px solid currentColor;opacity:.35;display:inline-block;margin-right:.75em}
pre.pygments .lineno::before{content:"";margin-right:-.125em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
table.tableblock{max-width:100%;border-collapse:separate}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
td.tableblock>.content>:last-child.sidebarblock{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd),table.stripes-even tr:nth-of-type(even),table.stripes-hover tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
</head>
<body class="article">
<div id="header">
<h1>ejb-txn-remote-call: Demonstrates remote EJB calls and transaction propagation</h1>
<div class="details">
<span id="author" class="author">Ondra Chaloupka</span><br>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="quoteblock abstract">
<blockquote>
The <code>ejb-txn-remote-call</code> quickstart demonstrates remote transactional EJB calls over two application servers of JBoss EAP.
</blockquote>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_what_is_it">What is it?</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The <code>ejb-txn-remote-call</code> quickstart demonstrates the remote transactional EJB calls over two application servers of Red Hat JBoss Enterprise Application Platform. The remote side forms a HA cluster.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_description">Description</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The EJB remote call propagates a JTA transaction. Further, the quickstart demonstrates the transaction recovery, which is run for both servers when a failure occurs.</p>
</div>
<div class="paragraph">
<p>This quickstart contains two Maven projects.
The first maven project represents the sender side, and is intended to be deployed on the first server (<code>server1</code>).
The second project represents the called side. This project is intended to be deployed
to the other two servers (<code>server2</code> and <code>server3</code>). The two projects should not be deployed to the same server.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Maven projects in this quickstart</caption>
<colgroup>
<col style="width: 40%;">
<col style="width: 60%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Project</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>client</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An application that you deploy to the first server, to <code>server1</code>.
It includes REST endpoints that provide EJB remote calls to the <code>server application</code>
residing on the other servers.
In addition, the remote EJB calls the REST endpoint invocation process to insert data into a database.
The REST invocation starts a transaction that enlists two participants
(the database and the EJB remote invocation).
The transaction manager then uses the two-phase commit to commit the transaction
over the two servers.
Further, the quickstart examines failures and shows the transactional behaviour
in such cases.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>server</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An application that receives the remote EJB calls from the <code>client</code> application.
This <code>server</code> application is deployed to <code>server2</code> and <code>server3</code>.
The EJB component receives the EJB remote call and, depending on the scenario,
resumes on the transaction propagated in the context of the remote EJB call.
The call inserts data to the database.
The propagated transaction enlists two participants
(the database, and a mock XAResource used for quickstart demonstration purposes).</p></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="sect1">
<h2 id="_running_the_quickstart">Running the Quickstart</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The quickstart elaborates on running the example in <a href="#_running_in_a_bare_metal_environment">a bare metal environment</a> and on OpenShift.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="system_requirements">System Requirements</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The application this project produces is designed to be run on Red Hat JBoss Enterprise Application Platform 7.4 or later.</p>
</div>
<div class="paragraph">
<p>All you need to build this project is Java 8.0 (Java SDK 1.8) or later and Maven 3.3.1 or later. See <a href="https://github.com/jboss-developer/jboss-developer-shared-resources/blob/master/guides/CONFIGURE_MAVEN_JBOSS_EAP.adoc#configure_maven_to_build_and_deploy_the_quickstarts">Configure Maven to Build and Deploy the Quickstarts</a> to make sure you are configured correctly for testing the quickstarts.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="use_of_jboss_home_name">Use of the EAP_HOME_1, EAP_HOME_2, and QUICKSTART_HOME Variables</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This quickstart requires that you clone your <code><em>EAP_HOME</em></code> installation directory and run two servers. The installation path is described in detail here: <a href="https://github.com/jboss-developer/jboss-developer-shared-resources/blob/master/guides/USE_OF_EAP_HOME.adoc#use_of_product_home_and_jboss_home_variables">Use of <em>EAP_HOME</em> and <em>JBOSS_HOME</em> Variables</a>.</p>
</div>
<div class="paragraph">
<p>In the following instructions, replace <code><em>EAP_HOME_1</em></code> with the path to your first JBoss EAP server and replace <code><em>EAP_HOME_2</em></code> with the path to your second cloned JBoss EAP server.</p>
</div>
<div class="paragraph">
<p>When you see the replaceable variable <em>QUICKSTART_HOME</em>, replace it with the path to the root directory of all of the quickstarts.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run_the_quickstart_in_redhat_codeready_studio_or_eclipse">Run the Quickstart in Red Hat CodeReady Studio or Eclipse</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This quickstart is not supported in Red Hat CodeReady Studio.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_goal">The Goal</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Your goal is to set up and start 3 JBoss EAP servers, first deploys the <code>client</code>
application the other two configure a cluster and deploy the <code>server</code> application.
The EJB remote call propagates transaction from <code>client</code> application
to <code>server</code> application. The remote call hits one of the two servers where the <code>server</code> application is deployed.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_running_in_a_bare_metal_environment">Running in a bare metal environment</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_setup_productname_servers">Setup JBoss EAP servers</h3>
<div class="paragraph">
<p>The easiest way to start multiple instances on a local computer is to copy the JBoss EAP installation directory
to three separate directories.</p>
</div>
<div class="paragraph">
<p>The installation directory for <code>server1</code> (<code>client</code> application) is named <code><em>EAP_HOME_1</em></code>,
for <code>server2</code> it is named <code><em>EAP_HOME_2</em></code> (<code>server</code> application) and for <code>server3</code> it is named <code><em>EAP_HOME_3</em></code> (<code>server</code> application).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh"># considering the $EAP_HOME is installation directory of the JBoss EAP
cp -r $EAP_HOME server1
EAP_HOME_1="$PWD/server1"
cp -r $EAP_HOME server2
EAP_HOME_2="$PWD/server2"
cp -r $EAP_HOME server3
EAP_HOME_3="$PWD/server3"</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_configure_ejb_remoting_and_authentication_of_the_remote_call">Configure EJB remoting, and authentication of the remote call</h3>
<div class="paragraph">
<p>To successfully process the remote call  from <code>server1</code> to either <code>server2</code>
or to <code>server3</code> you must create a user on the receiver server
that the remote call will be authenticated to.</p>
</div>
<div class="paragraph">
<p>Run the following procedure in the directories <code><em>EAP_HOME_2</em></code> and <code><em>EAP_HOME_3</em></code> to create the user for <code>server2</code> and <code>server3</code>.</p>
</div>
<div class="sect3">
<h4 id="add_the_application_user">Add the Authorized Application User</h4>
<div class="paragraph">
<p>This quickstart uses secured application interfaces and requires that you create the following application user to access the running application.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 40%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">UserName</th>
<th class="tableblock halign-left valign-top">Realm</th>
<th class="tableblock halign-left valign-top">Password</th>
<th class="tableblock halign-left valign-top">Roles</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">quickstartUser</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">ApplicationRealm</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">quickstartPwd1!</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>To add the application user, open a terminal and type the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>$ <em>EAP_HOME</em>/bin/add-user.sh -a -u 'quickstartUser' -p 'quickstartPwd1!' </code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
For Windows, use the <code><em>EAP_HOME</em>\bin\add-user.bat</code> script.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>If you prefer, you can use the <code>add-user</code> utility interactively.
For an example of how to use the add-user utility, see the instructions located here: <a href="https://github.com/jboss-developer/jboss-developer-shared-resources/blob/master/guides/CREATE_USERS.adoc#add_an_application_user">Add an Application User</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>For the <code>add-user.sh</code> (or <code>.bat</code>) command you, can add the parameter <code>-ds</code>.
When you include this parameter, after the user is added, the system outputs a secret value that you can use to set up the remote output connection on <code>server1</code>.</p>
</div>
<div class="paragraph">
<p>The output of command when <code>-ds</code> parameter is used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>To represent the user add the following to the server-identities definition &lt;secret value="cXVpY2tzdGFydFB3ZDEh" /&gt;</pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now, you must configure <code>server1</code> to authenticate with the remote side when
the EJB call is invoked.
See the script <code>${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/remote-configuration.cli</code>
to review the commands that will be executed.
The <code>cli</code> script is configured with <code>cli.local.properties</code>
to run in <a href="https://wildfly.org/news/2015/03/13/Offline-CLI/">embedded mode</a> against the <code>standalone.xml</code>.</p>
</div>
<div id="remote_configuration_cli" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh"># go to the directory with distribution of server1
cd $EAP_HOME_1
./bin/jboss-cli.sh \
  --file=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/remote-configuration.cli \
  --properties=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/cli.local.properties</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
For Windows, use the <code>bin\jboss-cli.bat</code> script.
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>It configures a <code>remote outbound socket</code> that points to the port where EJB remoting endpoint
can be reached at <code>server2</code>.</p>
</li>
<li>
<p>It configures a <a href="https://docs.wildfly.org/22/wildscribe/subsystem/remoting/remote-outbound-connection/index.html"><code>remote outbound connection</code></a>. It is referenced in the war deployment with <code>jboss-ejb-client.xml</code> descriptor
(see <code>${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/src/main/webapp/WEB-INF/jboss-ejb-client.xml</code>).</p>
</li>
<li>
<p>It defines the security realm, using the credentials of the user created at <a href="#add_application_user">Add the Authorized Application User</a>.</p>
</li>
<li>
<p>It defines the security realm, using the credentials of the user created at <a href="#add_application_user">Add the Authorized Application User</a>.</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_configure_datasources">Configure datasources</h3>
<div class="paragraph">
<p>The EJBs perform transactional work against a database, so the servers need
to know how to connect to that database. The following steps shows how to configure
an XA datasource with the name <code>ejbJtaDs</code> for connecting to a PostgreSQL database.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>First you need a database running.
The following <a href="https://github.com/jboss-developer/jboss-developer-shared-resources/blob/master/guides/CONFIGURE_POSTGRESQL.md#download-and-install-postgresql">procedure</a> briefly summarizes the steps required to configure PostgreSQL.</p>
</div>
<div class="paragraph">
<p>For local testing purposes you can use a simple docker container:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">docker run -p 5432:5432 --rm  -ePOSTGRES_DB=test -ePOSTGRES_USER=test -ePOSTGRES_PASSWORD=test postgres:9.4 -c max-prepared-transactions=110 -c log-statement=all</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Install the JDBC driver as <a href="https://docs.wildfly.org/22/Developer_Guide.html#Class_Loading_in_WildFly">a jboss module</a>.
Using Maven artifact definition and $JBoss EAP will download
the driver during startup.<br>
Run the command on each server.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">cd $EAP_HOME_1
./bin/jboss-cli.sh "embed-server,\
  module add --name=org.postgresql.jdbc \
  --module-xml=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/postgresql-module.xml"
cd $EAP_HOME_2
# -- ditto --
cd $EAP_HOME_3
# -- ditto --</code></pre>
</div>
</div>
</li>
<li>
<p>Configure the JDBC driver. For <code>server1</code> use the configuration file <code>standalone.xml</code>;
for the <code>server2</code> and <code>server3</code> use the configuration file <code>standalone-ha.xml</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">cd $EAP_HOME_1
./bin/jboss-cli.sh "embed-server --server-config=standalone.xml,\
 /subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql.jdbc,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)"
cd $EAP_HOME_2
./bin/jboss-cli.sh "embed-server --server-config=standalone-ha.xml,\
 /subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql.jdbc,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)"
cd $EAP_HOME_3
# -- ditto --</code></pre>
</div>
</div>
</li>
<li>
<p>Configure xa-datasource for each server. For <code>server1</code> use the configuration file <code>standalone.xml</code>;
for <code>server2</code> and <code>server3</code> use the configuration file <code>standalone-ha.xml</code>.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">cd ${jbossHomeName}_1
./bin/jboss-cli.sh "embed-server --server-config=standalone.xml,\
  xa-data-source add --name=ejbJtaDs --driver-name=postgresql --jndi-name=java:jboss/datasources/ejbJtaDs --user-name=test --password=test --xa-datasource-properties=ServerName=localhost,\
  /subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=PortNumber:add(value=5432),\
  /subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=DatabaseName:add(value=test)"
cd ${jbossHomeName}_2
./bin/jboss-cli.sh "embed-server --server-config=standalone-ha.xml,\
  xa-data-source add --name=ejbJtaDs --driver-name=postgresql --jndi-name=java:jboss/datasources/ejbJtaDs --user-name=test --password=test --xa-datasource-properties=ServerName=localhost,\
  /subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=PortNumber:add(value=5432),\
  /subsystem=datasources/xa-data-source=ejbJtaDs/xa-datasource-properties=DatabaseName:add(value=test)"
cd cd ${jbossHomeName}_3
# -- ditto --</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
For Windows, use the <code>bin\jboss-cli.bat</code> script.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_start_productname_servers">Start JBoss EAP servers</h3>
<div class="paragraph">
<p>When the setup was done you can start the servers.
Start the <code>server1</code> with the <code>standalone.xml</code> configuration.
The <code>server2</code> and the <code>server3</code> comprise a cluster, you need to start them
with the <code>standalone-ha.xml</code> configuration.</p>
</div>
<div class="paragraph">
<p>For starting at the same machine you need to use the port offset
to bind every server at a different port.
Each server has to define a unique transaction node id and jboss node name.
Use the system properties <code>jboss.tx.node.id</code> and <code>jboss.node.name</code> when starting the servers.
The configuration file <code>custom-config.xml</code> refers to application user&#8217;s credentials
and making possible for the transaction recovery to authenticate to recover the remote transaction failure.</p>
</div>
<div class="paragraph">
<p>Start each server in a separate terminal.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">cd $EAP_HOME_1
./bin/standalone.sh -c standalone.xml -Djboss.tx.node.id=server1 -Djboss.node.name=server1 -Dwildfly.config.url=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/configuration/custom-config.xml

cd $EAP_HOME_2
./bin/standalone.sh -c standalone-ha.xml -Djboss.tx.node.id=server2 -Djboss.node.name=server2 -Djboss.socket.binding.port-offset=100

cd $EAP_HOME_3
./bin/standalone.sh -c standalone-ha.xml -Djboss.tx.node.id=server3 -Djboss.node.name=server3 -Djboss.socket.binding.port-offset=200</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
For Windows, use the <code>bin\standalone.bat</code> script.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_deploying_the_quickstart_applications">Deploying the Quickstart applications</h3>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Expecting the JBoss EAP servers were <a href="#_setup_productname_servers">configured</a> and <a href="#_start_productname_servers">started.</a></p>
</li>
<li>
<p>Clean and build the project by navigating to the root directory of this quickstart in terminal and running</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/
mvn clean install</code></pre>
</div>
</div>
</li>
<li>
<p>On <code>server1</code>, navigate to the <code>client</code> subfolder of the <code>ejb-txn-remote-call</code> quickstart and deploy the application <code>war</code> file.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client
mvn wildfly:deploy</code></pre>
</div>
</div>
</li>
<li>
<p>On <code>server2</code> and <code>server3</code>, navigate to the <code>server</code> subfolder of the <code>ejb-txn-remote-call</code> quickstart and deploy the application <code>war</code> file.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">cd ${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server
mvn wildfly:deploy -Dwildfly.port=10090
mvn wildfly:deploy -Dwildfly.port=10190</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>The commands should finish without any errors.
The commands connect to running instances of the JBoss EAP
and deploys the <code>war</code> archives to the servers.
If an error occurs first verify that the JBoss EAP is running
and that&#8217;s bound to the correct port.
Then consult the error message details.</p>
</div>
<div class="paragraph">
<p>If you run the commands then verify
that the deployments are published on the all three servers.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>On to <code>server1</code> check the log to confirm that the <code>client/target/client.war</code> archive is deployed.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>...
INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 76) WFLYUT0021: Registered web context: '/client' for server 'default-server'
INFO  [org.jboss.as.server] (management-handler-thread - 2) WFLYSRV0010: Deployed "client.war" (runtime-name : "client.war")</code></pre>
</div>
</div>
</li>
<li>
<p>On <code>server2</code> and <code>server3</code>, check the log to confirm that the <code>server/target/server.war</code> archive is deployed.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>...
INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 86) WFLYUT0021: Registered web context: '/server' for server 'default-server'
INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deployed "server.war" (runtime-name : "server.war")</code></pre>
</div>
</div>
</li>
<li>
<p>Verify that <code>server2</code> and <code>server3</code> formed a HA cluster.
Check the server log of either <code>server2</code> and <code>server3</code>, or both.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>[org.infinispan.CLUSTER] () ISPN000094: Received new cluster view for channel ejb: [server2|1] (2) [server2, server3]
[org.infinispan.CLUSTER] () ISPN100000: Node server3 joined the cluster
...
INFO  [org.infinispan.CLUSTER] () [Context=server.war/infinispan] ISPN100010: Finished rebalance with members [server2, server3], topology id 5</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_examining_the_quickstart">Examining the Quickstart</h3>
<div class="paragraph">
<p>After the JBoss EAP servers are configured and started, and the quickstart artifacts are deployed
you can invoke the methods and examine their results.</p>
</div>
<div class="paragraph">
<p>The <code>client.war</code> deployed to <code>server1</code> exposes several endpoints that invoke
EJB remote invocations to the HA cluster that <code>server2</code> and <code>server3</code> formed.</p>
</div>
<div class="paragraph">
<p>The expected behaviour varies depending on type
of the remote call. It depends on running the call as part of the transaction &ndash;
then the transaction affinity makes all calls to hit the same server instance.
When the calls go to stateful EJB then the affinity again ensures
the multiple calls hitting the same server instance (the calls to stateful EJB are sticky).
When the call runs against the stateless EJB out of the transaction context then
the calls should be load balanced over the both servers in the HA cluster.
The following table defines the available endpoints, and the expected behaviour
when they are invoked.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>The endpoints return data in JSON format. You can use <code>curl</code> for invocation
and <code>jq</code> command to format the results. For example:
<code>curl -s <a href="http://localhost:8080/client/remote-outbound-stateless" class="bare">http://localhost:8080/client/remote-outbound-stateless</a> | jq .</code></p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>On Windows, the <code>curl</code> and <code>jq</code> commands might not be available.
If so, enter the endpoints directly to a browser of your choice.
The behaviour and the obtained JSON will be the same as for the <code>curl</code> command.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The HTTP invocations return the hostnames of the contacted servers.</p>
</div>
<table id="rest-endpoints" class="tableblock frame-all grid-all stretch">
<caption class="title">Table 2. HTTP endpoints of the test invocation</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">URL</th>
<th class="tableblock halign-left valign-top">Behaviour</th>
<th class="tableblock halign-left valign-top">Expectation</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/remote-outbound-stateless" class="bare">http://localhost:8080/client/remote-outbound-stateless</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Two invocations under the transaction context started on <code>server1</code> (<code>client</code> application).
The EJB remote call is configured from the <code>remote-outbound-connection</code>.
Both calls are directed to the same remote server instance (<code>server</code> application)
due to transaction affinity.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The two returned hostnames must be the same.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/remote-outbound-notx-stateless" class="bare">http://localhost:8080/client/remote-outbound-notx-stateless</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Seven remote invocations to stateless EJB without a transaction context.
The EJB remote call is configured from the <code>remote-outbound-connection</code>.
The EJB client is expected to load balance the calls on various servers.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The list of the returned hostnames should contain occurrences of both
 <code>server2</code> and <code>server3</code>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/direct-stateless" class="bare">http://localhost:8080/client/direct-stateless</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Two invocations under the transaction context started on <code>server1</code> (<code>client</code> application). The stateless bean is invoked on the remote side.
The EJB remote call is configured from data in the <code>client</code> application source code.
The remote invocation is run via the EJB remoting protocol.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The returned hostnames must be the same.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/direct-stateless-http" class="bare">http://localhost:8080/client/direct-stateless-http</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Two invocations under the transaction context started on <code>server1</code> (<code>client</code> application). The stateless bean is invoked on the remote side.
The EJB remote call is configured from data in the <code>client</code> application source code.
The remote invocation is run, unlike the other calls of this quickstarts, via <a href="https://docs.wildfly.org/22/Developer_Guide.html#EJB_over_HTTP">EJB over HTTP</a>.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The returned hostnames must be the same.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/remote-outbound-notx-stateful" class="bare">http://localhost:8080/client/remote-outbound-notx-stateful</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Two invocations under the transaction context stared on <code>server1</code> (<code>client</code> application).
The EJB remote call is configured from the <code>remote-outbound-connection</code>.
Both calls are directed to the same stateful bean on the remote server because
the stateful bean invocations are sticky ensuring affinity to the same server instance.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The returned hostnames must be the same.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em><a href="http://localhost:8080/client/remote-outbound-fail-stateless" class="bare">http://localhost:8080/client/remote-outbound-fail-stateless</a></em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An invocation under the transaction context started on <code>server1</code> (<code>client</code> application).
The call goes to one of the remote servers, where errors occur during transaction processing.
The failure is simulated at time of two-phase commit.
This HTTP call finishes with success. Only the server log shows some warnings.
This is an expected behaviour. An intermittent failure during commit phase
of two-phase protocol makes the transaction manager obliged to finish the work
eventually. The finalization of work is done in the background
(by Narayana recovery manager, see details <a href="#_details_on_recovery">below</a>), and the HTTP call may inform the client back with success.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">When the recovery manager finishes the work all the transaction resources are committed.</p></td>
</tr>
</tbody>
</table>
<div class="sect3">
<h4 id="_details_on_recovery">Observing the recovery processing after <em>client/remote-outbound-fail-stateless</em> call</h4>
<div class="paragraph">
<p>The EJB call simulates the presence of an intermittent network error
happening at the commit phase of two-phase commit protocol (2PC).</p>
</div>
<div class="paragraph">
<p>The <a href="http://jbossts.blogspot.com/2018/01/narayana-periodic-recovery-of-xa.html">transaction recovery manager</a>
periodically retries to recover the unfinished work.
When it makes the work successfully committed, the transaction is complete,
and the database update will be visible. You can confirm the database update
was processed by issuing REST endpoint reporting number of finished commits.</p>
</div>
<div class="paragraph">
<p>You can invoke the endpoint <code>server/commits</code> at both servers <code>server2</code> and <code>server3</code>
where <code>server</code> application is deployed (i.e. <em><a href="http://localhost:8180/server/commits" class="bare">http://localhost:8180/server/commits</a></em>
and <em><a href="http://localhost:8280/server/commits" class="bare">http://localhost:8280/server/commits</a></em>).
The output of this command is a tuple. It shows the node info, and the number of commits recorded. For example the output could be <code>["host: mydev.narayana.io/192.168.0.1, jboss node name: server2","3"]</code> and it says that the hostname is <code>mydev.narayana.io</code>, the jboss node name is <code>server2</code>,
and the number of commits is <code>3</code>.</p>
</div>
<div class="paragraph">
<p>Transaction recovery manager runs periodically (by default, it runs every 2 minutes)
on all servers. The transaction was initiated on <code>server1</code>,
and you will need to wait until is initiated there.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<div class="paragraph">
<p>You can speed up the process and invoke the recovery process manually by accessing
the port on which the recovery process listens.
When the <a href="https://docs.wildfly.org/22/wildscribe/subsystem/transactions/index.html#attr-recovery-listener">listener is enabled</a> you can force the recovery to start on demand.
Use <code>telnet</code> to send the <code>SCAN</code> command to the recovery manager socket at <code>localhost:4712</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>telnet localhost 4712
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
SCAN
DONE
Connection closed by foreign host.</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="_steps_to_observe_recovery_processing">Steps to observe that the recovery processing was done</h5>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Before the executing the <em>remote-outbound-fail-stateless</em> endpoint do verify
how many <code>commits</code> are counted on <code>server2</code> and <code>server3</code> by executing the <code>/commits</code>
HTTP endpoints.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">curl http://localhost:8180/server/commits; echo
# output:
# ["host: mydev.narayana.io/192.168.0.1, jboss node name: server2","1"]
curl http://localhost:8280/server/commits; echo
# output:
# ["host: mydev.narayana.io/192.168.0.1, jboss node name: server3","2"]</code></pre>
</div>
</div>
</li>
<li>
<p>Invoke the HTTP request to <em><a href="http://localhost:8080/client/remote-outbound-fail-stateless" class="bare">http://localhost:8080/client/remote-outbound-fail-stateless</a></em></p>
<div class="paragraph">
<p>The output prints the name of server the request hits.
Immediately verify the number of commits finished by running the <code>/commit</code> HTTP endpoint at that server again.</p>
</div>
</li>
<li>
<p>Verify that the number of commits has not changed yet.</p>
</li>
<li>
<p>Check the log of <code>server1</code> for the following warning message</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>ARJUNA016036: commit on &lt; formatId=131077, gtrid_length=35, bqual_length=36, tx_uid=..., node_name=server1, branch_uid=..., subordinatenodename=null, eis_name=unknown eis name &gt; (Subordinate XAResource at remote+http://localhost:8180) failed with exception $XAException.XA_RETRY: javax.transaction.xa.XAException: WFTXN0029: The peer threw an XA exception</code></pre>
</div>
</div>
<div class="paragraph">
<p>The message means that the transaction manager was not able to commit the transaction.
An error occurred during committing the transaction on the remote server.
The <code>XAException.XA_RETRY</code> exception, meaning an intermittent failure, was reported to the log.</p>
</div>
</li>
<li>
<p>The logs on <code>server2</code> or <code>server3</code> contain a warning about the <code>XAResource</code> failure as well.</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>ARJUNA016036: commit on &lt; formatId=131077, gtrid_length=35, bqual_length=43, tx_uid=..., node_name=server1, branch_uid=..., subordinatenodename=server2, eis_name=unknown eis name &gt; (org.jboss.as.quickstarts.ejb.mock.MockXAResource@731ae22) failed with exception $XAException.XAER_RMFAIL: javax.transaction.xa.XAException</code></pre>
</div>
</div>
</li>
<li>
<p>Wait (or force) recovery to be processed at <code>server1</code>.</p>
</li>
<li>
<p>The number of commits on the targeted server instance has increased by one.</p>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="undeploy_the_quickstart">Undeploy the Quickstart</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When you are finished testing the quickstart, follow these steps to undeploy the archive.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Make sure you <a href="#start_the_eap_standalone_server">start the JBoss EAP server</a> as described above.</p>
</li>
<li>
<p>Open a terminal and navigate to the root directory of this quickstart.</p>
</li>
<li>
<p>Type this command to undeploy the archive:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>$ mvn wildfly:undeploy</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Repeat the same for the <code>server2</code> and <code>server3</code> by navigating
to the quickstart sub-folder <code>${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server</code> and run:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">mvn wildfly:undeploy -Dwildfly.port=10090
mvn wildfly:undeploy -Dwildfly.port=10190</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="_server_log_expected_warnings_and_errors">Server Log: Expected Warnings and Errors</h3>
<div class="paragraph">
<p>This quickstart is not production grade. The server log includes the following
warnings during the startup. It is safe to ignore these warnings.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code>WFLYDM0111: Keystore standalone/configuration/application.keystore not found, it will be auto generated on first use with a self signed certificate for host localhost

WFLYELY01084: KeyStore .../standalone/configuration/application.keystore not found, it will be auto generated on first use with a self-signed certificate for host localhost

WFLYSRV0018: Deployment "deployment.server.war" is using a private module ("org.jboss.jts") which may be changed or removed in future versions without notice.</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_running_on_openshift">Running on OpenShift</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_openshift_deployment">OpenShift deployment</h3>
<div class="paragraph">
<p>Before deploying this quickstart to OpenShift Container Platform we need to inspect
a bit the platform. The JBoss EAP server runs in a pod. The pod is an ephemeral object
that could be rescheduled, restarted or moved to a different machine by the platform.
The ephemeral nature of the pod is a poor match for the transaction manager handling transactions
and for EJB remoting passing the context as well.
The transaction manager requires a persistent log to be saved
for each JBoss EAP server instance.
The EJB remoting requires a stable remote endpoint for connection to guarantee
the state of stateful beans and the transaction affinity.
The stability of the remote endpoint address is important for transaction
recovery calls to eventually finish the transactions too.
For these properties being guaranteed from the platform
we use <em>StatefulSet</em> object in OpenShift.</p>
</div>
<div class="paragraph">
<p>The recommended way to deploy applications to JBoss EAP is using
the JBoss EAP Operator which utilizes the StatefulSet to manage JBoss EAP
as the default option in the background.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
<a href="../shared-doc/cd-openshift-getting-started.adoc">Other quickstarts discuss deploying</a>
      of the applications with <em>ReplicaSet</em> defined by DeploymentConfig in a template.
      It&#8217;s a different approach that does not match well with the transaction affinity
      and cannot be used here.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_running_on_openshift_prerequisites">Running on OpenShift: Prerequisites</h3>
<div class="sect4">
<h5 id="prepare_openshift_for_quickstart_deployment">Prepare OpenShift for Quickstart Deployment</h5>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Log in to your OpenShift instance using the <code>oc login</code> command.</p>
</li>
<li>
<p>Create a new project for the quickstart in OpenShift. You can create a project in OpenShift using the following command.</p>
<div class="listingblock">
<div class="content">
<pre class="nowrap">$ oc new-project ejb-txn-remote-call-project</pre>
</div>
</div>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_start_postgresql_database">Running on OpenShift: Start PostgreSQL database</h4>
<div class="paragraph">
<p>The quickstart requires the PostgreSQL database to be running.
For testing purposes you can use the provided yaml template
which deploys the database on your OpenShift instance
(usable only for the testing purpose).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh"># change path to ${PATH_TO_QUICKSTART_DIR}
cd ${PATH_TO_QUICKSTART_DIR}
# deploy not-production ready XA capable PostgreSQL database to OpenShift
oc new-app --namespace=$(oc project -q) \
           --file=${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/extensions/postgresql.deployment.yaml</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_build_the_application">Running on OpenShift: Build the application</h4>
<div class="paragraph">
<p>For building the application the JBoss EAP s2i functionality
(provided out-of-boxy by OpenShift) needs to be used.</p>
</div>
<div class="paragraph">
<p>The JBoss EAP provides <code>ImageStream</code> definition of builder images and runtime images.
The builder image makes the application to be build, configure the application server
with s2i scripts. The resulted image may be used for running,
but it&#8217;s big as it contains many dependencies needed only for the build.
The chain build defines the next step which is to get the runtime image
and copy there the configured JBoss EAP server with the application.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh"># Install builder and runtime image streams
oc create -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/eap74/eap74-openjdk11-image-stream.json

# Deploy template with chain build to get the quickstart
# being deployed within runtime image
oc create -f https://raw.githubusercontent.com/jboss-container-images/jboss-eap-openshift-templates/master/eap-s2i-build.yaml</code></pre>
</div>
</div>
<div class="paragraph">
<p>The final step for starting the application start
is the <code>s2i</code> chain build execution.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh"># s2i chain build for client application
oc new-app --template=eap-s2i-build \
  -p EAP_IMAGESTREAM_NAMESPACE=$(oc project -q) \
  -p APPLICATION_IMAGE=client \
  -p SOURCE_REPOSITORY_URL=https://github.com/jboss-developer/jboss-eap-quickstarts \
  -p SOURCE_REPOSITORY_REF=7.4.x \
  -p CONTEXT_DIR=ejb-txn-remote-call/client \
  -p EAP_IMAGE=jboss-eap74-openjdk11-openshift \
  -p EAP_RUNTIME_IMAGE=jboss-eap74-openjdk11-runtime-openshift
# s2i chain build for server application
oc new-app --template=eap-s2i-build \
  -p EAP_IMAGESTREAM_NAMESPACE=$(oc project -q) \
  -p APPLICATION_IMAGE=server \
  -p SOURCE_REPOSITORY_URL=https://github.com/jboss-developer/jboss-eap-quickstarts \
  -p SOURCE_REPOSITORY_REF=7.4.x \
  -p CONTEXT_DIR=ejb-txn-remote-call/server \
  -p EAP_IMAGE=jboss-eap74-openjdk11-openshift \
  -p EAP_RUNTIME_IMAGE=jboss-eap74-openjdk11-runtime-openshift</code></pre>
</div>
</div>
<div class="paragraph">
<p>Wait for the builds to finish. You can verify the build status by executing
the <code>oc get pod</code> command.</p>
</div>
<div class="paragraph">
<p>The expected output, after few whiles, shows that the <code>*-build</code> jobs
have got the value <code>Completed</code> in the <code>STATUS</code> column.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">oc get pod
NAME                                READY   STATUS      RESTARTS   AGE
client-2-build                      0/1     Completed   0          35m
client-build-artifacts-1-build      0/1     Completed   0          45m
server-2-build                      0/1     Completed   0          15m
server-build-artifacts-1-build      0/1     Completed   0          19m</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_install_productname_operator">Running on OpenShift: Install JBoss EAP Operator</h4>
<div class="paragraph">
<p>With the prior step we have got the application image with the server being part of.
The next step is to install the JBoss EAP Operator which is responsible
for managing the life cycle of the application image.</p>
</div>
<div class="paragraph">
<p>Consult necessary steps to install the JBoss EAP Operator
at JBoss EAP documentation
<a href="https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/" class="bare">https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/</a></p>
</div>
<div class="paragraph">
<p>The following steps can be used as a quickstart guide</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh"># 1. log in to account with cluster-admin permission
# 2. create a YAML file containing Subscription object
cat &gt;&gt; /tmp/eap-operator-sub.yaml &lt;&lt; EOF
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: eap
  namespace: openshift-operators
spec:
  channel: alpha
  installPlanApproval: Automatic
  name: eap
  source: redhat-operators
  sourceNamespace: openshift-marketplace
EOF
# 3. create the Subscription object in the OpenShift
oc apply -f eap-operator-sub.yaml
# 4. verify the openshift-operators namespace that the object was created
oc get csv -n openshift-operators</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_run_the_quickstart_with_productname_operator">Running on OpenShift: Run the Quickstart with JBoss EAP Operator</h4>
<div class="paragraph">
<p>After you install the JBoss EAP Operator, you can deploy the`CustomResource` that uses it.
The <code>CustomResource.yaml</code> definition contains information the JBoss EAP Operator uses
to start the application pods for the client application and for the server application.</p>
</div>
<div class="paragraph">
<p>Before deploying the application, ensure the <code>view</code> permissions for the default system account
is set up. The <code>KUBE_PING</code> protocol, that is used for forming the HA JBoss EAP cluster
on OpenShift, requires <code>view</code> permissions to read labels of pods.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-sh" data-lang="sh">oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default -n $(oc project -q)</code></pre>
</div>
</div>
<div class="paragraph">
<p>After granting the permissions, deploy the <code>CustomResource</code>, managed by JBoss EAP Operator
that, referencing to the <a href="#_running_on_openshift_build_the_application">built application images</a>.</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<div class="title">Caution</div>
</td>
<td class="content">
<div class="paragraph">
<p>Adjust the value of the <code>applicationImage</code> value in the OpenShift deployment templates
<code>${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/client/client-cr.yaml</code> and
<code>${PATH_TO_QUICKSTART_DIR}/ejb-txn-remote-call/server/server-cr.yaml</code>
to match the project. It is the most probably ejb-txn-remote-call-project.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">cd ${PATH_TO_QUICKSTART_DIR}

# deploying client definition, one replica, PostgreSQL database has to be available
oc create -f ejb-txn-remote-call/client/client-cr.yaml
# deploying server definition, two replicas, PostgreSQL database has to be available
oc create -f ejb-txn-remote-call/server/server-cr.yaml</code></pre>
</div>
</div>
<div class="paragraph">
<p>If these commands are successful, the <code>oc get pod</code> command shows
all the pods required for the quickstart, namely the quickstart client and two
server pods and the PostgreSQL database pod that the application connects to.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">NAME                                READY   STATUS      RESTARTS   AGE
client-0                            1/1     Running     0          29m
postgresql-f9f475f87-l944r          1/1     Running     1          22h
server-0                            1/1     Running     0          11m
server-1                            1/1     Running     0          11m</code></pre>
</div>
</div>
<div class="paragraph">
<p>To observe the JBoss EAP Operator look at</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">oc get po -n openshift-operators

NAME                            READY   STATUS    RESTARTS   AGE
eap-operator-75c77c789c-2zdnd   1/1     Running   0          86m</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_verify_the_quickstarts">Running on OpenShift: Verify the Quickstarts</h4>
<div class="paragraph">
<p>The JBoss EAP Operator creates routes that make the applications accessible
outside the OpenShift environment. Run the <code>oc get route</code> command to find the location of the REST endpoint.
An example of the output is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">NAME           HOST/PORT                                                            PATH   SERVICES              PORT
client-route   client-route-ejb-txn-remote-call-client-artifacts.apps-crc.testing          client-loadbalancer   http
server-route   server-route-ejb-txn-remote-call-client-artifacts.apps-crc.testing          server-loadbalancer   http</code></pre>
</div>
</div>
<div class="paragraph">
<p>For HTTP endpoints provided by the quickstart application
check <a href="#rest-endpoints">the table above</a>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh">curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-notx-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/direct-stateless | jq .
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-notx-stateful | jq .</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you like to <a href="#_steps_to_observe_recovery_processing">observe the recovery processing</a>
then you can follow these shell commands.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight nowrap"><code class="language-sh" data-lang="sh"># To check failure resolution
# verify the number of commits that come from the first and second node of the `server` deployments.
# Two calls are needed, as each reports the commit count of different node.
# Remember the reported number of commits to be compared with the results after crash later.
curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits

# Run the remote call that causes the JVM of the server to crash.
curl -s $(oc get route client-route --template='{{ .spec.host }}')/client/remote-outbound-fail-stateless
# The platforms restarts the server back to life.
# The following commands then make us waiting while printing the number of commits happened at the servers.
while true; do
  curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
  curl -s $(oc get route server-route --template='{{ .spec.host }}')/server/commits
  I=$((I+1))
  echo " &lt;&lt;&lt; Round: $I &gt;&gt;&gt;"
  sleep 2
done</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_on_openshift_quickstart_application_removal">Running on OpenShift: Quickstart application removal</h4>
<div class="paragraph">
<p>To remove the application you need to remove the <code>WildFlyServer</code> definition
(which was deployed by <a href="#_running_on_openshift_run_the_quickstart_with_productname_operator"><code>*-cr</code> yaml descriptor</a>).
You can do that by running <code>oc remove WildFlyServer client</code>
and <code>oc remove WildFlyServer server</code>.
With that the application will be stopped, and the pods will be removed.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_conclusion">Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This quickstarts is a showcase for the EJB remoting calls from one JBoss EAP server
to other with transaction propagation being involved.
It shows things from multiple areas from setting-up the datasources, through security definition
for remote connection, EJB remoting in the application, up to observing the transaction recovery processing.
On top of that it shows running this all in OpenShift managed with JBoss EAP Operator.</p>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2021-06-23 15:53:25 UTC
</div>
</div>
</body>
</html>