NoXML Spring.NET

If you say to any .NET programmer you use Spring.NET (that they know it exists is already good to hear) the discussion will head immediately into XML world. Yes they can be a pain but with a bit of discipline you can keep them structured and well maintained, though if I could choose I’d drop them too. The reason I’m still sticking to this framework is because it offers so much. DI, AoP, data access, messaging,… most applications I’ve created need at least some components from the Spring.NET stack.

Erich Eichinger has posted on CodeConfig and assembly scanning for Spring.NET a while ago and it is scheduled to be included in Spring.NET in the future. Go check it out.

WCF ChannelManagement bug fix

Not really a release but I’ve just applied a bug fix that solves a null reference exception when returning null from the service you’re calling. Thanks to Jay from the Spring.NET forum for reporting and fixing the issue. I’ll clean up the code and add some more test cases the coming days. The updated code is available in the svn repository.

SVN Repository available

I’ve made availble a svn repository with the source code of the channel library for Spring.Net and my work on a Cuyahoga module for events. The last one is still pretty much a work in progress. I think I’ll be able to work on it some more later this year. There’s a lot on my todo list.

Readers have reported that the latest version of Fluent NHibernate breaks the approach which I illustrated on this blog, I’ll look into that later today. I’ll also be patching the channel library with a bug fix which someone on the Spring.Net forum was kind enough to provide. Had hoped to do that yesterday but the machine on which I was working did not have NUnit installed and Sourceforge was down. So stay tuned, this blog will get some more action in August.

Repository is located at:

Edit: Moved code to github @ https://github.com/BennyM/SpringWCFChannelManager

Changing your connection string at runtime with Spring.Net

Something that pops up every once in a while on the Spring.Net user forum is how to change your connection string at runtime. You need this behaviour for instance when you have a multi tenant application.

Out of the box Spring.Net comes with two DbProviders to change information about your connection string at runtime. One provider to change the credentials at runtime named UserCredentialsDbProvider, and one that can choose a connectionstring from a predefined list called MultiDelegatingDbProvider.

If you want to change the connection string at runtime, for instance based on the current logged in user, what works best is to either subclass DelegatingDbProvider or UserCredentialsDbProvider (which actually is a subclass of DelegatingDbProvider).

Attached you can find a quick and dirty sample which shows what you need to hook up.

RuntimeConnectionString.zip (8.29 kb)

WCF ChannelManagement drop 3

A new version is available, with two modes of channel pooling.

The ‘FixedPool’ mode is based on the SimplePool which you can find in the Spring.Pooling library. Meaning that at any given time there can be a maximum of x amount of channels. Where x equals the SimplePool’s size. So if the size of your pool is 5 and you request a 6th channel while the previous 5 are still busy doing their business you’ll get a blocking thread until one of the previous five is returned to the pool. This is good for when you want to limit the connectivity to your server, but don’t forget that it will block the calling thread when you request more channels than there are available.

The other pool mode is ‘VariablePool’. This is a pool that grows and shrinks depending on the load. So if you request 6 channels you’ll get 6 channels which will be available for future requests when returned to the pool. Channels which are no longer usable will be removed and new ones will be created when needed.

I spend most of the time trying to find a good away around my dependency on ChannelFactory. Since that class has a method ‘CreateChannel’ which takes no arguments and the factory can be configured using the endpoint name in your system.servicemodel section. The interface which the class implements doesn’t have this. The classes which populate a channelfactory from the app.config are marked internal and so you can’t use them.

The only solution I found that worked pretty ok was a wrapper interface which exposes the CreateChannel method, it helped me to test the code without a channelfactory instance.

I did a lot of renaming in the codebase but on the consuming end not much has changed.

A ‘SingleAction’ operating channel is still the easiest to configure.

<object id=“MyService” type=“WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager”>
	<property name=“ChannelType” expression=“T(Server.IService1, Common)/>
	<property name=“EndpointConfigurationName” value=“MyEndpoint”/>
</object>

Creating a fixed pool is one extra line.

<object id=“MyService” type=“WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager”>
	<property name=“ChannelType” expression=“T(Server.IService1, Common)/>
	<property name=“EndpointConfigurationName” value=“MyEndpoint”/>
	<property name=“ChannelManagementMode” value=“FixedPool”/>
</object>

A variable pool means just another value as ChannelManagementMode.

<object id=“MyService” type=“WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager”>
	<property name=“ChannelType” expression=“T(Server.IService1, Common)/>
	<property name=“EndpointConfigurationName” value=“MyEndpoint”/>
	<property name=“ChannelManagementMode” value=“VariablePool”/>
</object>

If you want to use your own channel manager, you can use the ProductTemplate to hook everything up. The sample below illustrates this, here the variable pool is configured via the template instead of using the ChannelManagementMode property of the FactoryObject.

