finish nms quickstart docs

add minimal wcf quickstart docs
This commit is contained in:
markpollack
2008-08-14 08:09:02 +00:00
parent 3f5d910936
commit 2e9f948ffd
11 changed files with 299 additions and 69 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

View File

@@ -45,6 +45,7 @@
<!ENTITY tx-quickstart SYSTEM "tx-quickstart.xml">
<!ENTITY quartz-quickstart SYSTEM "quartz-quickstart.xml">
<!ENTITY nms-quickstart SYSTEM "nms-quickstart.xml">
<!ENTITY wcf-quickstart SYSTEM "wcf-quickstart.xml">
<!ENTITY javadevelopers SYSTEM "javadevelopers.xml">
<!ENTITY misc SYSTEM "misc.xml">
<!ENTITY pooling-example SYSTEM "pooling-example.xml">
@@ -59,7 +60,7 @@
<title>The Spring.NET Framework</title>
<subtitle>Reference Documentation</subtitle>
<releaseinfo>Version 1.2.0 M1</releaseinfo>
<pubdate>Last Updated July 16, 2008</pubdate>
<pubdate>Last Updated August 15,2008</pubdate>
<authorgroup>
<author>
<firstname>Mark</firstname>
@@ -375,6 +376,9 @@
<listitem>
<xref linkend="nms-quickstart" />
</listitem>
<listitem>
<xref linkend="wcf-quickstart" />
</listitem>
</itemizedlist>
</partintro>
&quickstarts;
@@ -386,6 +390,7 @@
&tx-quickstart;
&quartz-quickstart;
&nms-quickstart;
&wcf-quickstart;
</part>
<part id="index-javadevelopers">
<title>Spring.NET for Java developers</title>

View File

@@ -189,13 +189,12 @@
higher level than the traditional messaging APIs such as JMS and NMS
since you are programing to a service interface and use metadata (either
XML or attributes) to configure the messaging behavior. If you prefer to
use this service-oriented, RPC style approach, to messaging middleware
then look to see if a vendor provides a WCF binding for your messaging
provider. Note that even with the option of using WCF, many people
prefer to sit 'closer to the metal' when using messaging middleware, to
access specific features and functionality not available in WCF, or
simply because they are more comfortable with that programming
model.</para>
use this service-oriented, RPC style approach, then look to see if a
vendor provides a WCF binding for your messaging provider. Note that
even with the option of using WCF, many people prefer to sit 'closer to
the metal' when using messaging middleware, to access specific features
and functionality not available in WCF, or simply because they are more
comfortable with that programming model.</para>
</section>
</section>
@@ -1156,6 +1155,15 @@ namespace MyApp
<entry><para>An optional message selector for this
listener.</para></entry>
</row>
<row>
<entry>pubsub-domain</entry>
<entry><para>An optional boolean value. Set to true for the publish-subscribe domain
(Topics) or false (the default) for point-to-point domain (Queues). This is useful
when using the default implementation for destination resolvers.
</para></entry>
</row>
</tbody>
</tgroup>
</table>
@@ -1294,28 +1302,43 @@ namespace MyApp
<section>
<title>TIBCO EMS Specific Details</title>
<para>Caching of messaging resources is usually done by a wrapping the
'raw provider' provider implementation with an implementation that will
cache messaging resources. The resources that are candidates for caching
are the Connection, Session, and MessageProducer. The JMS specification
requires that the Connection be thread safe. The Session and
MessageProducer are not required to be thread safe but they are in TIBCO's
implementation. The most important resource to cache is the JMS Connection
since the flow of events in the message template class (EmsTemplate) is to
create/close a connection on each operation and this is an expensive
operation.</para>
<para>This section covers functionality and behavior that is different
than described previously and is specific to TIBCO EMS.</para>
<para>Spring provides a convenience class, SingleConnectionFactory, in
which the same Connection is returned on calls to CreateConnection() and
all calls to .Close() on the returned Connection are ignored. Since
TIBCO's Connection class does not have an interface nor virtual methods
this strategy is not possible. An alternative strategy used is to
'hard-code' the caching of these resources within EmsTemplate and
SimpleMessageContainer. This functionality is controlled by the property
<property>CacheJmsResources</property> and is set to true by default,
resulting in caching of Connection, Session, and MessageProducer. When
using the TIBCO EMS binding for the NMS APIs you do not need to set this
property and can instead use one of the wrapper implementations in Spring
based on the NMS API that performs caching of messaging resources.</para>
<section>
<title>Resource Management</title>
<para>Caching of messaging resources is usually done by a wrapping the
'raw provider' provider implementation with an implementation that will
cache messaging resources. The resources that are candidates for caching
are the Connection, Session, and MessageProducer. The JMS specification
requires that the Connection be thread safe. The Session and
MessageProducer are not required to be thread safe but they are in
TIBCO's implementation. The most important resource to cache is the EMS
Connection since the flow of events in the message template class
(EmsTemplate) is to create/close a connection on each operation and this
is an expensive operation.</para>
<para>Spring provides a convenience class, SingleConnectionFactory, in
which the same Connection is returned on calls to CreateConnection() and
all calls to .Close() on the returned Connection are ignored. Since
TIBCO's Connection class does not have an interface nor virtual methods
this strategy is not possible. An alternative strategy used is to
'hard-code' the caching of these resources within EmsTemplate and
SimpleMessageContainer. This functionality is controlled by the property
<property>CacheJmsResources</property> and is set to true by default,
resulting in caching of Connection, Session, and MessageProducer. When
using the TIBCO EMS binding for the NMS APIs you do not need to set this
property and can instead use one of the wrapper implementations in
Spring based on the NMS API that performs caching of messaging
resources.</para>
</section>
<section>
<title>Queue browsing in EmsTemplate</title>
<para>The following queue browsing operations are available on
EmsTemplate</para>
</section>
</section>
</chapter>

