Monthly Archives: November 2002

EnterpriseServices and transactions

Ok, I’m going to barge in on this discussion that Clemens kicked off.  Hope no one minds.  :-)  First, my general opinion is that if you need distributed transactions, object pooling, or a consolidated process model (for caching, etc.), then sure, EnterpriseServices is an easy way to get these features.  However, I hold that there is a huge class of applications that don’t actually require any of these.

I wanted to specifically comment on something Ingo Rammer said about transactions.  To start it off, John Lam wrote:

If I’m writing a managed application that has a web-based front end, and I don’t need distributed transactions, why do I need to care about Enterprise Services?

To which Ingo replied:

The second scenario in which I’d think about using EnterpriseServices is if I don’t know the exact call chain of my infrastructure components. Using imperative, single resource manager transactions absolutely requires you to know the very call chain/s which will be used to call your infrastructure components.

<example type=”very contrived”>
  public void StoreCustomer(Customer cust);
  public void AddOrder(Order ord);
</example>

[…]  So, at least for me, the question which should be used to choose between declarative and imperative TX (and therefore also in favor or against EnterpriseServices) is not only “Do I need distributed transactions?” but also “Do I need transactions for which I don’t know the exact call chains which will be used to access my infrastructure layer components?” and “Will these call chains ever change or could there be new ones?”.

So he’s saying that in order to design a robust application with local non-declarative transactions, one needs to know every possible permutation of the call chain.  I beg to differ on this; a model I’ve used is as follows.  A (possibly optional) transaction parameter can be passed throughout the call chain (you could even make this implicit via the CallContext, but I haven’t seen the need yet).  Each function operates based on the passed in transaction.  So the outside controller looks something like:

using (SqlConnection conn = new SqlConnection(connectionStr))
{
  conn.Open();
  SqlTransaction trans = conn.BeginTransaction();

  try
  {
    int custId = Customer.AddCustomer(custInfo, trans);
    Order.AddOrder(custId, orderInfo, trans);
    trans.Commit();
  }
  catch (MyException e)
  {
    trans.Rollback();
    // log error, throw exception, etc.
  }
}

and the lower level objects look something like:

public int AddCustomer(CustInfo custInfo, SqlTransaction trans)
{
 
int custId = 0;
 
SqlConnection conn = null;

 
if (trans != null)
   
conn = trans.Connection;
 
else
 
{
   
conn = new SqlConnection(…);
    conn.Open();
 
}

 
try
 
{
   
SqlCommand cmd = new SqlCommand(…, conn, trans);
   

 
}
  finally
 
{
   
if (trans == null)
     
conn.Dispose();
 
}

 
return custId;
}

So they can operate in the presence of a transaction, or in the absense of one.  If there is not a transaction passed in, they would have the option of creating one, executing without one, or failing.  And if all critical (ie. transaction must be aborted) manifest themselves as exceptions, then the transaction outcome will be correct.

The benefit, obviously, is not having to use distributed transactions, and the associated overhead that comes with them.  In my opinion, the code above is not complicated, and other than the boilerplate code, the “way of thinking” is much the same as it is with using declarative transactions with EnterpriseServices.  And to come back to Ingo’s point, I think if all of your business methods are designed like this, you can add/remove them at will from the call chain, and everything should still work.

Is WSDL too hard? Cont’d.

Is WSDL too hard?  Cont’d.

A couple of comments from Simon and Clemens:

Is WSDL too hard?. In response to Greg Reinacker’s comments I didn’t say WSDL is hard, I said its cumbersome and unproductive. Come on, its just angle brackets how hard can it be ?? [Simon Fell]

Simon – I didn’t actually mean to say that you were one of the “oh-so-many people” I talked about…your post just happened to remind me about them.  :-)

Hard or not hard — can we agree on “It’s just not enough” ? :) My main problem with WSDL is that it tries to do 2 things (message contract and transport mapping), while it should do 3 things (message contract, service contract and transport mapping), hnowever at the same time, one thing (WSDL) shouldn’t do all these 3 things altogether but leave them two 3 separate things: A message contract definition language (defines soap:Body content), a service contract definition language (soap:Header) and a “web services binding language” that maps messages combined with services to transports. [Clemens Vasters: Enterprise Development & Alien Abductions]

Clemens hits the nail on the head here.  What he describes as a “service contract” is exactly what’s missing from WSDL, in my opinion.  One example is a service that supports WS-Security; I should be able to look at the WSDL contract, and learn that WS-Security is required, and perhaps what form of credentials (certificate, username/password, etc.) are required, and perhaps even additional information such as an authentication domain, so I know which credentials to send.  Right now, there’s no standard way that I’m aware of to communicate this information.