<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager">
	<property name="ChannelType" expression="T(Server.IService1, Common)"/>
	<property name="EndpointConfigurationName" value="MyEndpoint"/>
	<property name="ProductTemplate">
	<object>
		<property name="ChannelManager">
			<object type="WCFChannelManager.ChannelPoolManager&lt;Server.IService1>, Perponcher.WCFChannelManager">
				<constructor-arg value="MyEndpoint"/>
				<constructor-arg>
					<object type="WCFChannelManager.AutoSizePoolFactory, Perponcher.WCFChannelManager"/>
				</constructor-arg>
			</object>
		</property>
	</object>
	</property>
</object>

The same approach can be used to configure the channelfactory for i.e. passing credentials.

<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager">
	<property name="ChannelType" expression="T(Server.IService1, Common)"/>
	<property name="EndpointConfigurationName" value="MyEndpoint"/>
	<property name="ChannelManagementMode" value="VariablePool"/>
	<property name="ProductTemplate">
		<object>
			<property name="ChannelManager.ChannelFactory.Credentials.UserName.UserName" value="username"/>
			<property name="ChannelManager.ChannelFactory.Credentials.UserName.Password" value="password"/>
		</object>
	</property>
</object>

That’s it for now. Future additions will include:

  • setting the pool size of a fixed sized pool via the FactoryObject, for now the default of 5 is used
  • extend or add a new pool based on the SimplePool. At the moment closed or faulted channels are not removed from that implementation, meaning that when your 5 channels are closed the pool will raise an exception.

WCFChannelManager_drop3.zip (1.16 mb)

Series:

WCF ChannelManagement drop 2

Updated version is now available, no channel pooling yet but I changed the way default values and the ProductTemplate were being handled. I’ve already used the library successfully at work in a very heavy WCF application. I found some issues with it, like when you wanted to configure the ChannelFactory in your configuration file, but these are now fixed.

Next up pooling!

WCFChannelManager_drop2.zip (1.14 mb)

Series:

First drop of ChannelManagement available.

First drop available of the ChannelManagement library. Currently only support single action channels, meaning that after executing the operation the channel is closed. I hope to add pooling the coming week.

The zip contains the source code and an example project. Not much changes in the ‘end user’ code:

static void Main(string[] args)
{
	var myService = ContextRegistry.GetContext().GetObject("MyService") as IService1;
	string value = myService.GetData(5);
	var returnValue = myService.GetDataUsingDataContract(new CompositeType() 
														 { 
														 BoolValue = false, 
														 StringValue = "Perponcher" });
	Console.ReadLine();
}
<spring>
	<context>
		<resource uri="config://spring/objects" />
	</context>
	<objects xmlns="http://www.springframework.net">
		<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject, Perponcher.WCFChannelManager">
			<property name="ChannelType" expression="T(Server.IService1, Common)"/>
			<property name="EndpointConfigurationName" value="MyEndpoint"/>
		</object>
	</objects>
</spring>
<system.serviceModel>
	<client>
		<endpoint name="MyEndpoint" address="http://localhost:8731/Design_Time_Addresses/Server/Service1/"
			contract="Server.IService1" binding ="wsHttpBinding"/>
	</client>
</system.serviceModel>

Out and ref parameters are not yet supported.

WCFChannelManager.zip (1.17 mb)

Series:

Configuring the ChannelManager

I’m trying to keep configuration to a minimum. Let’s look at an example:

<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject">
	<property name="ChannelType" expression="T(WCFChannelManagerTests.IService)"/>
	<property name="EndpointConfigurationName" value="MyEndpointName"/>
</object>

This is probably what you’ll need the most. You define the ChannelType, that is the interface exposed by the service you want to consume, and the EndpointConfigurationName, which is the name of the endpoint in the system.servicemodel section of your app/web.config. And that’s it. The behaviour of the channel in this case is that a new channel will be created for every operation you want to execute.

<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject">
	<property name="ChannelType" expression="T(WCFChannelManagerTests.IService)"/>
	<property name="EndpointConfigurationName" value="MyEndpointName"/>
	<property name="ChannelManagementMode" value="Recycle"/>
</object>

If you want channels to be reused, you can specify this by changing the value of the ‘ChannelManagementMode’. There are two predefined values you can use here, Recycle and ThrowAway. ThrowAway being the default. Not sure about these names though :-).

<object id="OneTimeUseChannel" type="WCFChannelManager.SingleActionChannelManager&lt;WCFChannelManagerTests.IService>"/>
<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject">
	<property name="ChannelType" expression="T(WCFChannelManagerTests.IService)"/>
	<property name="EndpointConfigurationName" value="MyEndpointName"/>
	<property name="ProductTemplate">
	<object>
		<property name="ChannelManager" ref="OneTimeUseChannel"/> 
	</object>
	</property>
