Application Server Setup Code

September 14, 2013

I just finished working through the final kinks (that I know of).

You can instantiate the application server and set it up any way you want to. You do not need the setup objects below. They are there for, hopefully, convenience and simplicity. The Build method on the ApplicationServerSetup object instantiates an appserver, then copies all the stuff from the setup objects to the appserver.

There are 3 setup pre-packaged setups:

  • Hub
  • Node
  • Application

There is an extension method for each. These examples are using node.

The only item you must specifically set is the ObjectFactory. The one I provide is based on Unity. I put all of that into a different assembly so that if someone wants to use something else, they won’t have the unity references polluting the core project.

The unity extension method and objects are not in the same assembly as the setup objects, so I can’t default it to unity because it doesn’t have the reference. The project that uses the app server will have a reference to the unity assembly if that’s what it wants to use.

            var appserver =
                new ApplicationServerSetup()
                    .AsNode()
                    .ObjectFactorySetup.UseUnity().Setup
                    .Build();

            var appserver2 =
                new ApplicationServerSetup()
                    .BusSetup.UseLocalBus().Setup
                    .CommandProcessorManagerSetup.UseDefault().Setup
                    .FeatureManagerSetup.UseDefault().AddApplicationHostFeature().UseAllFolders().SetRootFolder("Applications").Setup
                    .ObjectFactorySetup.UseUnity().Setup
                    .ObjectRepositorySetup.UseDefault().Setup
                    .TypeCacheSetup.UseDefault().Setup
                    .Build();

The first example is the bare-minimum to get a node going. The second expands all of the optional components. So far there is only one implementation for each major component.

The application server can contain one or more features. You can see in the middle that I’m adding a feature called Application Host Feature. It has a dependency that give a list of application configuration objects. It will then create apps for each of those objects. I have two implementations of that dependency. The first, shown, will create one application for every folder within the specified root folder. The other requires you to specify exactly which ones you want.

It defaults to UseAllFolders. If you use AsNode(), it sets it up for you. Then you can tweak the settings if necessary. Furthermore, every setup object has a default builder, so you don’t have to initialize everything explicitly

If you call the same Use more than once, it doesn’t reset it. IE: If you want to get back to the bus, you can do UseLocalBus() again, and it won’t overwrite the existing bus setup. It will see that the type has not changed and will return the existing setup object.

That is handy because these objects all have their own custom properties and methods, but they are stored as their base type. BusSetup.UseLocalBus() will return the correct type you are looking for. But, if later you go to BusSetup.Builder, then all you get is an IBuilder, so then you would have to cast it appropriately. Instead, just use UseLocalBus() again, and it will get the existing object and cast it for you.

The SETUP at the end of each line brings you back to the root ApplicationServerSetup object.

I’m not an expert with fluent interfaces. I may look at this later and bow my head in shame, but at least for the moment, it does what I need it to. In my opinion, it doesn’t matter how well something works if it takes forever to get it up and going. You can now simply create a hub, node or application. If you need something fancier, you can do that too. If the fluent interface doesn’t support something you want, you can add it to share with others (via extension methods and subclasses), or you can just add what you need to the server itself. I am now satisfied with how this balances simplicity and flexibility.

There will be a lot more things to add as I go, but the pattern has been established, so I can get back to working on the app server itself.

If anyone is interested in how the setup objects work, drop a comment and I will elaborate.


When 3 Become 1

September 14, 2013

Whoops… I posted this on the wrong blog 2 days ago.

Application Server

It’s been quite a while since my last post. I took a hiatus from major work on side projects.

Since about 2004 or 2005, I have building what I now call “Application Servers”. The first one I built was nameless. A former IBM employee that the company hired as a consultant spent some time with it and called it “An Application Server”, so it stuck.

DevDash, which I built a couple years ago, is a mini-application server that hosts just one application. I did just enough to host DevDash parts. I built that based on my experiences to that point; it solved every problem I had run into in previous versions. But then it introduced new things to learn from. In particular, the startup process are hard to control. It has services, and tasks, and it starts/executes them in order. IE: All services, then all tasks, etc. But, I ran into situations where I wanted to mix them up: Service A, Task A, Service B, etc. I had to putz around it.