Interface Uniformity

A while back, Jon Udell and Mark Baker were discussing addressibility and interface uniformity.  Mark said:

getSunwStockQuoteRealtime()
getIbmStockQuoteDelayed()

The problem with these is obviously that they’re not readily reusable.
They do one thing and one thing only.  So we typically generalize them
by parameterization; permitting a single method to be used for multiple
quotes, by moving identifying information away from the method name
and into the parameters.  An obvious next iteration would be;

getStockQuote( “SUNW”, “realtime” );
getStockQuote( “IBM”, “delayed” );

However, generalization doesn’t have to stop there.  We could do this;

getQuote( “Stock”, “SUNW”, “realtime” );

Which would permit other types of quotes to be retrieved, such as
insurance quotes, quotes for auto repairs, etc..

Eventually however, generalization has to end.  I suggest that this
is as far as one can go with it;

get( http://nasdaq.org/quotes/stock/realtime/sunw )

I would argue that the progression from getStockQuote to getQuote is where the usefulness of this model breaks down.  Suppose a getQuote function, which could be used a couple of ways:

getQuote(“Stock”, “SUNW”, “realtime”);
getQuote(“Insurance”, “Allstate”, “realtime”);

If you design such an interface, you’re making the assumption that a stock quote and an insurance quote have some amount of information in common.  In essense, you’re designing an inheritance hierarchy, that says you have “quotes” and they can be either “stock” or “insurance” (or others).  But how do I work with the quote once I get it?  For stock quotes, I might be interested in the current price and the day’s opening price.  For insurance, I might be interested in the premium and the deductibles.  Since you can’t generalize any “quote” into a single interface, you need to treat each kind of quote differently.  And if this is the case, did you really buy anything from being able to retrieve them all with a single mechanism? 

It seems to me you just move the specifics down a level.  You can retrieve anything the same way, but you can’t process it without knowing more specifically what it is.  And while it’s nice to have an interface that is essentially type-less (which seems like what Mark describes), it’s not as nice if the returned types can’t be coerced into something you can use.

Is WSDL too hard?

Modeling without WSDL. Mark Ericson has some thoughts on Interface design with WSDL, I agree with him, WSDL is far to cumbersome to work with by hand, the only way to be remotely productive is to use some sort of tool, personally I like Omniopera, YMMV.  [Simon Fell]

I’ve heard oh-so-many people talk about how difficult WSDL is to use, and how it’s too hard to create by hand.  Well, I don’t buy it.  Yes, it’s not exactly intuitive.  But for 95% of the WSDL one might need to create, you could create a boilerplate template and just fill it in.  When doing this, most of the work will be generating your schemas, which there are plenty of tools for (although I usually write schemas by hand).  It’s cryptic, it’s strange, and you might not understand it all at first…but it’s not all that hard.

Welcome

I’d like to extend a welcome to my good friend Sean Varley, who has just started a weblog.  Sean’s company does electronics and embedded systems engineering and consulting.

It’s interesting to read and talk about work on the fringes of what we do.  I talk to Sean a lot about software development issues, and the problems faced in embedded systems are very different than the problems we face in other kinds of software development.  Fun stuff.  And sooner or later, I just know I’m going to talk him into building something that will run the .NET compact framework.

Anyway, welcome Sean!

SoapExtensionReflector

Scott Short has an article on importing external schemas into your WSDL in the latest MSDN magazine. The text isn’t online yet, but you can download the code, which is the important part. The idea is that you can add attributes onto parameters and return values from your method. The attribute identifies a schema to associate with the parameter. I don’t think it provides validation, but that would be easy enough to add via a SoapExtension. The framework uses the semi-documented System.Web.Services.Description.SoapExtensionReflector class to modify the default WSDL generated by the .NET framework, so your WSDL contains the complete contract for the method, but internally, you’re dealing with the data as XML.  [Gordon Weakliem’s Radio Weblog]

This is super-cool.  With this code, you can create a method taking a XmlNode parameter, but have it strongly typed in your WSDL:

[WebMethod]
public int Test(
   [XmlImportedElement(“urn:test”, “test.xsd”, ElementName=”Stuff”)]
   XmlNode stuff)
{}

So on the server side, we can process the parameter as XML; and yet the contract is fully described (including schema) in the auto-generated WSDL.  Tim Ewald talked about this kind of thing at the DevCon – great stuff.

Nice job, Scott!