Note: This is the archive of my old homepage. To continue to the new homepage, go to http://davidtanzer.net

This is the personal homepage of David Tanzer. Here you can find a blog-like collection of articles I write. The RSS newsfeed is available here. You can contact me via email: mail-AT-davidtanzer-DOT-net.

You may use everything I write in this blog (tagged as "Submitted by struppi") except the linked papers and some other parts with explicit exceptions to this license, in whole or in part, without asking as long as you give me credit (like for example: "David Tanzer (http://davidtanzer.net) wrote in his blog: [Some quote from this homepage]").

Tech Tournament: Ruby on Rails Screencast

|

The Ruby on Rails Team from the Herbstcampus Technology Tournament have created a nice Screencast for their solution, it's really cool ;) You can watch it at Source-Knights. Be sure to watch in Full Screen Mode!

Herbstcampus .NET Newsletter talk on Youtube

|

There is a short video on youtube showing Oliver Szymanski and me in our talk during the Technology Tournament talk.

http://www.youtube.com/watch?v=moo3RFeyGEM

.NET Webservice with COM+ Serviced Component Example

This Newsletter Example was part of the "Technology Tournament" on the Herbstcampus 2008. The Idea of the Tech Tournament was to solve a simple problem live with different technologies. The rules were:

  • The teams have to write a newsletter application were:
  • Users can register on a website
  • The registered useres get a confirmation mail. This mail contains a Link, and after clicking this link the user is subscribed to the newsletter
  • Info about Subscribers of the newsletter is somehow persisted
  • There should be a GUI client to list all the subscribers
  • There should be a batch client to send emails to all confirmed subscribers
  • The GUI client should use a remoting mechanism to access the business logic

Note: I won't showcase the batch client here, but it is pretty simple.
Note: Sorry for the German screenshots, I only have a German version of Visual Studio.

We chose to use Web Services as our remoting mechanism. We publish the Web Service by creating a Serviced Component and deploying it as a Webservice. Here is a Step by Step Explanation on how to do this:

The Serviced Component (Business Logic)

Open Visual C# Express Edition, then create a new project (File -> New Project) and select "Class Library". I called the Project "NLDemo".
Screenshot Serviced Component Example

Visual Studio automatically creates a class, you can delete it.
Screenshot Serviced Component Example

Open the "Database Explorer" from the "View" - Menu.
Screenshot Serviced Component Example

In the Database Explorer, add a new DB Connection. Use a MS SQL Server Database File, and call it "NLDemo". Use Windows Authentification. When you are asked if you want to create the DB File, click OK.
Screenshot Serviced Component Example

Add a new table to the database, and create the columns "Id" (uniqueidentifier), "Alias" (text), "Email" (text) and "Committed" (bit). Right click on the ID column and make it the primary key.
Screenshot Serviced Component Example

In the Project Explorer, right click on your project (NLDemo), then add a new Element and select "LINQ to SQL Class". I used "SubscriberDataClasses.dbml" as name for this class.
Screenshot Serviced Component Example

Now, when VS asks you if it should copy the File to your Project and change the DB Link, click No!. You really want to click No here, believe me.
Screenshot Serviced Component Example

From the Database Explorer, drag the Table "Subscriber" into "SubscriberDataClasses.dbml". Now you have a class which maps to the DB Table.
Screenshot Serviced Component Example

Add a normal C# Class to your project and call it "SubscriberDTO.cs". We use this class as a Data Transfer Object for our Webservice. We can not use the generated class directly here, becaus we can not transfer GUIDs over the web service. Also this is better design ;)
Screenshot Serviced Component Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NLDemo
{
    [Serializable]
    public class SubscriberDTO
    {
        public string Alias;
        public string Email;
        public bool Committed;
        public String Id;

        public SubscriberDTO(Subscriber s)
        {
            bool foo = false;
            Alias = s.Alias;
            Email = s.Email;
            Committed = s.Committed;
            Id = s.Id.ToString();
        }
    }
}

