Working Towards a Vision
What Was Past
One of the changes that I recently added to CruiseControl.NET (for the 1.5 release) is a common communications library. This project is a cut-down version of Remote – I stripped out everything that had nothing to do with communications (e.g. exceptions, NetReflector, lots of interfaces, etc.)
The aim for this library is simple – it contains everything that is needed for a client to communicate with a server. This includes all communications protocols – currently HTTP and .NET Remoting – plus an implementation of every possible method. Additionally it contains a number of classes to simplify the process of communicating with a server.
Considering a lot of this already existed within Remote, you might ask why I have added another library to do this? The answer is simple – Remote contained the basic components for communications, it didn’t actual provide anything to facilitate the process. Instead, each client had to write its own mechanisms for communications – which is why CCTray has one way for communications, the dashboard has another and the server uses yet another way (when it needs to communicate with other servers.) Making a change in one wouldn’t affect the other – so if there was a common change it needed to be made to all three!
Finally, these mechanisms were deeply entrenched within each client. I couldn’t just take the communications part of CCTray and use it – I had to include everything else (and CCTrayLib has a lot of stuff in it!) I certainly tried and did produce a simple command-line client that used CCTrayLib. The problem was it needed all the other dependencies for CCTray, and it wasn’t the easiest thing to use.
What Is Now
As I wrote above, I have added a new communications only project to CruiseControl.NET. Remote still contains everything, plus the new communications work, while the communications library only contains the communications classes (hence it is a subset of remote.)
The heart of this library is a class called CruiseServerClientBase. This class is actually an abstract class, but it exposes all of the communications methods. The actual implementations of this class take the methods and pass them onto the server for processing. This means a developer does not need to worry about how the methods are transmitted, just that they are transmitted.
Since CruiseServerClientBase is an abstract class there is a static factory class called CruiseServerClientFactory that generates instances of it. This can be as simple as just saying “I want a client class” or as complex as saying “I want a HTTP client class that communicates to the localhost server”. Eventually over time this factory will handle a whole variety of communications protocols – while hiding the complexity from the developer.
The following shows the only line that is needed to instantiate a CruiseServerClientBase:
var client = CruiseServerClientFactory.GenerateClient("tcp://localhost:21234");This will create a client for connecting to the server on localhost. Since the protocol is tcp:// it will create a .NET remoting client. There are also methods to create HTTP or .NET Remoting clients directly – GenerateRemotingClient() and GenerateHttpClient().
Under the hood these methods all create an instance of CruiseServerClient. This is another facade class that provides common functionality. With the 1.5 release CruiseControl.NET is moving to a message-style method interface. This style means every message has a request message and a response message. CruiseServerClient generates the request messages, passes them onto a IServerConnection instance and then processes the response. The IServerConnection instance is actually responsible for transmitting the messages.
As you can guess, there are HTTP and .NET Remoting implementations of IServerConnection. These serialise the message, send it using the correct protocol and then deserialise the response. This response is then returned from the implementation.
As such, it is possible to completely bypass CruiseServerClientFactory and CruiseServerClient and use the IServerConnection instance directly. However this would mean you’d need to write the code to generate the messages yourself, and you’d need to process the responses yourself. CruiseServerClient does all of this plumbing for you.
The following shows how it is possible to trigger a force build with just two lines of code:
var client = CruiseServerClientFactory.GenerateRemotingClient("tcp://localhost:21234");client.ForceBuild("A project");As an added bonus, it is very easy to change from .NET Remoting to HTTP, you’d just change the address. The communications library hides all the underlying complexity for you.
However, before I say everything is roses, there is one current limitation: this will only work with the new 1.5 version server. There is no backwards compatibility.
Which brings me to…
What Is Coming
This work all started out of the security work I did for CruiseControl.NET. I got frustrated by the number of places that needed changing, and the number of different ways, so I merged and simplified them. This opened up some ways of making things simpler under the hood.
However there is still the question of previous versions of CruiseControl.NET. The new library will only work with 1.5 or later versions of CruiseControl.NET servers. It would also be nice to allow backwards compatibility. Now this is much more challenging as a number of base classes have been changed to work with messaging, but I still think it is a worthwhile goal.
I should also mention that HTTP compatibility is broken between 1.4.4 and 1.5. Since CCTray promises that HTTP can be used between versions, I am aiming to ensure that at least HTTP compatibility is ok, and then if possible .NET Remoting. That is the reason why there is a CruiseServerClientBase base class, with only one implementation. These older versions do not use the messaging style method calls, and so won’t be able to use CruiseServerClient. Instead they will need to make their own implementations.
Another step for current functionality is to convert CCTray, the dashboard and the server to all use the new client. These currently still have their existing ways of doing things (although I have started converting CCTray). This means in future, we will only need to change one place to change all three clients! Now that is exciting news to me
![]()
And finally I can write about what I think is really exciting – a CruiseControl.NET SDK.
One of the great points about CruiseControl.NET is its flexibility. It has a lot of functionality in-built, plus a lot of ways of configuring this functionality. And if that is not enough, people can write their own extensions. But that’s where the good news stops – there isn’t exactly a lot of documentation on how to write extensions, how to configure them or how to use them. Plus just to complicate things, the code of CruiseControl.NET isn’t very well documented.
For the communications library I’m going to build up an SDK. This will include:
- The library itself (the API)
- A help document (both compiled and HTML)
- Examples (both code and help-based)
- Quick starts (processes to get someone up and running)
The idea behind this is to provide a knowledge base for a person new to CruiseControl.NET (although no new to programming) and help them to quickly build applications for CruiseControl.NET.
So as you can see, I have a vision that I’m aiming for with the new Communications library. Over time I’ll try and write up some more posts about this library. This library – together with the server extensions – opens up a whole world of possibilities for expanding CruiseControl.NET.
Stay tuned…
