Friday, January 23, 2009

Java web service interoperability from .NET CF 1.0

I don’t suppose anyone else is developing in .NET CF 1.0 now in 2009. Well those are the constraints for project I’m involved in and I prefer to think about this as a challenge :)

Anyway current topic is interoperability with Java web services. This causes a lot of problems in .NET CF 1.0, some of them weren’t addressed until .NET CF 3.5. In my case it started with inability to generate web service client proxy using standard wsdl.exe tool.

In this example we have a Java web service for querying cars by name. It returns car description with name and collection of car parts. Each car parts can have a set of string attributes. The model looks like this:

image

  Let’s say we have WSDL like this one:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="ws" targetNamespace="http://tempuri.org" 
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
                  xmlns:tns="http://tempuri.org" 
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xsd:schema targetNamespace="http://tempuri.org" xmlns:pref="http://tempuri.org/to">
        <xsd:import namespace="http://tempuri.org/to" schemaLocation="myschema.xsd" />
        <xsd:element name="getCarDesc">
            <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="carQuery" type="pref:CarQuery" maxOccurs="1" minOccurs="1" />
          </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
        <xsd:element name="getCatDescResponse">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="response" type="pref:Car" maxOccurs="1" minOccurs="0" />
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="carRequest">
    <wsdl:part element="tns:getCarDesc" name="parameters"/>
  </wsdl:message>
  <wsdl:message name="carResponse">
    <wsdl:part element="tns:getCarResponse" name="parameters"/>
  </wsdl:message>
  <wsdl:portType name="ws">
    <wsdl:operation name="getCar">
      <wsdl:input message="tns:carRequest"/>
      <wsdl:output message="tns:carResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="wsSOAP" type="tns:ws">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getCar">
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ws">
    <wsdl:port binding="tns:wsSOAP" name="wsSOAP">
      <soap:address location="http://myhost/get-cat-web/ws" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

There is one service and it has one method, getCar. This method takes CarQuery object as a parameter and returns a Car object as response. The WSDL refers to external schema in myschema.xsd file, which contains type definitions.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
        targetNamespace="http://tempuri.org/to" 
        xmlns:tns="http://tempuri.org/to" 
        elementFormDefault="qualified"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0">

    <complexType name="CarPart">
        <sequence>
            <element name="attribute" type="string" maxOccurs="unbounded" minOccurs="1" />
        </sequence>
    </complexType>

    <complexType name="Car">
        <sequence>
          <element name="name" type="string" maxOccurs="1" minOccurs="1" />
          <element name="parts" type="tns:CarPart" maxOccurs="unbounded" minOccurs="0" />
        </sequence>
    </complexType>

    <complexType name="CarQuery">
        <sequence>
            <element name="name" type="string" maxOccurs="1" minOccurs="1" />
        </sequence>
    </complexType>
</schema>

This works perfectly in Java and is used by Java guys to generate a web service. When you try to feed this to wsdl.exe, the only thing it has to say is:

Error: Unable to import binding 'wsSOAP' from namespace 'http://tempuri.org'.
 - Unable to import operation 'getCar'.
 - The operation binding 'getCar' from namespace 'http://tempuri.org' had invalid syntax.
Missing soap:operation binding.

At least wsdl.exe is being quite specific about this one. I went to validate my WSDL at this site and it confirmed, that I lack soap:operation tag. So I added it and specified operation URI:

    <wsdl:operation name="getCar">
      <soap:operation soapAction="http://tempuri.org/ws/getCar" style="document"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

The wsdl.exe finished successfully and generated proxy class along with used types. This however was not the end of my struggle. It turned out, that the generated code won’t compile int .NET CF 1.0 as there is no support for Form property of XmlElementAttribute class. The web service method was decorated with this attribute in following way:

