views:

112

answers:

1

I am using NVelocity in my application to generate html emails. My application has an event-driven model, where saving and/or updating of objects causes these emails to be sent out. Each event can trigger zero, one or multiple multiple emails.

I want to be able to configure which emails get sent out at run-time without having to modify code. I was thinking I could leverage the NVelocity #if() directive to do this. Here is my idea...

Step 1) Prior to email sending, the administrator must configure a formula for NVelocity to evaluate. For example:

$User.FirstName == "Jack"

Step 2) When an object is saved or created, build an NVelocity template in memory based on the input formula. For example:

String formula = GetFormulaFromDB(); // $User.FirstName == "Jack"
String templ = "#if( " + formula + ") 1 #else 0 #end";

Step 3) Execute the NVelocity engine in memory against the template. Check the results to see if we have to send the email:

String result = VelocityMerge(templ); // utility function 
if( result.Trim() == "1" )
{
    SendEmail();
}

I know this is not exactly what NVelocity was intended to do, but I think it just might work :) One of the benefits of doing things this way is that the same syntax can be used for the formula as is used inside the template.

Does anybody have any words of caution or suggestions? Is there a way to execute the #if() directive without jumping through hoops like I have above? Is there a recommended way to validate the formula syntax ahead of time?

Thanks.

+1  A: 

If a non-technical end-user is the one that changes the criteria, I'd be very careful to validate his input. You could easily validate it by running the template (i.e. your VelocityMerge() method) against the input, if NVelocity complains you reject the input, otherwise save it to the database.

Another limitation is that you'd have to know upfront all the variables that can be present on the criteria, as serg555 commented. Some mail template might need a variable that no other mail needs, but still you'd have to make it available to all templates. Whether this is a real limitation or not depends on the homogeneity (?) of your mail templates.

Also the end-user that defines the criteria would have to know all available variables (e.g. $User) and the properties of each variable (e.g. FirstName, LastName, etc). Some help screen that lists them, perhaps.

Mauricio Scheffer
Thanks Mauricio. I think that's a good suggestion to run the VelocityMerge() function before saving to the database. Each email is going to be tied to an object type - i.e. $User vs $Product. So each email of that same type will have the same variable names. I might make a global utility class to pass into all templates. At this point, I think I have a good start. Thanks again for the tips and for confirming the validity of my idea.FYI - I am using this post (http://stackoverflow.com/questions/568215/does-nvelocity-no-longer-support-string-templates) as a basis for doing my merge.
dana