From 9f4849f7804e12b10abd839605e7ee121b222284 Mon Sep 17 00:00:00 2001 From: markpollack Date: Fri, 15 Aug 2008 02:10:25 +0000 Subject: [PATCH] misc doc improvements --- doc/reference/src/aop.xml | 78 +++++++++++++++++++++++----- doc/reference/src/index.xml | 5 ++ doc/reference/src/msmq.xml | 48 +++++++++++++---- doc/reference/src/nms-quickstart.xml | 25 ++++++--- 4 files changed, 125 insertions(+), 31 deletions(-) diff --git a/doc/reference/src/aop.xml b/doc/reference/src/aop.xml index 8d49316a..4880569f 100644 --- a/doc/reference/src/aop.xml +++ b/doc/reference/src/aop.xml @@ -1571,21 +1571,33 @@ MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject"); // Will ret Proxying mechanisms Spring creates AOP proxies built at runtime through the use of the - TypeBuilder API. Two types of proxies can be created, composition based or + TypeBuilder API. + + Two types of proxies can be created, composition based or inheritance based. If the target object implements at least one interface then a composition based proxy will be created, otherwise an inheritance - based proxy will be created. The composition based proxy is implemented by - creating a type that implements all the interfaces specified on the target - object. The actual class name of this dynamic type is 'GUID' like. A - private field holds the target object and the dynamic type implementation - will first execute any advice before or after making the target object - method call on the target object. The inheritance based mechanism creates - a dynamic type where that inherits from the target type. This lets you - downcast to the target type if needed. Please note that in both cases a - target method implementation that calls other methods on the target object - will not be advised. To force inheritance based proxies you should either - set the ProxyTargetType property of a ProxyFactory or the element - proxy-target-type when using an AOP schema based configuration. + based proxy will be created. + + The composition based proxy is implemented by creating a type that + implements all the interfaces specified on the target object. The actual + class name of this dynamic type is 'GUID' like. A private field holds the + target object and the dynamic type implementation will first execute any + advice before or after making the target object method call on the target + object. + + The inheritance based mechanism creates a dynamic type where that + inherits from the target type. This lets you downcast to the target type + if needed. Please note that in both cases a target method implementation + that calls other methods on the target object will not be advised. To + force inheritance based proxies you should either set the + ProxyTargetType to true property of a ProxyFactory + or set the XML namespace element proxy-target-type = + true when using an AOP schema based configuration. + + + An important alternative approach to inheritance based proxies is + disucssed in the next section. + In .NET 2.0 you can define the assembly level attribute, InternalsVisibleTo, to allow access of internal interfaces/classes to @@ -1594,6 +1606,46 @@ MyInterface myProxyObject2 = (MyInterface)ctx.GetObject("MyObject"); // Will ret InternalsVisibleTo("Spring.Proxy")] and [assembly: InternalsVisibleTo("Spring.DynamicReflection")] to your to AssemblyInfo file. + + + InheritanceBasedAopConfigurer + + There is an important limitation in the inheritance based proxy as + described above, all methods that manipulate the state of the object + should be declared as virtual. Otherwise some method invocations get + directed to the private 'target' field member and others to the base + class. Winform object are an example of case where this approach does + not apply. To address this limitation, a new post-processing mechanism + was introduced in version 1.2 that creates a proxy type without the + private 'target' field. Interception advice is added directly in the + method body before invoking the base class method. + + To use this new inheritance based proxy described in the note + above, declare an instance of the InheritanceBasedAopConfigurer, and + IObjectFactoryPostProcessor, in yoru configuraiton file. Here is an + example. + + <object type="Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop"> + <property name="ObjectNames"> + <list> + <value>Form*</value> + <value>Control*</value> + </list> + </property> + <property name="InterceptorNames"> + <list> + <value>debugInterceptor</value> + </list> + </property> +</object> + +<object id="debugInterceptor" type="AopPlay.DebugInterceptor, AopPlay"/> + + This configuraiton style is similar to the autoproxy by name + approach described here and is + particuarly appropriate when you want to apply advice to WinForm + classes. + diff --git a/doc/reference/src/index.xml b/doc/reference/src/index.xml index 6f850218..aaceb3de 100644 --- a/doc/reference/src/index.xml +++ b/doc/reference/src/index.xml @@ -45,6 +45,7 @@ + @@ -376,6 +377,9 @@ + + + @@ -390,6 +394,7 @@ &tx-quickstart; &quartz-quickstart; &nms-quickstart; + &msmq-quickstart; &wcf-quickstart; diff --git a/doc/reference/src/msmq.xml b/doc/reference/src/msmq.xml index c48df4e4..842a1696 100644 --- a/doc/reference/src/msmq.xml +++ b/doc/reference/src/msmq.xml @@ -88,6 +88,9 @@ classes to write enterprise MSMQ applications than rolling your own infrastructure. Feedback and new feature requests are always welcome. + + The Spring.MsmqQuickstart application located in the examples + directory of the distribution shows this functionality in action.
@@ -427,6 +430,10 @@ void Send(MessageQueue messageQueue, Message message); MessageQueueTemplate. The default value is MessageQueue.InfiniteTimeout (which is actually ~3 months). + + The XML configuration snippit for defining a MessageQueueTemplate + is shown in the previous section and also is located in the MSMQ + quickstart application configuraiton file Messaging.xml
@@ -649,7 +656,6 @@ void Send(MessageQueue messageQueue, Message message); <!-- Delegate to plain .NET object for message handling --> <object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"> <property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/> - <property name="MessageConverterObjectName" value="messageConverter"/> <property name="HandlerObject" ref="simpleHandler"/> </object> @@ -779,7 +785,6 @@ void Send(MessageQueue messageQueue, Message message); <!-- Delegate to plain .NET object for message handling --> <object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"> <property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/> - <property name="MessageConverterObjectName" value="messageConverter"/> <property name="HandlerObject" ref="simpleHandler"/> </object> @@ -837,8 +842,11 @@ void Send(MessageQueue messageQueue, Message message); Commit and Rollback. A specific implementation is provided that will move the poison message to another queue after a maximum number of redelivery attempts. See - SendToQueueExceptionHandler described - below. + SendToQueueExceptionHandler described below. + You can set a specific implementation to by setting + TransactionalMessageListenerContainer's + property + MessageTransactionExceptionHandler The IMessageTransactionExceptionHandler implementation SendToQueueExceptionHandler @@ -946,9 +954,29 @@ void Send(MessageQueue messageQueue, Message message); The default implementation used in - MessageQueueTemplate and the message listener is - an instance of XmlMessageConverter configured with a TargetType to be - System.String. + MessageQueueTemplate and the message listener + containers is an instance of XmlMessageConverter configured with a + TargetType to be System.String. You specify the types that the + XmlMessageConverter can convert though either the array property + TargetTypes or + TargetTypeNames. Here is an example taken from + the QuickStart application + + <object id="xmlMessageConverter" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging"> + <property name="TargetTypes"> + <list> + <value>Spring.MsmqQuickStart.Common.Data.TradeRequest, Spring.MsmqQuickStart.Common</value> + <value>Spring.MsmqQuickStart.Common.Data.TradeResponse, Spring.MsmqQuickStart.Common</value> + <value>System.String, mscorlib</value> + </list> + </property> + </object> + + You can specify other IMessageConverter + implementations using the + MessageConverterObjectName property on the + MessageQueueTemplate and + MessageListenerAdapter. Other implementations provided are @@ -988,7 +1016,7 @@ void Send(MessageQueue messageQueue, Message message);
- interface based message processing + Interface based message processing
@@ -1077,12 +1105,12 @@ void Send(MessageQueue messageQueue, Message message); } The following configuration shows how to hook up the adapter to - process incoming MSMQ messages. + process incoming MSMQ messages using the default message converter. + <!-- Delegate to plain .NET object for message handling --> <object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging"> <property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/> - <property name="MessageConverterObjectName" value="messageConverter"/> <property name="HandlerObject" ref="myHandler"/> </object>
diff --git a/doc/reference/src/nms-quickstart.xml b/doc/reference/src/nms-quickstart.xml index b31ad002..17fcfe0f 100644 --- a/doc/reference/src/nms-quickstart.xml +++ b/doc/reference/src/nms-quickstart.xml @@ -25,6 +25,9 @@ + + This example was developed with ActiveMQ 5.1 and the ActiveMQ NMS + library with subversion repository number 685750.
@@ -55,7 +58,7 @@ Queues are shown in red and topics in green.
-
+
Gateways Gateways represent the service operation to send a message. The @@ -89,7 +92,7 @@ purposes.
-
+
Message Data The TradeRequest object shown above contains @@ -209,7 +212,7 @@ structure.
-
+
Message Handlers When the TradeRequest message is received by @@ -322,7 +325,7 @@ The implementations of the gateway interfaces inherit from Spring's helper class NmsGatewaySupport in order to get easy access to a NmsTemplate for sending. The implementation of the - IStockService interface is shown below + IStockService interface is shown below public class NmsStockServiceGateway : NmsGatewaySupport, IStockService { @@ -344,8 +347,14 @@ } } - The use of an anonymous delegate allows makes it very easy to apply - any post processing logic to the converted message. + The Send method is using NmsTemplate's + ConvertAndSendWithDelegate(object obj, + MessagePostProcessorDelegate messagePostProcessorDelegate) + method. The anonymous delegate allows you to modify the message + properties, such as NMSReplyTo and NMSCorrelationID after the message has + been converted from an object but before it has been sent. The use of an + anonymous delegate allows makes it very easy to apply any post processing + logic to the converted message. The object definition for the NmsStockServiceGateway is shown below along with @@ -380,11 +389,11 @@ A similar configuration is used on the server to configure the class Spring.NmsQuickStart.Server.Gateways.MarketDataServiceGateway that implements the IMarketDataService - interface. + interface. 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. + message listener containers are defined as shown below. <nms:listener-container connection-factory="ConnectionFactory"> <nms:listener ref="MessageListenerAdapter" destination="APP.STOCK.JOE" />