Now add an Interface to your Project and call it "INewsletterSubscriberManager.cs". This will be the Interface for our Managed Component (-> the interface for the web service).
Screenshot Serviced Component Example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NLDemo
{
    interface INewsletterSubscriberManager
    {
        SubscriberDTO Insert(string alias, string email);
        SubscriberDTO FindById(string id);
        SubscriberDTO[] FindAllCommitted();
        SubscriberDTO[] FindAll();
        void CommitSubscriber(string id);
    }
}

Now add the class "NewsletterSubscriberManager.cs". This class will implement the interface we just created.
Screenshot Serviced Component Example

We want this class to be a serviced component, so we need a reference to "System.EnterpriseServices". You can add this reference in the context menu of the project.
Screenshot Serviced Component Example

When you make ServicedComponent your base class you can add the using directive right after you have typed the name. Do this by clicking on the "Auto Correct" icon. At first, this seems really strange for a java developer who is used to using Eclipse, but it works.
Screenshot Serviced Component Example

After adding the Interface Declaration, you can implement all the methods of the interface by using "Auto Correction".
Screenshot Serviced Component Example

Implement the Interface. Note the cool LINQ queries which are syntax-checked directly by the compiler:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.EnterpriseServices;
using System.Runtime.InteropServices;

namespace NLDemo
{
    [Transaction(TransactionOption.RequiresNew)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class NewsletterSubscriberManager : ServicedComponent, INewsletterSubscriberManager
    {
        private SubscriberDataClassesDataContext dc = new SubscriberDataClassesDataContext();

        public NewsletterSubscriberManager()
        {
        }

        #region INewsletterSubscriberManager Member

        [AutoComplete]
        public SubscriberDTO Insert(string alias, string email)
        {
            Subscriber s = new Subscriber();
            s.Id = Guid.NewGuid();
            s.Alias = alias;
            s.Email = email;
            s.Committed = false;
            
            //SubmitChanges writes to the DB, but since the container manages
            //the transactions it will not be committed until the method is 
            //completed successfully.
            //You can try this out by throwing an exception after "SubmitChanges".
            dc.Subscriber.InsertOnSubmit(s);
            dc.SubmitChanges();

            return new SubscriberDTO(s);
        }

        [AutoComplete]
        public SubscriberDTO FindById(string id)
        {
            return (
                from s in dc.Subscriber
                where s.Id.Equals(new Guid(id))
                select new SubscriberDTO(s)
            ).First();
        }

        [AutoComplete]
        public SubscriberDTO[] FindAllCommitted()
        {
            return (
                from s in dc.Subscriber
                where s.Committed.Equals(true)
                select new SubscriberDTO(s)
            ).ToArray<SubscriberDTO>();
        }

        [AutoComplete]
        public SubscriberDTO[] FindAll()
        {
            return (
                from s in dc.Subscriber
                select new SubscriberDTO(s)
            ).ToArray<SubscriberDTO>();
        }

        [AutoComplete]
        public void CommitSubscriber(string id)
        {
            Subscriber sub = (
                from s in dc.Subscriber
                where s.Id.Equals(new Guid(id))
                select s
            ).First();

            sub.Committed = true;
            dc.SubmitChanges();
        }

        #endregion
    }
}

Now edit AssemblyInfo.cs, Auto Correct works here too. You have to change ComVisible to true because you want to deploy the library as a serviced component. The version number has to contain a wild card ("*"), because you need assembly versioning if you want to deploy more than once. The "assembly: Application*" attributes are used to control security, pooling, ... of the serviced component:
Screenshot Serviced Component Example

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.EnterpriseServices;

// Allgemeine Informationen über eine Assembly werden über die folgenden 
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("NLDemo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NLDemo")]
[assembly: AssemblyCopyright("Copyright ©  2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
[assembly: ComVisible(true)]

// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("c2ac940f-e63f-472f-9b0f-533b2141e5ca")]

// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
//      Hauptversion
//      Nebenversion 
//      Buildnummer
//      Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

[assembly: ApplicationName("NLDemo")]
[assembly: ApplicationActivation(ActivationOption.Server, SoapVRoot="NLDemo")]
[assembly: ApplicationAccessControl(
    AccessChecksLevel=AccessChecksLevelOption.Application,
    Authentication=AuthenticationOption.None,
    ImpersonationLevel=ImpersonationLevelOption.Anonymous,
    Value=false
    )]

You also have to sign the assembly. This is done in the Settings of your Project.
Screenshot Serviced Component Example

To deploy the assembly you have to register it in the Global Application Cache and also install it as a com+ component (using regsvcs.exe). In the Tech Tournament we used a batch file to deploy and undeploy the application, normally you would probably use NAnt.
deploy.bat:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe" /i "C:\work\Mathema\Herbstcampus\NLDemo\NLDemo\NLDemo\bin\Release\NLDemo.dll"
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\regsvcs.exe" "C:\work\Mathema\Herbstcampus\NLDemo\NLDemo\NLDemo\bin\Release\NLDemo.dll"
pause

undeploy.bat:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe" /u "NLDemo"
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\regsvcs.exe" /u "C:\work\Mathema\Herbstcampus\NLDemo\NLDemo\NLDemo\bin\Release\NLDemo.dll"
rmdir /S /Q "C:\Windows\System32\com\SoapVRoots\NLDemo"
pause

After deploying the Serviced Component, you can access it in the Component Services of the Operating System. In Windows Server 2008 this can be found in the Administration Tools menu, I have been told it is more complicated to find it in Windows Vista.
Component Manager And Webservice Screenshot

The NLDemo Component can be found in the COM+ Applications section:
Component Manager And Webservice Screenshot

Here you can change all properties of the serviced component, like security settings, queuing, pooling, ...:
Component Manager And Webservice Screenshot

You can find the web service at http://localhost/NLDemo/ where you will find a link to the WSDL:
Component Manager And Webservice Screenshot

The Web Portal

Open Visual Web Developer Express Edition, and create a new Website. Make sure that you have set the programming language to Visual C#.
Screenshot Serviced Component Example

Now create the Default.aspx page: Add two Text Boxes, and set the IDs of the Text Boxes to "Alias" and "EMail". Add a Button, set it's ID and Text to "Submit". The easiest way to do this is in the visual editor, you can then tune the ASP code to create standards compliant HTML in the Code Editor. To creat the code behind for the submit button, switch to the visual editor again and double-click on Submit.
Screenshot Serviced Component Example

You need to add a service reference to our webservice. Right-click on the project, and add a web reference. Then search for web services on the local computer, and select the one called "NLDemo". Click on "Add Reference".
Screenshot Serviced Component Example

You can use Auto Complete again:
Screenshot Serviced Component Example

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using localhost;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void Submit_Click(object sender, EventArgs e)
    {
        NewsletterSubscriberManagerService nlm = new NewsletterSubscriberManagerService();
        SubscriberDTO sub = nlm.Insert(Alias.Text, Email.Text);

        System.Net.Mail.MailMessage mail =
            new System.Net.Mail.MailMessage("sender.email@foo.com", Email.Text);
        mail.Subject = "Newsletter Registration";
        mail.Body = "Please confirm your registration by clicking this link:\n"
            + "http://localhost:12345/NLDemoWeb/Commit.aspx?id=" + sub.Id;

        System.Net.Mail.SmtpClient sc = new System.Net.Mail.SmtpClient();
        sc.Host = "mail.server.foo.com";
        sc.Port = 25;

        sc.Send(mail);
        
        Response.Redirect("Thanks.aspx");
    }
}

Change the From Email Address and the Mail Server Host (sc.Host) to valid values. The port of the website in the confirm link has to be changed if you want to use debugging - you don't know on which port your debugging webserver runs until you start it.
Screenshot Serviced Component Example

Just click the "Debug" button and select the option to change Web.config for debugging. Now the debug webpage is shown. You can use the port here for the confirm link. This port might change when you re-start Visual Web Developer or your computer.
Screenshot Serviced Component Example

Now add a new Web Form to your project, called "Commit.aspx".
Screenshot Serviced Component Example

Add a Text and a Label. Set the ID of the Label to "Alias".
Screenshot Serviced Component Example

Now open the Code Behind-File for the Commit Page and add the code for page load:
Screenshot Serviced Component Example

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using localhost;

public partial class Commit : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string id = Request.QueryString["id"];
        NewsletterSubscriberManagerService nlm = new NewsletterSubscriberManagerService();
        SubscriberDTO s = nlm.FindById(id);
        nlm.CommitSubscriber(s.Id);

        Alias.Text = s.Alias;
    }
}