Several months ago, I started writing a new app server primarily with the intent of working through all of the issues again. Really, it’s just an organizational/setup issue.

The solution to this was the command pattern. Rather than executing a bunch of things by type, it instead processes commands. You can add the commands in the desired order and it executes them one at a time. I use the command pattern for lots of things. It’s nice. It worked really well here.

That solved that problem. Then, it was onto the next issue which I struggled with quite a bit. I want this thing to be super simple to setup, and also super flexible. The flexibility is already there. You can wire it up to work anyway you want. You can swap out dependencies, add new stuff, remove stuff… but you need code/configuration to do it. The trick was to wrap that up in a user friendly way.

Several months ago, I wrote and threw away a lot of code a bunch of times. When the usability was reasonable, it didn’t work correctly behind the scenes. In some attempts, I was filling a unity container. One problem was when swapping dependencies, it didn’t have enough information to remove the old ones. It was quite the drama.

Then I didn’t touch it for a several months. I came back to it last week and made a few more attempts. At last, I have the setup working well.

It attempts to be a Fluent API, although I’m sure that can use some work. The setup objects keep track of everything they need without use of a container or anything else. Nothing is loaded until build time when the setup is converted into an appesrver object. So, if you swap out a dependency, the old setup object is replaced with the new one. It is extensible via subclassing and extension methods. When you put your own stuff into the appserver, you can do so directly. Or, if you’re in the mood, you can easily add it to the fluent API.

There are 3 out-of-the-box modes for the app server: Hub, Node, Application. Both HUB and NODE host applications. Unlike all previous versions, the application has it’s own server.

With the fluent API, you can prime it as one of the three then modify. Or, you can just build it from scratch on your own.

Deployment

DevDash is self-updating. When you deploy changes to the repository, the nodes are alerted. They each download the updates and restart themslves. Sweet. That took A LOT of work. Also, you can deploy it remotely from the portal. Just give it a server name and the credentials, and it installs it and starts it. Pretty sweet.

That’s pretty involved. Configuration wise, it contains 2 list of files: one for the service and one for the application. Those files are automatically kept in sync.

For DevDash purposes, and also as research for a work project I’m championing, I’ve been looking into making that more configurable and reusable. I build some db objects to define (basically) as schema, and other tables to store the data. That’s all generic. Then I used that to store some deployment data, such as applicatoins/features/files (which the app server uses), and exposing that via services. That’s all working well. I haven’t actually done the deployment part as I’ve done that many times before and not much to figure out there. But, having the configurable model and services  was a big help.

Dev Dash

I spent untold hours on DevDash, and I’m proud of it. It deploys automatically. It stays updated automatically. It provides custom WS-Discovery, REST routing, pluggable rest services, and lots of other goodies. The portal site receives timely updates (usually within 10 seconds of an event).

It took a lot of work for that. The biggest challenge was having everything work even when it’s counterparts were down. IE: Nodes need to start even if the hub is down. WS-DISCOVERY in WCF doesn’t support that (the discovery service must be reachable), so I wrote a custom implementation to get around that. If the hub goes down, the nodes need to reconnect. If a node goes down, it needs to reconnect. It’s thorough and, while not perfect, works very well.

My biggest regret is that I didn’t know about SIGNALR at the time. That would’ve made everything so much simpler, from the node/hub communication to the website updates. I would’ve had several hours more sleep.

Bringing Them Together

Finally. Now, I am slowly working to bring them altogether.

Step 1 is geting the appserver as complete as I need it to host DevDash.

Step 2 is creating a DevDash application and host it in the app server

Step 3 is adding the deployment to the appservers

I have a lot of work ahead of me, and much free time to do it, so this is going to take forever. Plus, I tend to not to work on things for months at a time. The saving grace there is that I’ve done all the research and playing that I need to, so hopefully that minimizes distractions.

The insanity continues. I will post the setup code soon.