Added WCF documentation
misc updates.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
<!ENTITY ajax SYSTEM "ajax.xml">
|
||||
<!ENTITY services SYSTEM "services.xml">
|
||||
<!ENTITY webservices SYSTEM "webservices.xml">
|
||||
<!ENTITY wcf SYSTEM "wcf.xml">
|
||||
<!ENTITY threading SYSTEM "threading.xml">
|
||||
<!ENTITY pool SYSTEM "pool.xml">
|
||||
<!ENTITY preface SYSTEM "preface.xml">
|
||||
@@ -285,12 +286,16 @@
|
||||
<listitem>
|
||||
<xref linkend="webservices" />
|
||||
</listitem>
|
||||
<listitem>
|
||||
<xref linkend="wcf" />
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</partintro>
|
||||
&psa-intro;
|
||||
&remoting;
|
||||
&services;
|
||||
&webservices;
|
||||
&wcf;
|
||||
</part>
|
||||
|
||||
<part id="spring-integration">
|
||||
|
||||
@@ -44,13 +44,14 @@
|
||||
|
||||
<listitem>
|
||||
<para>SonicMQ in namespace <literal>Spring.Messaging.Sonic</literal>,
|
||||
'Jms' is sometimes used as the class prefix.</para>
|
||||
'Jms' is sometimes used as the class prefix. (available 1.2
|
||||
RC1)</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Websphere MQ in namespace
|
||||
<literal>Spring.Messaging.Xms</literal>, 'Xms' is sometimes used as
|
||||
the class prefix</para>
|
||||
the class prefix (available 1.2 RC1)</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
@@ -1270,17 +1271,19 @@ namespace MyApp
|
||||
<row>
|
||||
<entry>recovery-interval</entry>
|
||||
|
||||
<entry><para>The time interval between connection recovery attempts. The default is 5 seconds.
|
||||
Specify as a TimeSpan value using Spring's TimeSpanConverter (e.g. 10s, 10m, 3h, etc)
|
||||
</para></entry>
|
||||
<entry><para>The time interval between connection recovery
|
||||
attempts. The default is 5 seconds. Specify as a TimeSpan value
|
||||
using Spring's TimeSpanConverter (e.g. 10s, 10m, 3h, etc)
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>max-recovery-time</entry>
|
||||
|
||||
<entry><para>The maximum time try reconnection attempts. The default is 10 minutes. Specify as a
|
||||
TimeSpan value using Spring's TimeSpanConverter (e.g. 10s, 10m, 3h, etc)
|
||||
</para></entry>
|
||||
<entry><para>The maximum time try reconnection attempts. The
|
||||
default is 10 minutes. Specify as a TimeSpan value using
|
||||
Spring's TimeSpanConverter (e.g. 10s, 10m, 3h, etc)
|
||||
</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1300,7 +1303,7 @@ namespace MyApp
|
||||
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>
|
||||
operation.</para>
|
||||
|
||||
<para>Spring provides a convenience class, SingleConnectionFactory, in
|
||||
which the same Connection is returned on calls to CreateConnection() and
|
||||
|
||||
286
doc/reference/src/wcf.xml
Normal file
286
doc/reference/src/wcf.xml
Normal file
@@ -0,0 +1,286 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<chapter id="wcf">
|
||||
<title>Windows Communication Foundation (WCF)</title>
|
||||
|
||||
<section id="wcf-introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<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>
|
||||
|
||||
<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
|
||||
approach creates an implementation of your service interface (a dynamic
|
||||
proxy) that retrieves a configured instance of your service type from the
|
||||
Spring container. This dynamic proxy is then the final service type that
|
||||
is hosted. The second approach uses the extension points in WCF itself to
|
||||
delegate to the Spring container to create and configure your service
|
||||
type. Both approaches are discussed below.</para>
|
||||
|
||||
<para>As it is desirable to have just one approach, we would greatly
|
||||
appreciate your input regarding these two approaches as well as any other
|
||||
suggestions regarding WCF support.</para>
|
||||
|
||||
<para>For those who would like to get their feet wet right way, check out
|
||||
the WcfQuickStart application in the examples directory.</para>
|
||||
</section>
|
||||
|
||||
<section id="Dependency Injection">
|
||||
<title>Configuring WCF services via Dependency Injection</title>
|
||||
|
||||
<para>In this approach the container will creates an implementation of
|
||||
your service interface (a dynamic proxy) that retrieves a configured
|
||||
instance of your service type from the Spring container. This dynamic
|
||||
proxy is then the final service type that is hosted.</para>
|
||||
|
||||
<section>
|
||||
<title>Dependency Injection using dynamic proxies</title>
|
||||
|
||||
<para>In this approach you develop your WCF services as you would
|
||||
normally do. For example here is a sample service type taken from the
|
||||
quickstart example.</para>
|
||||
|
||||
<programlisting> [ServiceContract(Namespace = "http://Spring.WcfQuickStart")]
|
||||
public interface ICalculator
|
||||
{
|
||||
[OperationContract]
|
||||
double Add(double n1, double n2);
|
||||
[OperationContract]
|
||||
double Subtract(double n1, double n2);
|
||||
[OperationContract]
|
||||
double Multiply(double n1, double n2);
|
||||
[OperationContract]
|
||||
double Divide(double n1, double n2);
|
||||
[OperationContract]
|
||||
string GetName();
|
||||
}</programlisting>
|
||||
|
||||
<para>The implementation for the methods is fairly obvious but an
|
||||
additional property, <literal>SleepInSeconds</literal>, is present. This
|
||||
is the property we will configure via dependency injection. Here is a
|
||||
partial listing of the implementation</para>
|
||||
|
||||
<programlisting> public class CalculatorService : ICalculator
|
||||
{
|
||||
private int sleepInSeconds;
|
||||
|
||||
public int SleepInSeconds
|
||||
{
|
||||
get { return sleepInSeconds; }
|
||||
set { sleepInSeconds = value; }
|
||||
}
|
||||
|
||||
public double Add(double n1, double n2)
|
||||
{
|
||||
Thread.Sleep(sleepInSeconds*1000);
|
||||
return n1 + n2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// additional implementation not shown for brevity
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>To configure this object with Spring, provide the XML
|
||||
configuration metadata as shown below as you would with any Spring
|
||||
managed object.</para>
|
||||
|
||||
<programlisting> <object id="calculator" <emphasis role="bold">singleton="false"</emphasis> type="Spring.WcfQuickStart.CalculatorService, Spring.WcfQuickStart.ServerApp">
|
||||
<property name="SleepInSeconds" value="1"/>
|
||||
</object>
|
||||
</programlisting>
|
||||
|
||||
<note>
|
||||
<para>The object must be declared as a 'prototype' object, i.e. not a
|
||||
singleton, in order to interact correctly with WCF instancing.</para>
|
||||
</note>
|
||||
|
||||
<para>To host this service type in a standalone application define an
|
||||
instance of a
|
||||
<classname>Spring.ServiceModel.Activation.ServiceHostFactoryObject</classname>
|
||||
and set is property <classname>TargetName</classname> to the id value of
|
||||
the previously defined service type.
|
||||
<classname>ServiceHostFactoryObject</classname> is a Spring
|
||||
<classname>IFactoryObject</classname> implementation. (See <link
|
||||
linkend="objects-factory-extension-factoryobject">here</link> for more
|
||||
information on <classname>IFactoryObjects</classname> and their
|
||||
interaction with the container.) The
|
||||
<classname>ServiceHostFactoryObject</classname> will create an instance
|
||||
of
|
||||
<classname>Spring.ServiceModel.Activation.SpringServiceHost</classname>
|
||||
that will be the ServiceHost instance associated with your service type.
|
||||
This configuration for this step is shown below.</para>
|
||||
|
||||
<programlisting> <object id="calculatorServiceHost" type="Spring.ServiceModel.Activation.ServiceHostFactoryObject, Spring.Services">
|
||||
<property name="TargetName" value="calculator" />
|
||||
</object></programlisting>
|
||||
|
||||
<para>Additional service configuration can be done declaratively in the
|
||||
standard App.config file as shown below</para>
|
||||
|
||||
<programlisting><system.serviceModel>
|
||||
<services>
|
||||
<service name="<emphasis role="bold">calculator</emphasis>" behaviorConfiguration="DefaultBehavior">
|
||||
<host> ... </host>
|
||||
<endpoint> ... </endpoint>
|
||||
</service>
|
||||
...
|
||||
</services>
|
||||
|
||||
</system.serviceModel></programlisting>
|
||||
|
||||
<note>
|
||||
<para>It is important that the name of the service in the WCF
|
||||
declarative configuration section match the name of the Spring object
|
||||
definition</para>
|
||||
</note>
|
||||
|
||||
<para><classname>Spring.ServiceModel.Activation.SpringServiceHost
|
||||
</classname>is where the dynamic proxy for your service type is
|
||||
generated. This dynamic proxy will implement a single 'WCF' interface,
|
||||
the same on that your service type implements. The implementation of the
|
||||
service interface methods on the proxy will delegate to a wrapped
|
||||
'target' object which is the object instance retrieved by name from the
|
||||
Spring container using the Spring API,
|
||||
<classname>ApplicationContext.GetObject(name)</classname>. Since the
|
||||
object retrieved in this manner is fully configured, your WCF service is
|
||||
as well.</para>
|
||||
|
||||
<para>Outside of a standalone application you can also use the class
|
||||
<classname>Spring.ServiceModel.Activation.ServiceHostFactory</classname>
|
||||
(which inherits from
|
||||
<classname>System.ServiceModel.Activation.ServiceHostFactory</classname>)
|
||||
to host your services so that they can be configured via dependency
|
||||
injection. To use the dynamic proxy approached described here you should
|
||||
still refer to the name of the service as the name of the object
|
||||
definition used to configure the service type in the Spring
|
||||
container.</para>
|
||||
|
||||
<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>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Dependency Injection using WCF extensibility points.</title>
|
||||
|
||||
<para>The second approach uses the extensibility points in WCF itself to
|
||||
delegate to Spring to create and configure your WCF service. This
|
||||
approach was first taken (afaik) by Oran Dennison on his <ulink
|
||||
url="http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html">blog</ulink>
|
||||
and several other folks on the web since then. In this approach Spring
|
||||
specific implementations of the WCF interfaces
|
||||
<classname>System.ServiceModel.Dispatcher.IInstanceProvider</classname>
|
||||
and
|
||||
<classname>System.ServiceModel.Description.IServiceBehavior</classname>
|
||||
are used to integrate Spring directly into the instancing of WCF
|
||||
services. </para>
|
||||
|
||||
<para>Spring's implementation of
|
||||
<classname>IInstanceProvider</classname> is
|
||||
<classname>Spring.ServiceModel.Dispatcher.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>
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<programlisting><%@ ServiceHost Language="C#" Debug="true" Service="Spring.WcfQuickStart.CalculatorService"
|
||||
Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %>
|
||||
</programlisting>
|
||||
|
||||
<para>The Spring configuration for the object is shown below.</para>
|
||||
|
||||
<programlisting> <object id="calculator" type="Spring.WcfQuickStart.CalculatorService, App_Code" <emphasis
|
||||
role="bold">singleton="false"</emphasis>>
|
||||
<property name="SleepInSeconds" value="1"/>
|
||||
</object></programlisting>
|
||||
|
||||
<note>
|
||||
<para>The object must be declared as a 'prototype' object, i.e. not a
|
||||
singleton, in order to interact correctly with WCF instancing.</para>
|
||||
</note>
|
||||
|
||||
<para>While integrating 'natively' with WCF does seem to be the most
|
||||
natural approach there is one 'gotya' that needs to be investigated
|
||||
further to see if there is an acceptable workaround in order for this
|
||||
approach to be viable. The issue is that if the service is configured to
|
||||
be a singleton, for example using
|
||||
<literal>[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]</literal>
|
||||
then the invocation of the <classname>IInstanceProvider</classname> is
|
||||
short-circuited. See the notes on the MSDN class documentation <ulink
|
||||
url="http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iinstanceprovider.aspx">here</ulink>.
|
||||
One workaround, which is not very appealing, is to use the PerCall
|
||||
instancing mode but set the singleton attribute in the Spring
|
||||
configuration to true, this way the same instance is always
|
||||
returned.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="Aspect Oriented Programming">
|
||||
<title>Apply AOP advice to WCF services</title>
|
||||
|
||||
<para>In either approach to performing dependency injection you can apply
|
||||
additional AOP advice to your WCF services in the same way as you have
|
||||
always done in Spring. The following configuration shows how to apply some
|
||||
simple performance monitoring advice to all services in the
|
||||
<classname>Spring.WcfQuickStart</classname> namespace and is taken from
|
||||
the QuickStart example.</para>
|
||||
|
||||
<programlisting> <object id="serviceOperation" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
|
||||
<property name="pattern" value="Spring.WcfQuickStart.*"/>
|
||||
</object>
|
||||
|
||||
<object id="perfAdvice" type="Spring.WcfQuickStart.SimplePerformanceInterceptor, Spring.WcfQuickStart.ServerApp">
|
||||
<property name="Prefix" value="Service Layer Performance"/>
|
||||
</object>
|
||||
|
||||
<aop:config>
|
||||
<aop:advisor pointcut-ref="serviceOperation" advice-ref="perfAdvice"/>
|
||||
</aop:config></programlisting>
|
||||
|
||||
<para>The aop:config section implicitly uses Spring's autoproxying
|
||||
features to add additional behavior to any objects defined in the
|
||||
container that match the pointcut criteria.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Creating client side proxies declaratively</title>
|
||||
|
||||
<para>To create a client side proxy based on the use of
|
||||
ChannelFactory<T>, you can use this rather ugly 'boiler plate' XML
|
||||
snippit that takes uses Spring's support for calling factory methods on
|
||||
object instances.</para>
|
||||
|
||||
<programlisting> <!-- returns ChannelFactory<ICalculator>("calculatorEndpoint").CreateChannel() -->
|
||||
|
||||
<object id="serverAppCalculator" type="Spring.WcfQuickStart.ICalculator, Spring.WcfQuickStart.ClientApp"
|
||||
factory-object="serverAppCalculatorChannelFactory"
|
||||
factory-method="CreateChannel" />
|
||||
|
||||
<object id="serverAppCalculatorChannelFactory"
|
||||
type="System.ServiceModel.ChannelFactory&lt;Spring.WcfQuickStart.ICalculator>, System.ServiceModel">
|
||||
|
||||
<constructor-arg name="endpointConfigurationName" value="serverAppCalculatorEndpoint" />
|
||||
|
||||
</object></programlisting>
|
||||
|
||||
<note>
|
||||
<para>This will be shortened using a custom namespce in the 1.2 RC1
|
||||
release</para>
|
||||
</note>
|
||||
</section>
|
||||
</chapter>
|
||||
Reference in New Issue
Block a user