Also add a "Thanks.aspx" file which contains only a thank you message. The front page redirects here.
Screenshot Serviced Component Example

The GUI client

In Visual C#, create a new Windows Forms project. Change the name of Form1 to "NLDemoClient", and add a ListBox and a Button. Rename the ListBox to "subscriberList" and the Button to "refresh". Set the Text of the Button to "Refresh".
Screenshot Serviced Component Example

You need a reference to the web service. To add this, right-click on the project and select the menu item to add service references. There click on Advanced and then add the Web Reference (you can find the Button in the "Compatibility" - Section). From there on it is the same procedure as in the Web Portal.
Screenshot Serviced Component Example

Double-click on the Refresh Button to add the click-callback:
Screenshot Serviced Component Example

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NLDemoClient.localhost;

namespace NLDemoClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void refresh_Click(object sender, EventArgs e)
        {
            NewsletterSubscriberManagerService nlm = new NewsletterSubscriberManagerService();
            SubscriberDTO[] list = nlm.FindAll();

            subscriberList.Items.Clear();
            foreach (SubscriberDTO s in list)
            {
                subscriberList.Items.Add(s.Alias + " - " + s.Committed.ToString());
            }
        }
    }
}

After clicking on "Refresh" you will get the list of subscribers.
Screenshot Serviced Component Example

