Welcome to MSDN Blogs Sign in | Join | Help

Setting up Workflow Databases for Persistence and Tracking

Let's just say that I'm not a SQL wiz.  I like to use SQL Server Management Studio express when dealing with databases.  Unfortunately today I was trying to setup the Workflow databases on a machine where I had not installed SQL Management Studio Express yet and I had no Internet connection at the moment (after all it is a free download).

Update: Turns out that running the SQL Management Studio Express Installer in Vista results in a problem where the install fails with error 29506.
Once again Sid (one of our MVP's) had the solution to run the MSI from a command prompt with admin privileges. 

So what is a SQL lamer like me to do?  Whip out the good ol' command line tools.

To save you the trouble here is the command you need.  Assuming that you are running SQL Server Express as the named instance sqlexpress.

Create a new Database using Visual Studio 2008

  1. Start Visual Studio as Admin if on Vista
  2. Open the Server Explorer
  3. Right click on Data Connections
  4. Select Create New SQL Server Database

Run the scripts from the command prompt (yes you can run these from VS if you like)

  1. Open the Visual Studio command prompt (run as administrator if you are on Vista)
  2. CD\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN
  3. Run the following command (assumes the name of the DB is WorkflowTracking as an example)

sqlcmd -iTracking_Schema.sql -S.\sqlexpress -dWorkflowTracking -E

 

One Other Very Cool Thing I found Today

Suppose you are building a client application and you want to use workflows with persistence.  You need a database right?  Who wants to ask people to install SQL Server (even express) in addition to your app.  Of course SQL Server Compact Edition is the perfect solution.  But wait - you can't run those scripts on it because it doesn't support stored procedures!

Never fear - MVP Maurice de Beijer has created the SQL Server Compact Workflow Persistence Service and shared it with us on MSDN Code Gallery (way to go Maurice!)

Update: If you try to run this code on Vista x64 it will fail with an error "System.Data.SqlServerCe.3.5' not installed."  I puzzled over this for a while until I realized from Steve Lasker's post about SQLCE not being available on x64 yet.  It turns out that you can still use it you just have to target x86 in the build properties of your project.

Posted by ronjacobs | 1 Comments

uR 5UcH 4 n00B

I love playing computer games (probably a little too much).  Of course when you first get started you are the guy who gets killed all the time because you don't know what you are supposed to do or where the secret stash is.  After a while of playing and tips from other players you shed your "noobness" and become one of those guys who beats up on all the noobs in the game.  So what does this have to do with work?  Great question!

I can't help but think with so many new technologies that my head wants to explode that many of you, like me, feel like a total noob.  I just spent the last few months coming up to speed on Windows Workflow Foundation and Windows Communication Foundation and there were many times that I felt I should just know these things.  But there are many new concepts and techniques to learn so I struggled through reading large books until I began to get a grip.

If you feel like a noob, don't be a ashamed... Now you can do something about it.  Today I'm introducing "The Total Noobs Guide to WCF".    This is a bit of an experiment and it also marks my return to the world of podcasting.  Check it out and let me know what you think - it's only 16 minutes long. 

Noobs of the world - you can't help it.  Everyone is a noob at some point.  Just don't stay that way...

Posted by ronjacobs | 4 Comments

Locking in SqlWorkflowPersistenceService

In my previous post I was thinking about persisted workflows in a server farm and thinking about how optimistic and pessimistic locking affects the operation of workflows in a server farm.

I said that the default behavior of the SqlWorkflowPersistenceService is to use pessimistic locking.  I was partially correct.

It turns out that the default behavior varies depending upon the constructor you use.  There are three constructors for the SqlWorkflowPersistenceService class.  For the one with 4 arguments the default is to use pessimistic locking.  For the other two, one defaults to optimistic locking and the other also defaults to optimistic unless you pass the OwnershipTimeoutSeconds parameter see the docs for more info.

 

Getting this behavior right it turns out is critical.  Because persistence is often difficult to predict in a workflow (especially if you have set UnloadOnIdle==true).  If you allow more than one WorkflowRuntime to load a single instance of a Worfklow you run a high risk of the persisted state being overwritten by different running instances which can result in very strange behavior.

For example, in one test I did today I saw the following

Host 1 Host 2
Create workflow "A" which goes idle and is persisted  
  Get All Workflows - find Workflow "A"
Send a message to workflow "A" to continue processing.  Workflow goes idle  
  Sends message to complete workflow. Workflow instance is removed from the database
Sends a message to workflow "A" continue processing but workflow "A" has been removed from the database so the message cannot be delivered  

 

Given what I learned today I'd have to say that I'd be very careful about using workflows with an optimistic locking.  Detecting these types of situations is not that simple. 

 

One other tidbit.  Often people complain about not being able to predict persistence.  It is actually very easy to force a persistence point in your workflow by building a very simple custom activity.

 

Just a few lines of code and then you can drop this baby anywhere on your workflow to force a persistence point.

 

    [PersistOnClose]
    public partial class ForcePersist: Activity
    {
        public ForcePersist()
        {
            InitializeComponent();
        }
    }

 

image

Posted by ronjacobs | 1 Comments

Putting the "You" in Usability

Have you ever used a product and found it difficult at first?  Or maybe I should say, when have you not found this to be true?  Some things are just easy to pick up and use.  In fact, the best products don't even require much documentation because they are just that intuitive.  I'm happy to say that many product teams are now engaging in the discipline of usability testing and today I was the guinea pig in a usability test.

The product provides useful functionality in a library that is built on Windows Workflow (WF).  The team was recruiting experienced WF people to give feedback on the product so I signed up.  I spent about an hour and a half trying to complete a 6 step process on a product and technology that I had no background with and no idea of how to actually use it.  There were many fits and starts as I went through this process.

  1. Read the instructions of what I am supposed to do
  2. Try to guess at what activities on the tool palette might do that thing
  3. Try to guess at what the properties do and which ones I ought to set
  4. Look at the doc fruitlessly searching for help on the thing
  5. Study some sample code that was written by a pro who did the "right" thing but not the simple thing (meaning they wrote lots of code and did it in a way that no noob would do).
  6. Offer my perplexed guesses at what I should do to the team who was monitoring my test

 

Wow - what a great time eh?

Really, it was a good time.  I enjoyed taking the hit on this early product so that hopefully they will iron out the kinks and get somewhere better in the future before they unleash this product on you.  I think they were very surprised at the way I looked at the product (am I really that different?). 

When I work with some new piece of technology, I don't begin by reading the manual cover to cover (who does?) but I start my own scientific process.  I experiment, observe the results and form hypothesis about the way the thing works.  I then conduct tests to prove or disprove my hypothesis.  Sooner or later I develop a mental model of the way the thing works and after a while I find myself saying things like "Oh - that thing?  It's easy..."

How does one do a usability test?

First off you can do these at any stage of the project.  Even before any code is written you can do paper prototype testing (as I covered in this ARCast interview with Mia Northrop of seek.com.au).

Once you have some working UI and perhaps some basic help files you can construct a test.

Think about the kind of test subject you are looking for.  If you have thought much about your users you might have developed a list of "personas" that represent the kind of users you expect to have.  You will want to test with several people who represent your personas to see if they respond as you thought they would.

  1. Give them a set of small tasks with minimal instructions.
  2. Invite them to sit down at the computer and "think out loud"
  3. If they aren't saying much prompt them with questions... "What are you thinking?", "What are you looking for?"
  4. When they get stuck offer hints - "What if you tried...?", "Does the help say anything about this?"

Afterward you will find that you have a great deal of information about where people got stuck, what they were expecting and some guesses as to why they didn't find it.  At this point it may be too late to make major design changes but clear documentation and samples might help people to work around such issues.

Posted by ronjacobs | 1 Comments

Using Windows Workflow with WCF on a Load Balanced Server Farm

This morning I was in an interesting email thread with some of my Microsoft colleagues about the use of Windows Workflow Foundation (WF) on a load balanced server farm.  The question that started the whole thing was that a customer had asked their local Microsoft representative if there were any "issues" to think about when using WF on a server farm.

To be honest with you my first response was... why not use BizTalk for that?  After all BizTalk has support for enterprise scale solutions with the kind of robust management and monitoring that would likely be required for this type of solution.

And then there is the way that the SqlPersistenceProvider works (yes you can always write your own persistence provider) but my first reaction was that for short and sweet simple things it would probably be ok but for long running stuff I wouldn't do it.

But then I went for a run and couldn't stop thinking about it... So I came back and wrote down some thoughts that you might find useful.  Here they are.


After thinking a bit more deeply about this issue allow me to add some additional thoughts (this turned out to be much longer than I anticipated but hang in there and let me know if it makes sense).

Any multi-user application has concurrency issues right?

When you write your business logic you have to watch out for things like lost updates and concurrent writes, race conditions etc.

There are two basic philosophies for dealing with this. Optimistic and Pessimistic locking.

Optimistic assumes that contention over a shared resource is relatively rare and so developers assume (optimistically) that it will usually not happen. However they code defensively with things like row version identifiers to detect the rare cases when it does happen.

Pessimistic assumes that contention is likely to happen and locks a resource before attempting to work on it. Such locks typically have a lock expiration time span in the event that the locking process crashes or hangs. In the typical case the resource is locked, the work is done and the lock is released in relatively short order.

Let’s imagine a multi-step business process without using WF but instead a WCF service. Suppose you create a Service Contract like this one.

[ServiceContract]
public interface IService1
{
   [OperationContract]
   Guid DoStep1(string initialData);
   [OperationContract]
   int DoStep2(Guid processId, string additionalData);
}

This contract represents a two-step business process that you want to complete. When you invoke step 1 you are creating a business process that has state that has to be stored and will need additional work to be completed at some later point. You return an instance identifier to the client as a way to connect the second step to the business process created by the first step.

Now to get back to the original question about load balancing

Does load balancing impact this concurrency problem?

Not really, load balancing across a server farm doesn’t make this problem any better or worse. Even with a single server, multiple users can send concurrent update requests which will cause a contention over a shared resource. If the shared resource is accessible by all servers in the farm you have exactly the same problem with one server or 100 servers.

Note: The way to know if load balancing will affect your problem is to consider the use of local resources on a server (memory, files etc.) and the relationship of local state (on the one server) to shared state (available to the farm).

What happens when you start the business process with DoStep1?

When a message to DoStep1 is received by the service endpoint, it creates a new business process and returns an identifier for that process.

Design Issue #1: How to detect and deal with the issue of duplicate business processes are being created by service consumers

There is a risk that a client might inadvertently send more than one DoStep1 message for the same process. A well designed service would detect that the process (with this data) has already been created and that the second attempt is a duplicate. Does load balancing a server farm make this problem any better or worse? No.

What happens when you complete the business process with DoStep2?

Now the client is ready to complete this multi-step process by sending the DoStep2 message.

You send a message to the load balancer which selects a destination node. At this point you have a concurrency issue. What if someone else is trying to update the same business process at the same time?

The Optimistic solution would say

· This is a relatively rare occurrence

· We can detect this by using some kind of a version identifier in the data and rejecting updates destined for a version that no longer exists because another user updated it.

The Pessimistic solution would say

· I’ll try to lock the business process instance prior to updating it. If another user has it locked I will return an error

· When I lock it I will set a lock expiration time in case I crash or hang during the update in that event no other node will be able to update this business process until the lock expires

In either case, most of the time the business process will complete successfully but occasionally you will have to deal with concurrency problems that lead to failures either by being unable to lock the business process (within the timeout) or being unable to update the process because the row version has changed.

Design Issue #2: How to detect and deal with failure to complete a business process due to concurrency issues

Does load balancing affect this issue? No it is the exact same problem regardless of the number of processing nodes.

How does this scenario change with Windows Workflow?

Imagine now our contract is implemented with a workflow that looks like the following

clip_image002

How does this change things?

1. Now there is a WorkflowServiceHost that will receive the message and try to load a business process prior to delivering the message to it

2. The persistence provider is making decisions about optimistic or pessimistic concurrency and lock management

The SqlPersistenceProvider by default uses pessimistic concurrency but it doesn’t have to. You can set the lock timeout to 0 and it will assume an optimistic concurrency mode.

When you do optimistic concurrency with your workflow, you take responsibility for managing concurrency issues. For this reason it makes sense that the persistence provider will default to managing it for you pessimistically.

Now let’s think through those design challenges and ask the question “How should we deal with these issues when using WF?”

Design Issue #1: How to detect and deal with the issue of duplicate business processes are being created by service consumers

The most likely place to deal with this is in your activities that are launched after receiving the message. Just as with your WCF service you will have to design a way in your code to detect that the business process has already been created. In the event that you do detect this you will want to log the event (probably) and terminate the workflow which will cause the persistence provider to remove it from the persistence store and return an error to the client perhaps along with a reference to the workflow instance ID that is managing that business process.

How does load balancing affect this issue?

It has little or no effect on it. Yes a workflow is created in memory on a particular server but as long as the persistence store is shared across the server farm there is no real affinity with that workflow instance. The same thing would occur with a WCF service that creates an instance of a service class on a per-call basis to process the request. As soon as the workflow instance completes all scheduled activities it will go idle and will be persisted to the shared persistence store. A request destined for that workflow could be addressed by any node in the server farm as long as they are able to load the instance based on the way that the persistence provider handles concurrent requests.

Design Issue #2: How to detect and deal with failure to complete a business process due to concurrency issues

With pessimistic concurrency (the default behaviour of the SqlPersistenceProvider) the WorkflowServiceHost will call GetWorkflow which will invoke the persistence provider. When the provider detects that the instance is locked by another workflow instance (on any server in the farm) it will throw an

exception which will be returned to the client.

In the optimistic locking scenario your code will likely throw an exception when it detects that it cannot complete the operation because another user has updated the process before you did. In this case the most likely response is to abandon the request and move on.

What other options are there?

If you don’t want the client apps to have to deal with exceptions due to concurrency problems you are going to have to introduce a server side layer that can deal with them. This layer would likely accept requests from clients and immediately return some kind of identifier to them for future reference and queue the requests in a durable store of some kind (MSMQ or a database) for processing nodes to deal with. Now the server side components can implement policy on when to retry when to abandon and how to manage the results of failures when they occur.

When you think about it this is the sort of thing that BizTalk does.

So how does this affect a recommendation for using WF with long-running workflows on a server farm?

With either strategy optimistic or pessimistic locking you want to keep the work that you are doing short and sweet (and probably under the scope of a transaction). The workflow itself actually represents a series of steps that move the business process forward between persistence points.

In either case you have to deal with the (relatively rare) occurrence of concurrency problems.

Would using WF in a load balanced server farm of “Web Service Processing Nodes” make sense?

After thinking it through more I would have to say yes, it can make sense. Really you have the same problems to deal with whether or not you bring WF into the picture. You just need to understand how WF deals with them (via the persistence provider).

Whew... I hope that helps. Let me know if you think I was unclear or just plain wrong....

Posted by ronjacobs | 5 Comments

Help - My Head Is Exploding

At Tech-Ed this year I felt a new vibe from the people I talked to.  This feeling has been there before but this year it was even more pronounced.  It was the feeling that your brain just couldn't take any more.  In the past we used to come out with a new wave of stuff every 3-4 years but now with various libraries and CTP and CodePlex projects I'm being hit with "cool" new stuff nearly every day.

The problem is... I don't have time to look at all this stuff, much less figure out how to use it or what to do with it.  I'm glad people are innovating and doing cool stuff, but I just want to get my work done.  The reason I'm saying all this is that I have been contributing to the intellectual backlog in your brain.  Personally, I'd like some of your mental cycles... is that ok?

Actually, rather than just fill your head with random stuff, I want to help you get your work done quickly and correctly.  I recognize that most of you are not specialists.  You have to write everything from the web page to the SQL scripts and workflows and web services and on and on it goes.  The funny thing is that here at Microsoft most of us *are* specialists.  We focus on a product or area and try to grow very deep in that area.  We often get together with our specialist buddies and geek out going very, very deep in certain areas.  But I have the feeling that the vast majority of people who we speak with just want to get the project done.  Who can blame you?  I have a life outside of work too!

So what?

Well... I was thinking about this the other day and it seemed to me that we have been guilty of scope creep.  We asked for a portion of your brain and we just kept asking for more and more.  What we need to do is to create learning that is scoped for you.  You want to learn about web services?  Why should we ask you to plumb the depths of WCF?  Why should we expect you to ascend to the heights of REST?  Good grief!  All you want to do is create a simple web service, a syndicated feed or a LO-REST service that is read only and available to anyone on the web.

It occurred to me that this is like a video game.  I like playing video games and typically you start out with a pretty simple level, sometimes even a training level, that helps you to develop the skills you will need throughout the game.  You have some simple challenges, you acquire skills, powers and weapons that you will need to tackle the harder stuff.  Eventually you take down the big bad boss on the highest level.

Isn't that what learning all this technology should be like?

What if we had something that scoped your learning

Web Service Developer Level 1

Knows the basics of WCF (contracts, service descriptions and simple security for intranet scenarios)

Web Service Developer Level 2

Adds Web Http programming model (REST) and Syndication

Web Service Developer Level 3

Adds duplex, advanced security, etc.

Then we could create scenarios and tell you what the scope of the skills required would be kind of the way that home improvement shows rate the difficulty of home repair jobs

Scenario: Intranet SOAP Web Service - requires Web Service Developer Level 1

Scenario: Internet ATOM Syndication Feed - requires Web Service Developer Level 2

Then if you just want to get the job done, you find a scenario that maps to the job you have to do and you get an idea of the skills, concepts and techniques that you will need to know or learn to get the job done.

Now you don't need to feel like you have to read that 300 page book to get your job done (after all nobody really reads all 300 pages do they?)

Really... we can't have heads exploding around here.  It's far too messy. 

Posted by ronjacobs | 4 Comments

Modeling Change

If you have heard anything about "Oslo" (the codename for the future application platform) you have probably heard that Oslo is about 2 things, models and services.  Today I met with a group of smart guys here in Sydney where we had a chat about Models and the pain of versioning.

Everybody agrees that the only constant is change.  We know that data will change, schema will change, workflows will change, business rules will change, service contracts and data contracts will change.  We have to manage the change.

The platform infrastructure we use has semantics it applies when dealing with change.  As I mentioned in my last post, the point where the pain hits us is when new behavior encounters old state.  For example, what does the DataContract Serializer do when it encounters state that doesn't quite match up?  There are rules that it uses to deal with this.  The rules are documented but they are implicit.  You don't see them, they are not modeled but they exist never the less.

It occurred to us that if you are creating models of entities, workflows, services etc. that the modeling tool should be able to suggest a model for change.  For example, if you add an activity to a workflow.  The modeling tool can look at the delta between the previous version and your new version and suggest a model for what it will do when it encounters state from the old version.  The model could be something like, it will load the prior state and resume execution where the workflow left off when it was persisted.

Suppose you decided that this wasn't what you wanted.  What if the "change model" was itself a workflow that would execute when new behavior encountered old state?  If this were the case, you could modify this change model workflow to do what you wanted it to do. 

Suppose you are modifying a system that has 100,000 in-process workflows stored in the persistence database.  You might choose to do a batch migration process where you load them one by one and run the change model to move them forward to the new model.  Or you might choose to leave them as they are until in the course of normal processing they are loaded and then the change workflow model applies.

The meta-point is that change happens, we must deal with change, no single strategy can adequately deal with all the changes that will need to take place.  We can suggest a default, we can allow people to extend or replace the default but if we do, we ought to make the change a first class citizen of the model universe we are building.

Posted by ronjacobs | 1 Comments

Behavior Change and State

Last post I was thinking about change and how one plans for change in the life of an application.  I became particularly interested in this after hearing from customers about the pain of versioning and how little we help them with this in the platform.  One trend that makes this even more painful is the idea that the platform can manage state for your application automatically.  The prime example of this is how Windows Workflow (WF) can automatically persist a workflow.

The vast majority of applications manage their own state.  In a typical N-Tier architecture, applications have a data layer that takes on this responsibility and provides a layer of insulation against change.  If the mean old DBA decides to change the database in some way, our friend the data layer can absorb the impact of such changes without them rippling throughout the entire application.  In fact the idea of every external interaction having a layer between it and the rest of the application is such a good idea that it is often used for services as well.  On the sending side a service agent can provide a place to contain logic that is needed for invoking an external service.  On the receiving end a service facade can be used to deal with boundary issues.

There are some principles we need to keep in mind about Behavior and State when thinking about change over time.  While not absolutes, I believe these principles to be true in general

Behavior and State are linked temporarily

You create an object, it has behavior which was built at compile time.  State on the other hand is built up at runtime.  It is either collected from a user, function calls or read from a durable store.  Eventually your object has both behavior and state that is required to fulfill it's task.  For some moment in time the two state and behavior are bound together.  Your application is designed to restore the world to this moment in time at some future point as well.

State lives longer than Behavior

The business process that your object supports outlives your object in time.  The time scale of the real world is much slower than the machine.  Instead of micro or milliseconds we operate on the scale of minutes, hours, days, weeks, months.  The state that helps us get our work done is mostly kept in durable storage so we can recall it, act on it and store it again.

Behavior Changes More Often Than State (schema)

Yes, state changes, but the schema of state changes less often than behavior.  You fix a bug, you modify a business rule, these changes occur with greater frequency than changes like adding a field to a table.

Behavior Changes often require State Migration

You changed a business rule.  Does this change affect state?  Possibly.  You might need to run the business rule again on orders placed in the last week.  You added a new field, in the database this field is now blank.  You might now need to run a process that will lookup or calculate a value for this new field in order to make the record valid.

The Place of Vulnerability

If there is one place in our application where we will feel pain around versioning it is in the place where the new behavior encounters the old state.  Whenever we have code that attempts to read state we must have a plan for what to do when we face this situation.  Increasingly the trend has been to want platform infrastructure to manage this for us automatically.  The typical way this is done in the past was to serialize the state to a stream of some kind.

While this sounds great on the surface, problems occur when the new behavior encounters this old state.  Usually at this point de-serialization fails because it doesn't know what to do with this old state.  Worse yet, if you cannot manually fix up this old state or successfully migrate it to the new state format you face the possibility of loosing data.

It seems to me that at this place of vulnerability, platform infrastructure needs to be very extensible.  This ought the place where you can modify, extend or replace platform behavior.

What do you think?

Posted by ronjacobs | 2 Comments

Living through "The Change"

Funny how it happens, but things change don't they?  Our applications, as perfect as they are when brand new, grow and change over time and like teenagers, sometimes these changes are quite painful.

Over the past few weeks we have been speaking to customers about their dreams and wishes for our children (WCF and WF).  These youngsters are just toddlers really but we all have high hopes for them.  One thing we heard repeatedly and loudly from you was that you need help with versioning and some said that we put no thought at all into this.

As I thought back about my past years at Microsoft I realized that for the most part you are correct.  Even though every app will have to live through a change, we platform builders give precious little thought to how we can help you live through this.  I recall the experience of COM+ where we added a feature to disable a COM+ app to COM+ 1.5 because customers pointed out that there was no reliable way to change the dlls associated with the app without actually unplugging the network cable.  How do you build a platform and have nobody actually think of such things?

In fact, if you are building an application, you should be planning for a change as well.  It seems to me there are several types of changes that we need to consider.

Add Something New

Your app is running along just fine, working the way it should when someone asks you to add something.  None of the existing functionality will be changed, just some new "stuff" will be added to it.  This should be the easiest type of change.  It involves the following steps

  1. Build the new functionality
  2. Test new and old together to make sure nothing breaks
  3. Test the deployment in a simulated production environment
  4. Deploy application with minimal disruption to production system

Of course, the simplest way to deploy an application is to shut everything down, deploy it, and bring it back up.  My guess is that this is the most common method of deployment of applications, with the second most common being to bring one node of a production cluster at a time down while the others keep operating.

Change Something That Already Exists

Your app is running but there is a problem.  It might be a bug, or it might be some missing functionality that somebody needs.  The solution is to change the app in some way.  It might involve a simple bug fix or something as radical as a complete redesign of the internal implementation.  I am not speaking of replacing an old system which is in my view something else entirely.  This type of change is more difficult but here is what you must do.

  1. Make the change
  2. Test the change (unit or functional testing)
  3. Do integration testing with every other system that integrates with this one to insure that no previously working integration is broken
  4. If the change affects the user experience in some way, document the changes, do user testing and plan for training and increased support needs during change rollout.
  5. Create a deployment strategy and test it in a simulated production environment
  6. Deploy the application with minimal disruption

Remove Something The Already Exists

Some portion of your application functionality is going to be deprecated.  You want to remove some useless appendage of data or functionality.  Like an appendix, the easiest thing to do is to leave it alone if it isn't causing a problem.  However, if you must remove it you will need to do the following

  1. Analyze the effect of removing the thing especially with regard to historical data and reporting and user experience (are people using that thing for some purpose you are unaware of?)
  2. Remove the thing
  3. Test the app thoroughly to determine if the missing thing is going to cause a problem
  4. Do integration testing with every other system that integrates with this one to determine if the missing thing will cause an integration problem
  5. If the change affects the user experience in some way, document the changes, do user testing and plan for training and increased support needs during change rollout.
  6. Create a deployment strategy and test it in a simulated production environment
  7. Deploy the application with minimal disruption

Summary

Wow, in the process of thinking about this thing called change my thinking is evolving already.  Someone who is likely to successfully change an application will probably have the following traits

  • They have developed their application with high test coverage (TDD anyone?)
  • They have a well defined integration boundary with the app by providing integration "contracts" not only with web service endpoints but also for data integration via files or ETL type integrations.  This makes it possible for them to test the integration to determine if the integration contract is broken in some way.
  • They have a planned deployment strategy from the very beginning and are able to test it in a simulated production environment (including data)

Now some of you should be screaming at me at this point because I have neglected one very large topic.  That is the topic of state.

Applications consist of behavior and state.  If you plan only for changes to behavior but neglect to deal with changes in state you are asking for trouble.  If your application consists solely of data that lives for milliseconds and only in memory you probably don't have to worry much about this but most applications consist of state that is created, modified, reported on and archived over a long period of time.  Changes to the behavior of the code that touches this state must be considered.  I'll save that for my next post...

What do you think?

Where are your big pain points with versioning?

Posted by ronjacobs | 4 Comments

AdventureWorks REST API Version 4 updated for Architect Connections Orlando

I've added support for conditional get in client side code with WCF (this is the only working sample of this you will find anywhere).  I also fixed the code to invalidate the server cache when the collection of customers is modified in some way.

The demo code is here

The slides are here

More to come from Architect Connections

 200x200_Arch_BeThere

Posted by ronjacobs | 1 Comments

Death at the hands of the Demo gods or PowerPoint glitch? You decide....

At Tech-Ed Israel I tried a technique I got from Juval Lowy with PowerPoint for the first time.  What Juval does is he clicks on an icon of Visual Studio to start it with the correct solution already loaded.  After sitting through his class I thought that I would give this a try.  it took a little work (and help from Juval) to figure it out but here it is.

You get a picture file of the icon you want to place on your presentation.  Drop the picture on the slide but don't add a hyperlink.  I know, you thought (as I did) that the way to run a program from PowerPoint was with a hyper link.  No my friend, what you need is to add an action.

With PowerPoint 2007 you can find the action on the Insert toolbar.  Now when you have an action you will see this dialog.

image

This allows you to run a program - wohoo!  So I setup a link to a Yahoo Search that I wanted to show in my presentation.  I tested it and everything was good (or so I thought..)

The day of the presentation when I clicked the link I got nothing.  IE cannot open the page etc.  I was so flustered I thought it was the show network.  Today as I am rehearsing for the same session at DevConnections in Orlando I realized what happened.

The shortcut is supposed to be this

C:\Program Files (x86)\Internet Explorer\iexplore.exe http://search.yahooapis.com/WebSearchService/V1/webSearch?appid...

And it was that after I put it in, I tested it and it worked, but then... I saved the file as a pptx file. When I loaded it again for the session I got this link instead

C:\Program Files (x86)\Internet Explorer\iexplore.exe http:\search.yahooapis.com\WebSearchService\V1\webSearch?appid...

Aarrrgh! My link is totally screwed up. PowerPoint has replaced every "/" with "\" and after the http: changed "//" to "\".  Had I read the link more carefully in the browser I would have found the problem but instead convinced that my machine was hosed, I rebooted in the middle of my talk.

Why didn't you just use a hyperlink you ask?  Seems like that would be the right solution.  The only problem is that the hyperlink always opens behind the presentation window.

So now what?

Now I'm going to use the Hyperlink and then switch to the IE window that popped up behind my presentation.  It is a drag but better than death at the hands of the Demo gods... 
Posted by ronjacobs | 3 Comments

My first WCF REST Talk at Tech-Ed Israel

How did it go?  Well... my demos tanked a couple of times...  I had to reboot the machine.  The A/V guys kept wanting me to change resolution on the screen because it was fuzzy.  The screen was small for the room so it was hard to read the code from the back.  But other than those things I'd say it was pretty good.  Who knows how the evals will go...  Sometimes people get really tweaked by these things and take it out on you.

I found the problem with one of the demos and fixed the code.  So I've uploaded it again.  This is the link to the updated code.

Posted by ronjacobs | 2 Comments

My RESTful Client / Service Sample

I worked right up to the wire here at Tech-Ed Israel.  I have to speak in just 2 hours so I'm calling it done for now.  This sample code demonstrates a RESTful Service API over the AdventureWorks database.  The code is not something you can just download and hit F5 with.  You will need AdventureWorksLT installed and I was running the Web Site in IIS so I could get Fiddler to work with it.  But if you just want read the code here it is...

Posted by ronjacobs | 3 Comments

Building and Managing the Magic of Software - My talk in Athens with Bill Gates

Often people ask me "Have you ever met Bill Gates?"  Well, the answer is no, I have not met him.  But recently I was in Athens where I gave a keynote speech at an event there where Bill Gates was the other speaker.  If you have heard about "Oslo" the code name for our next version of the .NET platform you might enjoy seeing this video of my presentation there.

Posted by ronjacobs | 0 Comments

AdventureWorks Security and webHttp endpoint behavior

Yes... these are the two devils that kept getting in my way today.  I'm going to tell you exactly what I found out about these two things since my fruitless web searches got me nowhere but some poor soul who follows me one day may find this blog post.

AdventureWorks

Everybody knows about the Northwind database but apparently the SQL team didn't like it too much.  A few years back they came out with the AdventureWorks database (in several flavors) including a trimmed down AdventureWorksLT database for sample applications.  They did a very nice job on the design of this thing and unlike the Northwind database security is clearly in force.

I have never tried to write code with the AdventureWorks database so I tracked down the Codeplex project where you can install the SQL 2005 version of AdventureWorks.  Of course if you are installing on SQL 2008 the MSI does everything you need.  But if you install on SQL 2005 you must manually attach the database files.  Since I'm running on Windows Vista I had to run SQL Server Management Studio Express as Administrator to do this.  That worked great but then when I ran Visual Studio or my App I was getting "Access Denied" whenever I tried to connect to the AdventureWorksLT database.

Finally after a great deal of searching I found the "Walkthrough: Installing the AdventureWorks Database".  This has good instructions for granting permission to ASP.NET to use the database.  I also added my account to all the grant statements as well.  That way I can access the DB even when I'm not running VS or my app as Administrator.

Then I had a load of fun writing my first real LINQ to SQL code.  Wow - this stuff is fantastic and unlike a lot of our stuff I didn't have to read a book or take a class before I could use it.

<webHttp />

Next week I'm giving a talk on RESTful services at Tech-Ed Israel and I'm frantically working on my demo code.  There are a number of pretty simple things in WCF that support this and many of them are clearly documented.  However this one little devil, the webHttp endpoint behavior was not one of them.  Yes, it is documented here, but every sample and slide deck I looked at neglected to mention this thing. 

The samples didn't use config files because they wanted to show the use of the config free WebServiceHost.  Great, but I wanted to host my service in IIS so I can't use that (or so I thought until I found Steve Maine's blog post about the WebServiceHostFactory - beware however that the full name changed since Steve's post.  In the RTM release it is System.ServiceModel.Activation.WebServiceHostFactory).

I built my service, I decorated the interface with WebGet and UriTemplates but whenever I tried to invoke my service via the RESTful API, nothing.  It just didn't work.  Normally if WCF detects a configuration that would not be valid it blows you up (as Juval says).  In this case I wonder how the webHttpBinding can possibly work but I digress.

As the end of the day was approaching and I was just about to give up, I was reviewing the MySpace guy's implementation of REST Chess and I noticed that little tag in the app.config file.  

Wohoo! My service now works with the RESTful URI!  Now I can focus on the HttpModule to support URL re-writing tomorrow and get busy playing some games tonight.

Fighting Through It

Some days it seems that it is just one battle after another, the first time to do "x", the first time you do "y".  Each new thing is just another obstacle of learning to overcome.  Unfortunately the information you need is often just out of reach... but don't give up.  Yes, it should be easier to get this stuff done, but in the end that's why you get paid the big bucks.

See you next time...

Posted by ronjacobs | 1 Comments
More Posts Next page »
 
Page view tracker