11 November 2006

AppDomain, process and components...

This is a fundamental concept in .Net. In this short retrospective I try to offload following points:
1. What is AppDomain? Aslo a derived question: what is the difference between Appdomain and process?
2. Why we need AppDomain?
3. What is the design implication of Appdomain has on software?

So what is AppDomain? What is the difference between Appdomain and process?
From gotnotnet
“Application Domain is a construct in the CLR that is the unit of isolation for an application.” In non-.NET CLR environment, each running application is hosted by a process. There can be numerous processes launched of the same application and each process can only host ONE application. In contrast, .NET CLR introduces a light-way unit to load an application – AppDomain. Each AppDomain hosts one application, (or indeed assembly, component). Each process can have multiple AppDomains.

Why we need AppDomain?
AppDomain provides isolation around applications without the heavy cost associated with running an application within a process (address space, context, security...). In another word when addressing security context for example, it is wrapped around process unit. It relives each resident in an AppDomain from handling it themselves.

The isolation means:
• An application can be independently stopped.
• An application cannot directly access code or resources in another application.
• A fault in an application cannot affect other applications.
• Configuration information is scoped by application. This means that an application controls the location from which code is loaded and the version of the code that is loaded.

What is the design implication of AppDomain has on software?
AppDomain promotes a loose-coupled component-oriented programming mode.

The term component is probably one of the most overloaded terms in morden software engineering. From Wikipedia I found quite a few entries, which defines ‘component’ in different domain. Where it is related to computer science, it reads ‘A piece that makes up a whole, a part of an assembly’. Very abstract. In electronic component, it says ‘An electronic component is a basic electronic element usually packaged in a discrete form with two or more connecting leads or metallic pads. Components are intended to be connected together…’ This definition is more vivid to use as a metaphor here.

In .net a class *IS* a component. In the extreme form, one can compile a .net class into a binary assembly. Then CLR can load it into an AppDomain of a process.
From runtime process’ point of view, ‘traditional’ programming model/application is packaged to a monolithic binary block, regardless how it maps class diagram for business logic. Monolithic binary means they are tightly coupled. A change to one class can trigger a massive relinking of the entire application and necessitate retesting and redeployment of all other classes.

In contrast, a .net component based application is a collection of binary building blocks grouped by functionality. Each block contains one or more classes. At run time, each block is loaded to an AppDomain, together, they make up a process. If one of the component needs to be update, changes are contained to that component only. No existing client of the component requires recompilation or redeployment. An updated component can even be updated while a client application is running, as long as the component isn’t currently being used.

02 November 2006

Create your custom xAnt task

Here are some notes on how to extend ant task to provide your custom ant task.

Both ant build (for Java) and nAnt build (for .net) are discussed.

1. nAnt

In nAnt for .net build you embedded c# code as script though semantically it is a derived class from Nant.Core.Task. (You don’t need to include Nant.Core assembly. It is loaded by default). A scripting block is a top level block, meaning side by side with <target> block.

In following sample script., the first static c# function is a - function - to work out number of running processes by given name.
The secnd task class is to kick off an external batch file - if you want the batch running in a separate process there isn't better way that this cumbersome one.
The third task class is to kill a process.

<script language="C#" prefix="custom">
<code>
<![CDATA[
[Function("NumberOfRunningProcess")]
public static int NumberOfRunningProcess(string name)
{
System.Diagnostics.Process[] procList = System.Diagnostics.Process.GetProcessesByName(name);
return procList.Length;
}

[TaskName("WriteRunXspBatchScript")]
public class WriteRunXspBatchScript: Task
{
private string _batchFilePath;
private string _httpRootPath;
private int _port;

[TaskAttribute("XspRunScript", Required=true)]
public string BatchFilePath
{
get{return _batchFilePath;}
set{_batchFilePath=value;}
}

[TaskAttribute("HttpRootPath", Required=true)]
public string HttpRootPath
{
get{return _httpRootPath;}
set{_httpRootPath=value;}
}

[TaskAttribute("Port", Required=true)]
public int HttpPort
{
get{return _port;}
set{_port=value;}
}

protected override void ExecuteTask()
{
string cmd = string.Format("start /MIN xsp --root \"{0}\" --port {1}", _httpRootPath, _port);
using (StreamWriter wr = new StreamWriter(_batchFilePath,false))
{
wr.WriteLine("@echo off");
wr.WriteLine(cmd);
}
}
}
[TaskName("StopXsp")]
public class StopXsp : Task{
private bool _deleteXsp;
private string _xspRunScript;

[TaskAttribute("DeleteXspRunScript", Required=false)]
public bool DeleteXspRunScript
{
get{return _deleteXsp;}
set{_deleteXsp=value;}
}

[TaskAttribute("XspRunScript", Required=false)]
public string XspRunScript
{
get{return _xspRunScript;}
set{_xspRunScript=value;}
}

protected override void ExecuteTask() {
System.Diagnostics.Process[] procList = System.Diagnostics.Process.GetProcessesByName("mono");
if (procList==null )
{
throw new Exception("No Mono process found. Expect to kill one and only one mono xsp process");
}
if (procList.Length>1)
{
throw new Exception("More than one Mono processes is running. Expect to kill one and only one mono xsp process");
}
try
{
procList[0].Kill();
}
catch(Exception){;}

if (_deleteXsp)
{
File.Delete(_xspRunScript);
}
}
}
]]>
</code>
</script>


Usage:
<echo message="process devenv ${custom::NumberOfRunningProcess('devenv')}" />
<WriteRunXspBatchScript Port="80" HttpRootPath="${webcontrolsUnitTest.src.dir}" XspRunScript="${build.dir}\${MonoXspRun}" />
<StopXsp DeleteXspRunScript="true" XspRunScript="${build.dir}\${MonoXspRun}"/>

2. ant
Reference to Extending Ant to support interactive builds, to archive this you need to write external java classes, expose package via classpath by system envronment variable or via <path> in the build script.

The only change to the sample code given in
Extending Ant to support interactive builds is instead of using classpath, it uses <path> :
<?xml version="1.0"?>
<project name="PropertyPromptExample" default="main" basedir=".">
<property name="promptTimeout" value="5"/>
<path id="extendedTask">
<fileset dir="c:\playpit\">
<include name="monkeyNuts.jar"/>
</fileset>
</path>
<taskdef name="propertyprompt" classname="com.ibm.samples.apache.tools.ant.taskdefs.optional.PropertyPrompt" classpathref="extendedTask"/>

<target name="main">
<!-- <javac srcdir="." destdir="." verbose="on"/> -->
<property name="propA" value="oldValA"/>
<property name="propA" value="oldValA1"/>
<echo>value of propA: ${propA}</echo>
<echo>value of propB: ${propB}</echo>
<propertyprompt propertyname="propA" promptcharacter=":">Enter value for propA</propertyprompt>
<propertyprompt propertyname="propB" defaultvalue="defvalB">What is the value for propB</propertyprompt>
<echo>value of propA: ${propA}</echo>
<echo>value of propB: ${propB}</echo>
</target>
</project>