Possible Errors

If you try to send a GUID in the Web Service you get this un-helpful error message:
Error Screenshot
This is one of the reasons why we added the class "SubscriberDTO".

If you redeploy the serviced component you have to refresh the service reference:
Error Screenshot

Otherwise you will get an InvalidCastException.
Error Screenshot

While practising the talk we also had problems when we deployed without undeploying, or when we called deploy and undeploy not in the right order (which would be "undeploy" - "build all" - "deploy"). I could not reproduce then when preparing this blog entry. I think deleting the whole SoapVRoot directory of IIS saves you a lot of trouble (the "rmdir" - line in the undeploy script), we added this line later to make sure everything is removed correctly.

Herbstcampus 2008

|

The last three days I was at the Herbstcampus 2008, a new Conference in Nürnberg (Germany), and it was really great. I am right next to James Gosling on the Speaker Foto ;)

I did only one talk, except that I didn't talk ;) - I was the programmer in the .NET session of the technology tournament. The tournament was about creating a newsletter application with a certain technology (.NET, Java EE, Java+Spring+Hibernat, Ruby on Rails an Ercatons). All the coding had to be done live in 70 Minutes, the only set up we ware allowed to prepare was the development environment. Oliver Szymanski and I did the .NET session and it was great - I think I'll present our solution here on this blog because we used COM+ Serviced Components as Webservices, and we didn't find a comprehensive tutorial on how to do this on the net (especially when it comes to errors and what the error messages mean).

The other talks were pretty cool too, especially the ones from James Gosling and Dirk Prims (an Evangelist from Microsoft Germany) who gave a pretty interesting talk about security and tricks how crackers can exploit certain programming errors. The whole conference was pretty cool, but there were some things which were a little bit annoying: Errors in the Schedule, Chaos at the meals (which were not very good). Anyway, it was the first time for the organizers, and I guess they'll learn for the next time.

