Tuesday, June 22, 2004

Web Services exposing internal object types

Lately I have been looking at creating some WSDL for a few web services for the product that I am working on.
One of the issues that I am having is how to maximize the flexibility of the system by making sure that each layer within the web service hierarchy (web service stub/business/data layer) is independent of one another. One of the decisions that I have to make is whether or not to return a domain model object type via a web service method. For instance, suppose that I have the following domain model object:

Case A:

public class Product
{
public string name;
public string sku;
public double price;

public Product() {}

public Product(string name, string sku, double price)
{
this.name = name;
this.sku = sku;
this.price = price;
}
}


My business layer has a method that retrieves an object of type Product:

public class ProductBusiness
{
public Product retrieveProduct()
{
return new Product("JellyBelly (8 oz.)", "PK09834", 2.50);
}
}

My web service calls the retrieveProduct method:

[WebMethod]
public Product getProduct()
{
ProductBusiness bus = new ProductBusiness();
Product prod = bus.retrieveProduct();
return prod;
}


In this example, the WSDL is driven by the domain model (what I call schema last). There
are a few drawbacks to this approach:


One solution would be to add a mapper class that would translate between the classes exposed via the public web service (WSDL) and the classes used internally by the business layer. One way to do this is to define the WSDL independently of any application domain model classes.

Case B:
Suppose that I defined the WSDL for a product called WSProduct:

public class WSProduct
{
public string name;
public string sku;
public double price;
public DateTime dateRetrieved;
}

And change the web method to use this class:

[WebMethod]
public WSProduct getWSProduct()
{
ProductBusiness bus = new ProductBusiness();
WSProduct prod = bus.retrieveWSProduct();
return prod;
}

Now the web service method returns a class of type WSProduct, and it obtains
the object from the ProductBusiness class via the retrieveWSProduct() method.
The retrieveWSProduct method on the ProductBusiness class looks like this:

public WSProduct retrieveWSProduct()
{
Product prod = new Product("JellyBelly (8 oz.)", "PK09834", 2.50);
WSProduct wsProd = new WSProduct();
wsProd.name = prod.name;
wsProd.sku = prod.sku;
wsProd.price = prod.price;
wsProd.dateRetrieved = DateTime.Now;
return wsProd;
}

The method creates a Product and a WSProduct class, and then it translates(copies)
the values from the Product class to the WSProduct class. It also sets the dateRetrieved field on the WSProduct class.

In this case, any changes to the Product domain model class will not affect the contract
exposed by the web service, since this contract is represented by the WSProduct definition
in the WSDL. Any changes to the WSProduct in the WSDL will only affect the ProductBusiness
object (retrieveProduct will need modification). The Product object will remain unchanged since it is only used internally and it is not exposed by the web service.

Now for the question:

Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?