INT-1477, added Loan Broker section to the samples, changed diagrams to be extracted from GUI tooling available in STS (with slight editing)
This commit is contained in:
BIN
src/docbkx/resources/images/bank-router.png
Normal file
BIN
src/docbkx/resources/images/bank-router.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
src/docbkx/resources/images/cafe-eip.png
Normal file
BIN
src/docbkx/resources/images/cafe-eip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
BIN
src/docbkx/resources/images/chain.png
Normal file
BIN
src/docbkx/resources/images/chain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
src/docbkx/resources/images/gateway.png
Normal file
BIN
src/docbkx/resources/images/gateway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
src/docbkx/resources/images/loan-broker-eip.png
Normal file
BIN
src/docbkx/resources/images/loan-broker-eip.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
BIN
src/docbkx/resources/images/quotes-aggregator.png
Normal file
BIN
src/docbkx/resources/images/quotes-aggregator.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -149,13 +149,251 @@ That includes Samples, so if you can't find what you are looking for let us know
|
||||
</para>
|
||||
<section id="samples-loan-broker">
|
||||
<title>Loan Broker</title>
|
||||
<para>
|
||||
In this section, we will review a <emphasis>Loan Broker</emphasis> sample application that is included in the
|
||||
Spring Integration samples. This sample is inspired by one of the samples featured in Gregor
|
||||
Hohpe's <ulink url="http://www.eaipatterns.com/ramblings.html">Ramblings</ulink>.
|
||||
</para>
|
||||
<para>The diagram below represents the entire process</para>
|
||||
<para>
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/loan-broker-eip.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/loan-broker-eip.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
<para>Now lets look at this process in more details</para>
|
||||
<para>
|
||||
At the core of EIP architecture are the very simple yet powerful concepts of Pipes and Filters and Message. Endpoints (Filters) are
|
||||
connected with one another via Channels (Pipes). The producing endpoint sends Message to the Channel and the Message is retrieved
|
||||
by the Consuming endpoint. This architecture is meant to define various mechanisms that describe How information is exchanged between
|
||||
the endpoints, without any awareness of What those endpoints are or What information they are exchanging, thus providing for a very loosely
|
||||
coupled and flexible collaboration model while also, decoupling Integration concerns from Business concerns. EIP extends this architecture
|
||||
by further defining:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>The types of pipes (Point-to-Point Channel, Publish-Subscribe Channel, Channel Adapter, etc.)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The core filters and patterns around how filters collaborate with pipes
|
||||
(Message Router, Splitters and Aggregators, various Message Transformation patterns, etc.)</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
The details and variations of this use case are very nicely described in Chapter 9 of the EIP Book, but here is the brief summary;
|
||||
A Consumer while shopping for the best Loan Quote(s) subscribes to the services of a Loan Broker, which handles details such as:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Consumer pre-screening (e.g., obtain and review the consumer's Credit history)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Determine the most appropriate Banks (e.g., based on consumer's credit history/score)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Send a Loan quote request to each selected Bank</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Collect responses from each Bank</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Filter responses and determine the best quote(s), based on consumer's requirements.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Pass the Loan quote(s) back to the consumer.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Obviously the real process of obtaining a loan quote is a bit more complex, but since our goal here is to demonstrate how
|
||||
Enterprise Integration Patterns are realized and implemented within SI, the use case has been simplified to concentrate only on
|
||||
the Integration aspects of the process. It is not an attempt to give you an advice in consumer finances.
|
||||
</para>
|
||||
<para>
|
||||
As you can see, by hiring a Loan Broker, the consumer is isolated from the details of the Loan Broker's operations, and each Loan Broker's
|
||||
operations may defer from one another to maintain competitive advantage, so whatever we assemble/implement must be flexible so any changes
|
||||
could be introduced quickly and painlessly.
|
||||
Speaking of change, the Loan Broker sample does not actually talk to any 'imaginary' Banks or Credit bureaus. Those services are stubbed out.
|
||||
Our goal here is to assemble, orchestrate and test the integration aspect of the process as a whole. Only then can we start thinking about
|
||||
wiring such process to the real services. At that time the assembled process and its configuration will not change regardless of the number
|
||||
of Banks a particular Loan Broker is dealing with, or the type of communication media (or protocols) used (JMS, WS, TCP, etc.)
|
||||
to communicate with these Banks.
|
||||
</para>
|
||||
<para> <emphasis>DESIGN</emphasis> </para>
|
||||
<para>
|
||||
As you analyze the 6 requirements above you'll quickly see that they all fall into the category of Integration concerns.
|
||||
For example, in the consumer pre-screening step we need to gather additional information about the consumer and the consumer's desires
|
||||
and enrich the loan request with additional meta information. We then have to filter such information to select the most appropriate list of
|
||||
Banks, and so on. Enrich, filter, select – these are all integration concerns for which EIP defines a solution in the form of patterns.
|
||||
SI provides an implementation of these patterns.
|
||||
</para>
|
||||
<para><emphasis>Messaging Gateway</emphasis>
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/gateway.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/gateway.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
<para>
|
||||
The <emphasis>Messaging Gateway</emphasis> pattern provides a simple mechanism to access messaging systems, including our Loan Broker.
|
||||
In SI you define the <emphasis>Gateway</emphasis> as a Plain Old Java Interface (no need to provide an implementation), configure it via the
|
||||
XML <emphasis><gateway&gr;</emphasis> element or via annotation and use it as any other Spring bean. SI will take care of
|
||||
delegating and mapping method invocations to the Messaging infrastructure by generating a <emphasis>Message</emphasis> (payload is mapped to an
|
||||
input parameter of the method) and sending it to the designated channel.
|
||||
<programlisting language="xml"><![CDATA[<gateway id="loanBrokerGateway"
|
||||
default-request-channel="loanBrokerPreProcessingChannel"
|
||||
service-interface="org.springframework.integration.samples.loanbroker.LoanBrokerGateway">
|
||||
<method name="getBestLoanQuote">
|
||||
<header name="RESPONSE_TYPE" value="BEST"/>
|
||||
</method>
|
||||
</gateway>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Our current <emphasis>Gateway</emphasis> provides two methods that could be invoked. One that will return the best single quote and another one that
|
||||
will return all quotes. Somehow downstream we need to know what type of reply the caller is looking for. The best way to achieve
|
||||
this in Messaging architecture is to enrich the content of the message with some meta-data describing your intentions.
|
||||
<emphasis>Content Enricher</emphasis> is one of the patterns that addresses this and although Spring Integration does provide a
|
||||
separate configuration element to enrich Message Headers with arbitrary data (we'll see it later), as a convenience, since
|
||||
<emphasis>Gateway</emphasis> element is responsible to construct the initial <emphasis>Message</emphasis> it provides embedded
|
||||
capability to enrich the newly created <emphasis>Message</emphasis> with arbitrary <emphasis>Message Headers</emphasis>. In our
|
||||
example we are adding header RESPONSE_TYPE with value 'BEST'' whenever the getBestQuote() method is invoked. For other method
|
||||
we are not adding any header. Now we can check downstream for an existence of this header and based on its presence and its value
|
||||
we can determine what type of reply the caller is looking for.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Based on the use case we also know there are some pre-screening steps that needs to be performed such as getting and evaluating the consumer's
|
||||
credit score, simply because some premiere Banks will only typically accept quote requests from consumers that meet a minimum credit
|
||||
score requirement. So it would be nice if the <emphasis>Message</emphasis> would be enriched with such information before it is forwarded
|
||||
to the Banks. It would also be nice if when several processes needs to be completed to provide such meta-information, those
|
||||
processes could be grouped in a single unit. In our use case we need to determine credit score and based on the credit score and some
|
||||
rule select a list of <emphasis>Message Channels</emphasis> (Bank Channels) we will sent quote request to.
|
||||
</para>
|
||||
<para><emphasis>Composed Message Processor</emphasis> </para>
|
||||
<para>
|
||||
The <emphasis>Composed Message Processor</emphasis> pattern describes rules around building endpoints that maintain control over message flow which
|
||||
consists of multiple message processors. In Sprig Integration <emphasis>Composed Message Processor</emphasis> pattern is implemented via
|
||||
<emphasis><chain></emphasis> element.
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/chain.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/chain.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
<para>
|
||||
As you can see from the above configuration we have a chain with inner header-enricher element which will further enrich the
|
||||
content of the <emphasis>Message</emphasis> with the header CREDIT_SCORE and value that will be determined by the call to a
|
||||
credit service (simple POJO spring bean identified by 'creditBureau' name) and then it will delegate to the <emphasis>Message Router</emphasis>
|
||||
</para>
|
||||
<para><emphasis>Message Router</emphasis>
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/bank-router.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/bank-router.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
<para>
|
||||
There are several implementation of <emphasis>Message Routing</emphasis> pattern available in Spring Integration. Here we are using
|
||||
router that will determine a list of channels based on evaluating an expression (Spring Expression Language) which will look at
|
||||
the credit score that was determined is the previous step and will select the list of channels from the Map bean with id 'banks'
|
||||
whose values are 'premier' or 'secondary' based o the value of credit score. Once the list of <emphasis>Channels</emphasis> is selected, the
|
||||
<emphasis>Message</emphasis> will be routed to those <emphasis>Channels</emphasis>.
|
||||
</para>
|
||||
<para>
|
||||
Now, one last thing the Loan Broker needs to to is to receive the loan quotes form the banks, aggregate them by consumer
|
||||
(we don't want to show quotes from one consumer to another), assemble the response based on the consumer's selection criteria
|
||||
(single best quote or all quotes) and reply back to the consumer.
|
||||
</para>
|
||||
<para><emphasis>Message Aggregator</emphasis>
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/quotes-aggregator.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/quotes-aggregator.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
An <emphasis>Aggregator</emphasis> pattern describes an endpoint which groups related <emphasis>Messages</emphasis> into a single
|
||||
<emphasis>Message</emphasis>. Criteria and rules can be provided to determine an aggregation and correlation strategy.
|
||||
SI provides several implementations of the <emphasis>Aggregator</emphasis> pattern as well as a convenient name-space based configuration.
|
||||
<programlisting language="xml"><![CDATA[<aggregator id="quotesAggregator"
|
||||
input-channel="quotesAggregationChannel"
|
||||
method="aggregateQuotes">
|
||||
<beans:bean class="org.springframework.integration.samples.loanbroker.LoanQuoteAggregator"/>
|
||||
</aggregator>]]></programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Our Loan Broker defines a 'quotesAggregator' bean via the <emphasis><aggregator></emphasis> element which provides a default
|
||||
aggregation and correlation strategy. The default correlation strategy correlates messages based on the <code>$corelationId</code> header
|
||||
(see <emphasis>Correlation Identifier</emphasis> pattern). What's interesting is that we never provided the value for this header.
|
||||
It was set earlier by the router automatically, when it generated a separate <emphasis>Message</emphasis> for each Bank channel.
|
||||
</para>
|
||||
<para>
|
||||
Once the <emphasis>Messages</emphasis> are correlated they are released to the actual <emphasis>Aggregator</emphasis> implementation.
|
||||
Although default <emphasis>Aggregator</emphasis> is provided by SI, its strategy (gather the list of payloads from all
|
||||
<emphasis>Messages</emphasis> and construct a new <emphasis>Message</emphasis> with this List as payload) does not satisfy our
|
||||
requirement. The reason is that our consumer might require a single best quote or all quotes. To communicate the consumer's
|
||||
intention, earlier in the process we set the RESPONSE_TYPE header. Now we have to evaluate this header and return either
|
||||
all the quotes (the default aggregation strategy would work) or the best quote (the default aggregation strategy will not work
|
||||
because we have to determine which loan quote is the best).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Obviously selecting the best quote could be based on complex criteria and would influence the complexity of the aggregator implementation and
|
||||
configuration, but for now we are making it simple. If consumer wants the best quote we will select a quote with the lowest interest
|
||||
rate. To accomplish that the LoanQuoteAggregator.java will sort all the quotes and return the first one.
|
||||
The <classname>LoanQuote.java</classname> implements <interfacename>Comparable</interfacename> which compares quotes based on the rate attribute.
|
||||
Once the response <emphasis>Message</emphasis> is created it is sent to the default-reply-channel of the <emphasis>Messaging Gateway</emphasis>
|
||||
(thus the consumer) which started the process. Our consumer got the Loan Quote!
|
||||
</para>
|
||||
<para>Conclusion</para>
|
||||
<para>
|
||||
As you can see a rather complex process was assembled based on POJO (read existing, legacy), light weight, embeddable messaging
|
||||
framework (Sprig Integration) with a loosely coupled programming model intended to simplify integration of heterogeneous systems
|
||||
without requiring a heavy-weight ESB-like engine or proprietary development and deployment environment, becouse as a developer you
|
||||
should not be porting your Swing or console-based application to an ESB-like server or implementing proprietary interfaces just
|
||||
because you have an integration concern.
|
||||
</para>
|
||||
<para>
|
||||
This and other samples in this section are build on top of Enterprise Integration Patterns that meant to describe "building blocks"
|
||||
for YOUR solution but not to be solutions in of themselves. Integration concerns exist in all types of applications (server based and not)
|
||||
and should not require change in design, testing and deployment strategy if such applications need to integrate with one another.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
<section id="samples-cafe">
|
||||
<title>The Cafe Sample</title>
|
||||
<para>
|
||||
In this section, we will review a sample application that is included in the Spring Integration
|
||||
distribution. This sample is inspired by one of the samples featured in Gregor Hohpe's
|
||||
<ulink url="http://www.eaipatterns.com/ramblings.html">Ramblings</ulink>.
|
||||
In this section, we will review a <emphasis>Cafe</emphasis> sample application that is included in the
|
||||
Spring Integration samples. This sample is inspired by another sample featured in Gregor
|
||||
Hohpe's <ulink url="http://www.eaipatterns.com/ramblings.html">Ramblings</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
The domain is that of a Cafe, and the basic flow is depicted in the following diagram:
|
||||
@@ -163,11 +401,11 @@ That includes Samples, so if you can't find what you are looking for let us know
|
||||
<para>
|
||||
<mediaobject>
|
||||
<imageobject role="fo">
|
||||
<imagedata fileref="src/docbkx/resources/images/cafe-demo.png"
|
||||
<imagedata fileref="src/docbkx/resources/images/cafe-eip.png"
|
||||
format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
<imageobject role="html">
|
||||
<imagedata fileref="images/cafe-demo.png" format="PNG" align="center"/>
|
||||
<imagedata fileref="images/cafe-eip.png" format="PNG" align="center"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</para>
|
||||
|
||||
Reference in New Issue
Block a user