You can read more about the campus (and Java and .NET programming in general) in the blog source-knights.com.

Did the Khronos Group just kill cross platform gaming?

Reading all the angry posts about OpenGL 3.0 like the slashdot discussion or this post by Irrlicht3D developer Nikolaus Gebhardt it looks like that...

Braindead Software: Outlook and Exchange

Seriously, why is anybody using Microsoft Outlook and Exchange? Outlook is really bad compared to other email programs (no other program was complaining when the inbox had more than 1000 mails...), and it's not even working properly:

Some days ago my Outlook just stopped to receive emails from the Exchange server. Webmail works fine, and Outlook says it is connected to the server. I tried to change the server settings to the initial settings, and guess what: You can not change the URL of an Exchange server in Outlook!

I think I'll just use webmail (Outlook Web Access) again, at least it works. Sometimes.

openmoko - will it ever work?

Somehow I am not so confident that openmoko will ever deliver an open, working mobile phone platform when I read blog postings like this and this. The project is running for almost two years now, and now they start developing the framework? Even if they are able to sell a working smartphone this year (which I still doubt), they are pretty late. What a pity, I thought this was a pretty cool project.

Naked CSS Day

Oops, I almost missed it. Today is CSS Naked Day.

As you can see, davidtanzer.net doesn't look too good without CSS, so I'll have to correct my theme for next year... If I don't forget ;)

C Unit Testing for my Diploma Thesis

I have now decided to write my own unit testing framework because I did not find a suitable one. I want to add special assert functions for testing vectors, matrices, maybe acceleration structures, and so on. A simple unit test suite looks like this:

#include <unittest/unittest.h>
#include <unittest/assert.h>
#include <core/gre_math.h>
#include <core/geometry.h>

void gre_mathtest_setup() {
	
}

void gre_mathtest_teardown() {
	
}

void gre_mathtest_vector_dot_vector() {
	gre_vector4d v1 __attribute__((aligned(16)));
	gre_vector4d v2 __attribute__((aligned(16)));
	v1.x=2; v1.y=3; v1.z=4; v1.w=5;
	
	v2.x=1; v2.y=0; v2.z=0; v2.w=0;
	gre_assert_float_equals(gre_math_vector_dot_vector(&v1, &v2),
			2, 0.00001, "Vector product [2,3,4,5]*[1,0,0,0]");
	v2.y=1;
	gre_assert_float_equals(gre_math_vector_dot_vector(&v1, &v2),
			5, 0.00001, "Vector product [2,3,4,5]*[1,1,0,0]");
	v2.z=1;
	gre_assert_float_equals(gre_math_vector_dot_vector(&v1, &v2),
			9, 0.00001, "Vector product [2,3,4,5]*[1,1,1,0]");
	v2.w=1;
	gre_assert_float_equals(gre_math_vector_dot_vector(&v1, &v2),
			14, 0.00001, "Vector product [2,3,4,5]*[1,1,1,1]");
}

int main(int argc, char **argv) {
	int num_test_functions=1;
	test_function mathtest_functions[] = {
			{ "vector_dot_vector", gre_mathtest_vector_dot_vector }
	};
	
	gre_unittest_register_test_case("mathtest", gre_mathtest_setup, 
			num_test_functions, mathtest_functions, gre_mathtest_teardown);
	
	gre_unittest_run_testsuite();
}

C Unit Testing Framework

Does anybody know a good Unit Testing Framework? I have had a look at CUnit which seems nice, but the license is LGPL and I would prefer a AL2 or compatible license. I also have checked out CuTest (ZLib license, but it looks a little bit strange) and RCUnit (GPL, so not an option).

All three frameworks are really simple, so it should only be a matter of a few days to write my own, and I am seriously considering doing that.