View File

@@ -9,19 +9,22 @@
messaging to implement a system for purchasing a stock. To purchase a
stock, a client application will send a stock request message containing
the information about the stock, i.e. ticker symbol, quantity, etc. The
client request message will be recieved by the server where it will
perform business processing on the requst, for example to determine if the
user has sufficient credit to purchase the stock or if the user is even
allowed to make the purchase due to existing account restrictions. Usually
the server application will persist state about the request and forward it
on to an execute venue where the actual execution of the stock request is
peformed. In addition, market data for the stock will be sent from the
server process to the client. The high level messaging flow is shown
below.</para>
client request message will be received by the server where it will
perform business processing on the request, for example to determine if
the user has sufficient credit to purchase the stock or if the user is
even allowed to make the purchase due to existing account restrictions.
These are typically external processes as well. Usually the server
application will persist state about the request and forward it on to an
execute venue where the actual execution of the stock request is
performed. In addition, market data for the stock will be sent from the
server process to the client. The high level exchange of information is
shown below.</para>
<para></para>
<para></para>
<mediaobject>
<imageobject>
<imagedata fileref="images/nms-quickstart.jpg" scale="75" />
</imageobject>
</mediaobject>
</section>
<section>
@@ -42,9 +45,14 @@
one based on messaging or another middleware technology. The messaging
flow showing the queues and topics used is shown below.</para>
<para> </para>
<mediaobject>
<imageobject>
<imagedata fileref="images/nms-quickstart-msg-destinations.jpg"
role="" scale="75" />
</imageobject>
</mediaobject>
<para></para>
<para>Queues are shown in red and topics in green.</para>
</section>
<section>
@@ -52,7 +60,7 @@
<para>Gateways represent the service operation to send a message. The
client will send a stock request to the server based on the contract
defined by the <classname>IStockService</classname> interface . </para>
defined by the <classname>IStockService</classname> interface .</para>
<programlisting> public interface IStockService
{
@@ -61,7 +69,7 @@
<para>The server will send market data to the clients based on the
contract defined by the <classname>IMarketDataService</classname>
interface. </para>
interface.</para>
<programlisting> public interface IMarketDataService
{
@@ -78,7 +86,7 @@
created. Implementations that use messaging to communicate will be based
on the Spring's <classname>NmsGateway</classname> class and will be
discussed later. stub or mock implementations can be used for testing
purposes. </para>
purposes.</para>
</section>
<section>
@@ -113,7 +121,7 @@
</programlisting>
<para>Running xsd.exe on this schema will result in a class that contains
properties for each of the element names. A parital code listing of the
properties for each of the element names. A partial code listing of the
TradeRequest class is shown below</para>
<programlisting>// This code was generated by a tool.
@@ -148,7 +156,7 @@
<para>When sending a response back to the client the type
<classname>TradeResponse</classname> will be used. The schema for the
<classname>TradeResponse</classname> is shown below </para>
<classname>TradeResponse</classname> is shown below</para>
<programlisting>&lt;xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://www.springframework.net/nms/common/2008-08-05"&gt;
@@ -202,10 +210,10 @@
</section>
<section>
<title>Mesage Handlers</title>
<title>Message Handlers</title>
<para>When the <classname>TradeRequest</classname> message is received by
the server, it wll be handled by the class
the server, it will be handled by the class
<classname>Spring.NmsQuickStart.Server.Handlers.StockAppHandler
</classname>shown below</para>
@@ -236,6 +244,186 @@
}
}</programlisting>
<para>The stub implementations of the services, located in the namespace
<literal>Spring.NmsQuickStart.Server.Services.Stubs</literal>, will result
in always sending back a error-free trade response message. A realistic
implementation would likely have the execution venue and trading service
be remote services and the trading service could be implemented as a local
transactional service layer that uses spring's declarative transaction
management features.</para>
<para>The client will receive a TradeResponse message as well as a
Hashtable of data representing the market data. The message handle for the
client is the class Spring.NmsQuickStart.Client.Handlers.StockAppHandler
and is shown below.</para>
<programlisting> public class StockAppHandler
{
// definition of stockController omitted for brevity.
public void Handle(Hashtable data)
{
// forward to controller to update view
stockController.UpdateMarketData(data);
}
public void Handle(TradeResponse tradeResponse)
{
// forward to controller to update view
stockController.UpdateTrade(tradeResponse);
}
}</programlisting>
<para>What is important to note about these handlers is that they contain
no messaging API artifacts. As such you can write unit and integration
tests against these classes independent of the middleware. The missing
link between the messaging world and the objects processed by the message
handlers are message converters. Spring's messaging helper classes, i.e.
SimpleMessageListenerContainer and NmsTemplate use message converters to
pass data to the handlers and to send data via messaging for gateway
implementations</para>
</section>
<section>
<title>Message Converters</title>
<para>The implementation of IMessageConverter used is
<classname>Spring.NmsQuickStart.Common.Converters.XmlMessageConverter</classname>.
This converter adds the ability to marshal and unmarshal objects to and
from XML strings. It also uses Spring's
<classname>SimpleMessageConverter</classname> to convert Hashtables,
strings, and byte arrays. In order to pass information about the
serialized type, type information is put in the message properties. The
type information can be either the class name or an integer value
identifying the type. In systems where the client and server are deployed
together and are tightly coupled, sharing the class name is a convenient
shortcut. The alternative is to register a type for a given integer value.
The XML configuration used to configure these objects is shown
below</para>
<programlisting> &lt;object name="XmlMessageConverter" type="Spring.NmsQuickStart.Common.Converters.XmlMessageConverter, Spring.NmsQuickStart.Common"&gt;
&lt;property name="TypeMapper" ref="TypeMapper"/&gt;
&lt;/object&gt;
&lt;object name="TypeMapper" type="Spring.NmsQuickStart.Common.Converters.TypeMapper, Spring.NmsQuickStart.Common"&gt;
&lt;!-- use simple configuation style --&gt;
&lt;property name="DefaultNamespace" value="Spring.NmsQuickStart.Common.Data"/&gt;
&lt;property name="DefaultAssemblyName" value="Spring.NmsQuickStart.Common"/&gt;
&lt;/object&gt;</programlisting>
<para>This configuration is common between the server and the
client.</para>
</section>
<section>
<title>Messaging Infrastructure</title>
<para>The implementations of the gateway interfaces inherit from Spring's
helper class <classname>NmsGatewaySupport</classname> in order to get easy
access to a NmsTemplate for sending. The implementation of the
IStockService interface is shown below</para>
<programlisting> public class NmsStockServiceGateway : NmsGatewaySupport, IStockService
{
private IDestination defaultReplyToQueue;
public IDestination DefaultReplyToQueue
{
set { defaultReplyToQueue = value; }
}
public void Send(TradeRequest tradeRequest)
{ // post process message
NmsTemplate.ConvertAndSendWithDelegate(tradeRequest, delegate(IMessage message)
{
message.NMSReplyTo = defaultReplyToQueue;
message.NMSCorrelationID = new Guid().ToString();
return message;
});
}
}</programlisting>
<para>The use of an anonymous delegate allows makes it very easy to apply
any post processing logic to the converted message. </para>
<para>The object definition for the
<classname>NmsStockServiceGateway</classname> is shown below along with
its dependent object definitions of NmsTemplate and the
ConnectionFactory.</para>
<para><programlisting> &lt;object name="StockServiceGateway" type="Spring.NmsQuickStart.Client.Gateways.NmsStockServiceGateway, Spring.NmsQuickStart.Client"&gt;
&lt;property name="NmsTemplate" ref="<emphasis role="bold">NmsTemplate</emphasis>"/&gt;
&lt;property name="DefaultReplyToQueue"&gt;
&lt;object type="Apache.NMS.ActiveMQ.Commands.ActiveMQQueue, Apache.NMS.ActiveMQ"&gt;
&lt;constructor-arg value="APP.STOCK.JOE"/&gt;
&lt;/object&gt;
&lt;/property&gt;
&lt;/object&gt;
&lt;object name="<emphasis role="bold">NmsTemplate</emphasis>" type="Spring.Messaging.Nms.Core.NmsTemplate, Spring.Messaging.Nms"&gt;
&lt;property name="ConnectionFactory" ref="<emphasis role="bold">ConnectionFactory</emphasis>"/&gt;
&lt;property name="DefaultDestinationName" value="APP.STOCK.REQUEST"/&gt;
&lt;property name="MessageConverter" ref="XmlMessageConverter"/&gt;
&lt;/object&gt;
&lt;object id="<emphasis role="bold">ConnectionFactory</emphasis>" type="Apache.NMS.ActiveMQ.ConnectionFactory, Apache.NMS.ActiveMQ"&gt;
&lt;constructor-arg index="0" value="tcp://localhost:61616"/&gt;
&lt;/object&gt;</programlisting>In this example the 'raw'
<classname>Apache.NMS.ActiveMQ.ConnectionFactory </classname>connection
factory was used. It would be more efficient resource wise to use Spring's
<classname>CachingConnectionFactory</classname> wrapper class so that
connections will not be open and closed for each message send as well as
allowing for the caching of other intermediate NMS API objects such as
sessions and message producers.</para>
<para>A similar configuration is used on the server to configure the class
<classname>Spring.NmsQuickStart.Server.Gateways.MarketDataServiceGateway
</classname>that implements the <classname>IMarketDataService</classname>
interface. </para>
<para>Since the client is also a consumer of messages, on the topic
APP.STOCK.MARKETDATA and the queue APP.STOCK.JOE (for Trader Joe!), two
message listener containers are defined as shown below. </para>
<programlisting> &lt;nms:listener-container connection-factory="ConnectionFactory"&gt;
&lt;nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.JOE" /&gt;
&lt;nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.MARKETDATA" pubsub-domain="true"/&gt;
&lt;/nms:listener-container&gt;</programlisting>
<para>Refer to the <link linkend="messaging">messages reference
docs</link> for all the available attributes to configure the container
and also the section on <link
linkend="xsd-config-body-schemas-nms">registering the NMS schema</link>
with Spring..</para>
<para>On the server we define a message listener container for the queue
APP.STOCK.REQUEST but set the concurrency property to 10 so that 10
threads will be consuming messages from the queue.</para>
<programlisting> &lt;nms:listener-container connection-factory="ConnectionFactory" concurrency="<emphasis
role="bold">10</emphasis>"&gt;
&lt;nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.REQUEST" /&gt;
&lt;/nms:listener-container&gt;</programlisting>
</section>
<section>
<title>Running the application</title>
<para>To run both the client and server make sure that you select
'Multiple Startup Projects' within VS.NET. The GUI has a button to make a
hardcoded trade request and show confirmation in a text box. A text area
is used to display the market data. There is a 'Get Portfolio' button that
is not implemented at the moment. A picture of the GUI after it has been
running for a while and trade has been sent and responded to is shown
below</para>
<mediaobject>
<imageobject>
<imagedata fileref="images/nms-quickstart-gui.png" />
</imageobject>
</mediaobject>
<para></para>
</section>
</chapter>