[return: System.Xml.Serialization.XmlElementAttribute("response", 
    Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public Car getCar(
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
    CarQuery carQuery) 
{
    ...
}

It’s really strange that this tool would generate code that won’t compile (and yes, the result was the same when created using Add Web Reference in Smart Device project). I went to look for solution on the web and came up with this modification to WSDL (added elementFormDefault attribute):

...
<wsdl:types>
    <xsd:schema elementFormDefault="qualified" 
                targetNamespace="http://tempuri.org" xmlns:pref="http://tempuri.org/to">
...

This removed all usages of the Form property of XmlElementAttribute class. The code would now compile, but looked a little different than I expected. Take a look at the Car class:

public class Car {
    
    private string nameField;
    
    private string[][] partsField;
    
    /// <remarks/>
    public string name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("attribute", typeof(string), IsNullable=false)]
    public string[][] parts {
        get {
            return this.partsField;
        }
        set {
            this.partsField = value;
        }
    }
}

There’s no CarPart object collection. There was no CarPart class in generated code at all. Instead, the tool generated string[][] array for me. Well it’s not what I would like to have, but I could live with it. So I went on to code that test the web service and to my surprise the constructor of the proxy class threw FileNotFoundException as the application was unable to find a dynamically created assembly used by XML serializer. I tried to do the same with Visual Studio 2008 and here’s what I got:

InvalidOperationException was unhandled
Unable to generate a temporary class (result=1).
error CS0029: Cannot implicitly convert type 'string' to 'string[]'

Not only the wsdl.exe changed the object model, but also the XML Serializer was unable to deal with it. At this point I decided to manually modify the generated code and added the CarPart class. I also changed parts collection to CarPart[] type. And it finally worked. Yet I feel disappointed that I have to manually create proxy classes to work with Java web services.

A whole different thing is performance of web services on the smart device. SOAP and XML imply large message sizes and extensive use of reflection, which has a great impact on the application’s performance.

DotNetKicks Image

Saturday, January 17, 2009

Dependency injection in .NET CF 1.0

Recently I got involved in building an application for mobile devices. The problem is that they are old Pocket PC 2002 devices, so the only option to write managed code is to use also old .NET CF 1.0. Don’t even get me started on how limited it is and how much pain it is to work with VS2003 – do you remember the times when you had to add namespace imports by hand? Without ReSharper it’s almost unbearable.

Anyway I’m responsible for the design of the solution. I thought it would be nice to have DI container, but there are some constraints on the mobile platform:

  • Performance – There’s no possibility to use reflection extensively without running into performance problems.
  • Limited BCL - .NET CF 1.0 base class library is only a small subset the .NET 1.1 BCL, not to mention .NET 2.0

Taking this into account I thought it would be best to implement a really simple solution myself. The features of my simple container are:

  • Mapping interfaces to implementing types
  • Registering types both as singleton and as transient instance
  • Registering existing instances
  • Resolving both mapped interfaces and unmapped types
  • Injecting dependencies into constructors (recursively)
  • Fluent registration syntax
  • Reflection usage reduced to a minimum

This set of functionalities should allow me to work comfortably with dependency injection and keep the container as simple as possible. Here is the code, first the container interface:

public interface IContainer
{
    IContainer Register(Type mapFrom, Type mapTo);
    IContainer RegisterSingleton(Type mapFrom, Type mapTo);
    IContainer RegisterSingleton(Type mapFrom, object toInstance);
    object Resolve(Type type);
}

Register method allows you to register a mapping of a transient objects (instantiated on every resolve). RegisterSingleton is overloaded and allows you to register either a type mapping or type to existing instance mapping as a singleton (instantiated only once). Resolve returns instance of requested type – either mapped or not.

Now TypeItem class used to store type mappings (in a Hashtable):

public class TypeItem
{
    private Type targetType;

    public Type TargetType { get { return targetType; } }

    private bool sigleton;

    public bool Singleton { get { return sigleton; } }

    public TypeItem(Type targetType, bool singleton)
    {
        this.targetType = targetType;
        this.sigleton = singleton;
    }
}

And the container itself:

public class Container : IContainer
{
    private Hashtable typeMap = new Hashtable();
    private Hashtable singletonCache = new Hashtable();
    private ArrayList targetTypeList = new ArrayList();

    #region IContainer Members

    public IContainer Register(Type mapFrom, Type mapTo)
    {
        CheckRegistrationConditions(mapFrom, mapTo, true);

        TypeItem item = new TypeItem(mapTo, false);
        AddItem(mapFrom, item);
        return this;
    }

    public IContainer RegisterSingleton(Type mapFrom, Type mapTo)
    {
        CheckRegistrationConditions(mapFrom, mapTo, true);

        TypeItem item = new TypeItem(mapTo, true);
        AddItem(mapFrom, item);
        return this;
    }

    public IContainer RegisterSingleton(Type mapFrom, object toInstance)
    {
        CheckRegistrationConditions(mapFrom, null, false);
        Guard.AgainstNullArgument(toInstance, "toInstance");

        TypeItem item = new TypeItem(toInstance.GetType(), true);
        if(targetTypeList.Contains(item.TargetType))
        {
            throw new ArgumentException(
                "Cannot register singleton because another singleton mapping " + 
                "uses the type of the instance",
                "toInstance");
        }
        AddItem(mapFrom, item);
        singletonCache.Add(item.TargetType, toInstance);
        return this;
    }

    public object Resolve(Type type)
    {
        Guard.AgainstNullArgument(type, "type");

        if (typeMap.ContainsKey(type))
        {
            // mapped type
            TypeItem item = typeMap[type] as TypeItem;

            if (item.Singleton && singletonCache.ContainsKey(item.TargetType))
                return singletonCache[item.TargetType];

            object instance = BuildInstance(item.TargetType);

            if (item.Singleton)
                singletonCache.Add(item.TargetType, instance);

            return instance;
        }
        else
        {
            // unmapped type
            if (!type.IsClass || !type.IsPublic)
                throw new TypeResolveException(
                    "The type " + type.Name + 
                    " is neither mapped nor can it be instantiated");

            return BuildInstance(type);
        }
    }

    #endregion

    private void CheckRegistrationConditions(Type mapFrom, Type mapTo, bool mapToValid)
    {
        Guard.AgainstNullArgument(mapFrom, "mapFrom");
        if (mapToValid)
        {
            Guard.AgainstNullArgument(mapTo, "mapTo");
            if (!mapTo.IsClass || !mapTo.IsPublic)
                throw new ArgumentException("The type " + mapTo.Name + 
                    " cannot be instantiated");
        }

        if (typeMap.ContainsKey(mapFrom))
            throw new ArgumentException("Provided type is already mapped", "mapFrom");
    }

    private void AddItem(Type mapFrom, TypeItem item)
    {
        typeMap.Add(mapFrom, item);
        targetTypeList.Add(item.TargetType);
    }

    private object BuildInstance(Type type)
    {
        ConstructorInfo[] constructors = type.GetConstructors(
            BindingFlags.Public | BindingFlags.Instance);

        if (constructors.Length == 0)
            throw new TypeResolveException("The type " + type.Name +
                " has no public constructors");

        ParameterInfo[] parameters = constructors[0].GetParameters();
        object[] paramValues = new object[parameters.Length];

        for (int i = 0; i < parameters.Length; i++)
        {
            paramValues[i] = Resolve(parameters[i].ParameterType);
        }

        return constructors[0].Invoke(paramValues);
    }

}

As you might noticed, the BuildInstance method just takes the first public constructor returned by GetConstructors and uses it to create instance. This is enough for my scenario, but you might want to mark injection constructor with a custom attribute or select constructor basing on some criteria (ex. most resolvable parameters).

There are also some tests for the container, but I won’t be posting them here.

DotNetKicks Image

Monday, January 12, 2009

Comparing OpenID and canonical Subject-IP-RP pattern

A hot topic lately is identity management in distributed environments and there are some interesting articles on this in the Architecture Journal. The basic thing to do in distributed environment, presumably SOA, is to delegate the identity management to separate component called Identity Provider (IP). It is responsible for maintaining user database and issuing security tokens. This security tokens are used by the subject (a user who wants to gain access to a resource) to authenticate at the Relaying Party (a component that maintains the resource). This way user doesn’t have to have separate user account on each Relaying Party and presumably authenticate in different way using different credentials. The Relaying Party trusts the Identity Provider to perform user authentication. Following diagram presents this situation:

image 

Now in order to authenticate at the Relaying Party, following steps are taken [1]:

image

Subject first discovers how to authenticate at Relaying Party by getting the security policy. It then authenticates at Identity Provider using proper credentials and receives a security token, which is used to authenticate resource requests at Replaying Party. Relaying Party verifies the token’s signature to ensure it comes from the trusted Identity Provider.

OpenID is a decentralized and open identification standard basing on a concept of trusted Identity Provider. The “distributed” in practice means, that there are many IPs on the web and it’s up to user to decide which one will suit him. For example there is OpenID provider for Google’s Federated Login API, which you can use your Google account to authenticate with OpenID. There are also some dedicated IPs and you even can easily setup your own IP if you do not trust anybody else :). OpenID was created with authentication at web portals and communities in mind (it’s being used by Stack Overflow for instance). It’s well suited for this task and differs from the canonical Subject-IP-RP pattern. It is assumed, that user uses web browser to authenticate and the protocol relies heavily on HTTP/HTML (but implementation in desktop apps is also possible). Authentication process orchestration is taken from hands of the subject and directed by Relaying Party instead. Username has a form of URL and plays significant role during the process of authentication as follows [2](a rough view):

image

Relaying Party queries username URL to discover information on Identity Provider used by given user. Then, user’s browser is redirected to IP’s login site. After logging in, IP redirects user to RP’s return URL including information about authentication result in the request. RP verifies whether the login status information is legitimate by querying IP.

There are also some modifications and extensions to this protocol like for example ability for RP and IP to establish a shared secret used to verify login status information without the need to query IP every time a user logs in.

Implementation of OpenID authentication is easy, because there are many open libraries for each platform. For .NET there is DotNetOpenId, which even provides ready to use controls for ASP.NET. I suggest you read OpenID specs [2] for more detailed information on this topic. Anyway it would be nice to see OpenID authentication more popular and used by all community portals.

Resources:

[1] Vittorio Bertocci, “Claims and Identity: On-Premise and Cloud Solutions”. The Architecture Journal, Journal 16.

[2] OpenID Authentication 2.0 – Final. http://openid.net/specs/openid-authentication-2_0.html, 2009.

DotNetKicks Image

Share