Sunday, 9 March 2008

Looking at the number of spam emails (approximately 3 spams for 1 good email!), something needs to make sure that the same sender does not send a different spam. To handle this, we could have an auto-bounce feature such that once a spam is marked manually for auto-bounce, the next spam from the same user results in an 'invalid email-address' or 'inbox full' kind of messages. The only issues we might face:

1.) This involves the mix-up of user-requirement with the underlying protocol!. No purists would like this.

2.) The spam-generators would start getting intelligent in sending spams - It might start using different 'from' addresses and messages against the same Inbox. If either of the email was delivered, it can safely assume that the email-id is valid. This could be resolved by letting the email-server perform auto-bounce using the same logic it uses currently for spam, rather than explicitly marking it for an 'auto-bounce'.3.) In cases of the server automatically handling it, we might loose a couple of good emails since it was identified as spam and got auto-bounced.

Can this work ? How else can I avoid that spam from reaching my email box and avoid skimming through the hundreds of spam in search of that one good-email ?

Wednesday, 5 March 2008

Dependency Injection: Dependency Injection refers to the process by which functional components ('concerns' in AOP terms) are induced into an object such that the object could use its functionalities. Say, you had a Customer Management module and one of the function it does was audit the name of all users who updated a customer record. On the simplest terms, we might have the following classes :MyBusinessObject - A base class for each the business entity classes.Customer - The business entity containing the customer details - name, DOB, Address etc. This being derived from MyBusinessObject.CustomerManager - Manages all business functions related with the customer. Say, adding customer, deleting, searching, modifying etcMySimpleAudit - A class which does the audit the various operations.

In simplest case, CustomerManager class would directly instanstiate the MySimpleAudit class and call the appropriate Audit function. All good. If we have more Audit classes , say StackTraceAudit (which audits the stack trace too..why? I dont know), ObjectStreamAudit (Audits the current state of the object) , the standard design logic would call for interfaces to separate the functionality out, in our case perhaps into an IAudit interface.

We would then make sure that all our Audit classes (MySimpleAudit, StackTraceAudit, ObjectStreamAudit) implement this interface. The only confused class is the CustomerManager class which does not know which IAudit implementing class to use. Ofcourse it could depend on a configuration entry to get the audit class name or it could just hard-code to use one of the class etc.

What if we could tell directly to the CustomerManager which audit object to use ? The crux of dependency injection is this . Injecting an object (IAudit Instance) instance into another object (CustomerManager) such that the injectee (the object that got injected! sic indeed) can use the functionality of the injected object (IAudit instance).

You could pass the instance of the injected object in three standard ways as part of the constructor , use a property or use an interface definition.

For our customer example, passing the object via a constuctor would be in the lines of :

In this case, when the CustomerManager class is instantiated, the right audit instance is passed along - eg :- new CustomerManager(new StackTraceAudit)

Stuff noted:1.) CustomerManager is not disturbed for any changes/additions to the IAudit implementation2.) Any new IAudit implementation class can be created without affecting the consuming class.3.) What is depicted is effectively an 'Inversion of Control'. The control of locating, creating of the audit class being inverted to a different object.4.) This pattern decouples the logic of - which object, from where etc out from the consumer object. Policy InjectionFor the similar scenario as above, assume you had a single Audit object consumed by CustomerManager. Now if there is a new requirement to include the functionalities of StackTrace, ObjectLogging too into the audit system, what would you do? Though there are numerous immediate solutions to get the stuff working (modify existing Audit class to call the other audits as well, create yet another master class which calls all the audit objects etc), Policy Injection calls for creating a proxy object class for the currently available Audit class. It would be this proxy class which gets used by at the CustomerManager object instead of the Audit object. The CustomerManager object might end up using a Factory pattern or a dependency injection pattern (!) to get the right proxy audit class (reread this line again till it makes sense.)

Now interestingly, what the Audit proxy object class would perform is this:1.) On the way in (when the request for audit happened) , it would call the 'Pre' step routines of all registered audit handlers (StackTrace, ObjectStream etc) in a sequence and finally call the original Audit class routines.2.) On the way back (when the request for audit is done), it might call further 'Post' step routines on each of the handlers in the reverse order.

As seen, from the point of view of the CustomerManager, it is dealing with only one object, which is the new Audit proxy object. Whenever it calls the proxy Audit class to audit, all the handlers would perform its audit (either in the pre/post routines) and finally call the original Audit object.

Monday, 3 March 2008

Creating workflows using Sharepoint DesignerIt should be noted that any workflow you create using Sharepoint Designer is effectively a sequential workflow, wherein you define the sequence of the steps to be performed. Each step being composed of actions and conditions. Any new functionality would require you to create new custom activity in VS.NET and deploy it as an action such that it could be used from within Sharepoint Designer.Some of the stuff noted in case of sharepoint designer (SD) :a.) It does not allow for coding/scripting. The best you can define are rules.b.) The association with a list/library/content type is done immediately when the workflow is first created.c.) Unlike workflows created in VS.NET, SD does not allow for modification of active workflow.

Breaking out from SDIn case the limitations of sharepoint designer gets on your head, you might want to export the workflow from sharepoint designer to VS.NET. For this :

a.) Export the workflow as an FWP from within the designer.b.) Rename .FWP to .CAB.c.) Extract the .CAB file.d.) Open the extracted .XOML, rules and other files from within VS.NET.VS.NET namespacesIn addition to the activities which WWF provides, MOSS adds onto this list by enhancing the Base Activity Library (BAL) using custom activities. These activities are available in Microsoft.Sharepoint.WorkflowActions & Microsoft.Sharepoint.Workflow.

Interaction PointsFrom a developer perspective, there are usually four points in the life of a workflow task when the end user can interact with the workflow. Effectively, its these four interaction points that can be handled/customised by the developer.

Association : When the workflow template is associated the first time with a library/document/content type.Initialization : When the workflow instance is initialized/created.Completion : When each user completes their task/step.Modification : When the workflow itself is modified.

All of the above interactions require you to create custom ASPX pages (for both WSS and MOSS). In case of MOSS, you also have the option to create these forms in InfoPath, which tends to be a lot easier to develop. The table at this blog should clear up any queries regarding which event to handle at each of the interaction points.

Developer Notes1.) Unlike a WWF workflow, the base class the sharepoint workflow is either SharePointSequentialWorkflowActivity or SharePointStateWorkflowActivity based on your workflow type (sequential or state).2.) OnWorkFloActivated needs to be first activity for a sharepoint workflow.3.) Correlation Token (we had discussed this in an earlier post) needs to be set the same for the related activities.4.) In WWF while you must have used ExternalDataExchangeAttribute , in MOSS most of the data exchange stuff is handled internally. (Is this a right assumption ?)5.) DependencyProperty makes it simpler to access workflow object properties which are available after activation.