View File

@@ -24,9 +24,9 @@
<classname>IJob</classname> interface represents the task you would like
to execute. You either directly implement Quartz's
<classname>IJob</classname> interface or a convenience base class. The
Quartz <classname>ITrigger</classname> controls when a job is executed,
for example in the wee hours of the morning every weekday (This would be
done using Quartz's <classname>CronTrigger</classname> implementation.)
Quartz <classname>Trigger</classname> controls when a job is executed, for
example in the wee hours of the morning every weekday . This would be done
using Quartz's <classname>CronTrigger</classname> implementation.
Instances of your job are created every time the trigger fires. As such,
in order to pass information between different job instances you stash
data away in a hashtable that gets passed to the each Job instance upon
@@ -90,7 +90,7 @@
<programlisting> &lt;object name="exampleJob" type="Spring.Scheduling.Quartz.JobDetailObject, Spring.Scheduling.Quartz"&gt;
&lt;property name="JobType" value="Spring.Scheduling.Quartz.Example.ExampleJob, Spring.Scheduling.Quartz.Example" /&gt;
&lt;!-- We can inject values throgh JobDataMap --&gt;
&lt;!-- We can inject values through JobDataMap --&gt;
&lt;property name="JobDataAsMap"&gt;
&lt;dictionary&gt;
&lt;entry key="UserName" value="Alexandre" /&gt;
@@ -103,7 +103,7 @@
<classname>JobDataAsMap</classname>, is used to set the values of the
ExampleJob's properties. This will result in the ExampleJob being
instantiated with it's UserName property value set to 'Alexandre' the
first time the trigger fires. </para>
first time the trigger fires.</para>
<para>We then will schedule this job to be executed on 20 second
increments of every minute as shown below using Spring's
@@ -174,9 +174,12 @@
&lt;/object&gt;
</programlisting>
<para>Note that <classname>AdminSerivce</classname> object is configured
<para>Note that <classname>AdminService</classname> object is configured
using Spring as you would do normally, without consideration for Quartz.
The trigger associated with the jobDetail object is listed below</para>
The trigger associated with the jobDetail object is listed below. Also
note that when using MethodInvokingJobDetailFactoryObject you can't use
database persistence for Jobs. See the class documentation for additional
details.</para>
<programlisting> &lt;object id="simpleTrigger" type="Spring.Scheduling.Quartz.SimpleTriggerObject, Spring.Scheduling.Quartz"&gt;
&lt;!-- see the example of method invoking job above --&gt;

View File

@@ -140,7 +140,11 @@ public class ExampleJob extends QuartzJobObject {
</programlisting>
<note>
<para>By default, jobs will run in a concurrent fashion.</para>
<para>By default, jobs will run in a concurrent fashion. </para>
<para>Also note that when using MethodInvokingJobDetailFactoryObject
you can't use database persistence for Jobs. See the class
documentation for additional details.</para>
</note>
</section>

View File

@@ -7,7 +7,7 @@
<para>Spring's WCF support allows you to configure your WCF services via
dependency injection and add additional behavior to them using
Aspect-Oriented programming (AOP). </para>
Aspect-Oriented programming (AOP).</para>
<para>There are two approaches in the 1.2 M1 release for configuring your
services with DI which are discussed in the following sections. One
@@ -26,7 +26,7 @@
the WcfQuickStart application in the examples directory.</para>
</section>
<section id="Dependency Injection">
<section id="wcf-di">
<title>Configuring WCF services via Dependency Injection</title>
<para>In this approach the container will creates an implementation of
@@ -34,7 +34,7 @@
instance of your service type from the Spring container. This dynamic
proxy is then the final service type that is hosted.</para>
<section>
<section id="wcf-di-proxy">
<title>Dependency Injection using dynamic proxies</title>
<para>In this approach you develop your WCF services as you would
@@ -161,10 +161,13 @@
<para>There are not many disadvantages to this approach other than the
need to specify the service name as the name of the object definition in
the Spring container and to ensure that singleton=false is used in the
object definition.</para>
object definition. You can also use
<classname>Spring.ServiceModel.Activation.ServiceHostFactory</classname>
to host your service inside IIS but should still refer to the service by
the name of the object in the Spring container.</para>
</section>
<section>
<section id="wcf-di-extension-points">
<title>Dependency Injection using WCF extensibility points.</title>
<para>The second approach uses the extensibility points in WCF itself to
@@ -177,18 +180,18 @@
and
<classname>System.ServiceModel.Description.IServiceBehavior</classname>
are used to integrate Spring directly into the instancing of WCF
services. </para>
services.</para>
<para>Spring's implementation of
<classname>IInstanceProvider</classname> is
<classname>Spring.ServiceModel.Dispatcher.SpringInstanceProvider</classname>.
<classname>Spring.ServiceModel.Support.SpringInstanceProvider</classname>.
This implementation will look for an object by type in the Spring
container and retrieve an instance configured using DI. If there is more
than one object of the type registered with the container than an
exception will be thrown. The
<classname>SpringInstanceProvider</classname> is used by a custom
service behavior class,
<classname>Spring.ServiceModel.Dispatcher.SpringServiceBehavior</classname>
<classname>Spring.ServiceModel.Support.SpringServiceBehavior</classname>
where it is applied to all the service endpoints. This behavior is then
added to the custom service host
<classname>Spring.ServiceModel.Activation.SpringServiceHost</classname></para>
@@ -196,7 +199,7 @@
<para>The service type is used to locate the object in the container. In
your .svc file you specify the custom service host type and also the
type of the service. Here is an example taken from the WcfQuickStart
application that shows the use of this approach inside IIS. </para>
application that shows the use of this approach inside IIS.</para>
<programlisting>&lt;%@ ServiceHost Language="C#" Debug="true" Service="Spring.WcfQuickStart.CalculatorService"
Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %&gt;
@@ -282,5 +285,9 @@
<para>This will be shortened using a custom namespce in the 1.2 RC1
release</para>
</note>
<para>The value 'serverAppCalculatorEndpoint' refers to the name of an
enpoints in the &lt;client&gt; section of the standard WCF configuration
inside of App.config.</para>
</section>
</chapter>

View File

@@ -258,7 +258,7 @@
&lt;/configuration&gt;</programlisting>
</section>
<section id="xsd-config-body-schemas-remoting">
<section id="xsd-config-body-schemas-nms">
<title>The <literal>nms</literal> messaging schema</title>
<para>The <literal>nms</literal> tags are for use when you want to