</object>

If one of the default ways to manage the lifecycle of a channel is not what you want or need you can create your own and specify it in the ProductTemplate property of the ChannelManagerFactoryObject. The example above shows how you can do this, in this case it would result in the same default behaviour you get in the first xml configuration I showed in the beginning of my post.

If you even want to customize the way a channel is retrieved, an action is executed on it and then handed back to the channel lifecycle manager, you can subclass ChannelActionWrapper and specify that type in the ChannelActionWrapperType property of the ChannelManagerFactoryObject. This is illustrated below:

<object id="MyService" type="WCFChannelManager.ChannelManagerFactoryObject">
	<property name="ChannelActionWrapperType" expression="T(WCFChannelManagerTests.MockChannelManager)"/>
	<property name="EndpointConfigurationName" value="MyEndpointName"/>
</object>
public class MockChannelManager
	: ChannelActionWrapper<IService>
{
	public MockChannelManager()
	: base(null)
	{
 
	}
	public override IService  GetChannelToWorkWith()
	{
		return new Service();
	}
 
 
	public object ExecuteOperation(MethodInfo info, object[] parameters)
	{
		return this.ExecuteInChannel(info, parameters);
	}
}

The ChannelType will now be retrieved from your subclass so you don’t need to specify the ChannelType.

And that’s all I have for you now.

Series:

Migrating from ‘asmx’ webservices to WCF with Spring.Net

Building webservices with Spring.Net is a piece of cake. The framework supported a single programming model long before WCF was available, exposing your service was just a different entry in your configuration. If you’re interested how you need to do this, please read my previous blog entries.

WCF introduced this same concepts to the main .Net Framework but also provides a lot of other functionality out of the box. Security, logging, … just change some xml tag and you’re done.

I make it sound a bit too easy here 🙂 figuring out what is wrong in your service section of the app/web.config is frustrating even with all the tools that are available.

So what do we need to change in our application to switch from ‘old’ webservices to the WCF counterpart?

Well if you’ve been following some best practices then your service is already behind an interface, and that means the only thing you have to change is the way Spring injects this service in your application.

public class OrderPresenter
	: IOrderPresenter
{
	public IOrderService OrderService { get; set; }
	public IOrderView View { get; set; }
}

With the code example above the presenter expects an instance which implements the IOrderService interface, it doesn’t care if it’s WCF, ‘asmx’ webservice or just a local object.

To add a WCF client object you do not need to change anything in your existing codebase, only the way Spring can find the Service you’re connecting to as illustrated below.

<object id="OrderService" type="ServiceContract.IOrderService, ServiceContract"
		factory-object="OrderServiceChannelFactory"
		factory-method="CreateChannel" />
 
<object id="OrderServiceChannelFactory"
	type="System.ServiceModel.ChannelFactory&lt;ServiceContract.IOrderService>, System.ServiceModel">
	<constructor-arg name="endpointConfigurationName" value="OrderServiceEndpoint" />
</object>

The OrderService above will be used by my presenter, and is created via the OrderServiceChannelFactory. Anyone who has some experience with WCF sees that this is just the same as you would do in code when using channels.

So we’re done!

No, not really. There is one, rather big, caveat.

In the ‘old’ days my client service reference would still function if there had been an exception. For example if the network cable was unplugged and I called a method on the server I’d get an exception. If I’d plug the cable back in and call the method again, my client service reference would still function and call the server successfully.

This is not the case with WCF channels, if there is an exception, either communication wise, like the unplugged network cable, or the server throws an exception my client channel will transition in a ‘faulted’ state. Any calls I make on this instance will fail, I need a new instance from the channelfactory to get my application going again.

I could change my presenter to check the service reference, but that would mean I need to couple my presenter to WCF and need to add new behaviour. This is not something you’d want to do. I can’t get around this problem by ‘normal’ AOP techniques. I can’t let the channel check it’s own status and have it magically change it’s own memory reference to a new instance.

Wouldn’t it be great if that boilerplate code (checking the state, creating new channels,….) was automagically done when calling a method on my client service reference?

Well using the Spring framework I’ve been able to accomplish this. You won’t need to change or add any code as long as your service is exposed with an interface. At runtime a new subclass of my ChannelManager class is created which implements the service interface. All calls are forwarded to the ExecuteInChannel method, which creates a channel, calls the method you originally wanted to execute, returns the result and closes the channel. You can also subclass the ChannelManager class to change the way you want to manage your channels.

Over the next few days I hope to add some more functionality, like channel pooling and test it a bit better. Source code will be available.

Series: