Monday, February 08, 2010
Some level of Reporting is very much integral to any web application now a days. Traditionally we have been writing special html page to achieve this result. This page is specially formatted to fit reporting requirements (like printer friendly view) which is achieved by mean of CSS magic. There is nothing wrong with the approach except the fact that it violates DRY [Hey, isn’t same content available in some other html page as well which is not suitable for direct printing??]
The violation of DRY comes with it’s own technical debt. Now every time you have some change to the page, you need to ensure same changes must be applied to the corresponding reporting page as well. Other issue I have with this kind of reporting pages is, they are neither very good fit as saving soft copy for later use nor they are mean to be shared easily with others.
We, at Headspring, are married to idea of least possible technical debt. Having separate print page just for the sake of formatting is something that clearly goes against our principle. For the very same reason, we opted for “HTML to PDF Conversation” approach. Hence we are not duplicating same content in two html page rather uses same html fragment on browser view as well as PDF view. Looking at available option we found “Prince” is very good fit for our requirement and hence we made Buy decision over Build and trailed Prince library for our need which in this case is ASP.NET MVC web application.
In very simple terms, Prince works as filter on response stream, intercepting browser response just before it is about to be rendered. Once html response is handed over to prince, rest magic happens inside prince which understands CSS 3 and formats your html into nice looking PDF document. Prince has very rich formatting support which includes repeating header, footer on each page and repeating caption row for table when table content span across multiple pages.
Here is solution for putting prince to work for you.
Create and HttpModule like this
1: public class PrinceModule : IHttpModule
2: {
3: public void Init(HttpApplication context)
4: {
5: context.BeginRequest += context_BeginRequest;
6: context.EndRequest += context_EndRequest;
7: }
8:
9: public void Dispose() { }
10:
11: private void context_EndRequest(object sender, EventArgs e)
12: {
13: var httpApplication = (HttpApplication)sender;
14:
15: if (IgnoreRequestForPrinceFilter(httpApplication.Request))
16: return;
17:
18: httpApplication.Response.AddHeader("Content-Type", "binary/octet-stream");
19: httpApplication.Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf;");
20: }
21:
22: private void context_BeginRequest(object sender, EventArgs e)
23: {
24: var httpApplication = (HttpApplication)sender;
25:
26: if (IgnoreRequestForPrinceFilter(httpApplication.Request))
27: return;
28:
29: httpApplication.Response.Clear();
30:
31: AttachPrinceFilter(httpApplication);
32: }
33:
34: private static bool IgnoreRequestForPrinceFilter(HttpRequest req)
35: {
36: return (req.Params["ViewAsPDF"] == null);
37: }
38:
39: private static void AttachPrinceFilter(HttpApplication httpApplication)
40: {
41: var configuration = ObjectFactory.GetInstance<IConfiguration>();
42: var path = configuration.GetPrincePath();
43: var prince = new Prince(path);
44: prince.SetBaseURL(httpApplication.Request.Url.AbsoluteUri);
45: prince.SetLog("prince.log");
46: prince.SetInsecure(true);
47:
48: httpApplication.Response.Filter = new PrinceFilter(prince, httpApplication.Response.Filter);
49: }
50: }
Next step is to register it with your web.config, under httpModule section
<httpModules>
<add type="Cuc.Jcms.UI.ViewPage.PrinceModule,Cuc.Jcms" name="PrinceModule" />
</httpModules>
Let’s look bit closely at the code snippet above. Notice two important points here
1) Module has real work to do only when request was made with parameter namely “ViewAsPdf”.
2) AttachPriceFilter method is reading prince path from configuration (which in this case is hidden behind Interface and I am using IoC to get concrete instance of it).
So once this module is hooked up with your website, all you have to do is add ViewAsPdf=1 at the end of url and see any page as PDF document. [Prince however has requirement that the source html page should be valid xHtml page. Since we are building website that is ADA, Section 508 compliance, every single page in my app is xHtml compliance. And yes we do have mechanism in place to validate this automatically. ]
Approach, I have highlighted above comes with a side benefit of supporting easy UI testing in automatic fashion. We uses WatiN/Gallio/MBUnit combination for automatic UI testing which now also includes not only generating PDF report pages but also asserting on it’s content through native WatiN library support, just like how you would do it for any other html page. After all these PDF report pages are html page only and we can get html response when we request original URL after removing “ViewAsPdf=1” .
Till next time, Code smartly…
Thursday, October 15, 2009
As the month of October proceed, 1 billion people from all around the world are busy preparing for their grand festival; The Diwali. It’s bit of misfortune for some of my friends here in America, that they have no idea about what 1 in every 6 person on the earth, is busy celebrating with. Why not to take this as opportunity to tell them about social as well as spiritual significance behind the festival? There is my 2 cents :)
Diwali, which is also known as Deepavali, is a festival of lights. These light signifies enlightenment, joy of victory of Dharma(implies as truth or good) over Adharma (implies as darkness, bad or evil). The day of festival also mark end of year as per Vikram Samvat Calendar, one of the oldest calendar in the history of man kind.(The Vikram Samvat was founded by the emperor
Vikramaditya of
Ujjain[1] following his victory over the
Sakas in 56 BC. More accurately, this calendar is 56.7 years ahead (in count) of the solar calendar).
Deepavali is Sanskrit word which means “row of light” (Deep means light and Avali means row). It teach us to drive way darkness by spreading light of knowledge. Spiritually, it is the day when Lord Ram returned to Ayodhya after completing His 14 year of exile (referred as Vanvas in Indian literature) and His victory over Ravana. Full of joy, people of Ayodhya welcomed their king by lighting rows(avali) of lamps(deep) and hence the name Deepavali. Just as we celebrate birth of oneself, Deepavali is for celebration of inner light which outshines all darkness or ignorance and awakening us to know our true nature; far far away from just physical existence.
To celebrate the occasion, people light oil lamps in and around their house and set off firecrackers. People paint and clean their homes, buy new clothes and distribute sweets to their relatives and friends. By spreading light in every corner of our premises, we try to destroy the reign of darkness, on the night of Diwali. People decorate their premises with diyas, electric bulbs and other decorative electric lighting fixtures, to make their surroundings filled with colorful light and to make it bright and beautiful. Many interesting rituals and traditions have been attached to the celebrations of Diwali. Fire crackers are burst and people enjoy wearing new clothes, on the auspicious day.
Diwali is a five-day long festival, which is celebrated with fun and fervor.
The first day of Diwali is known as 'Dhanteras' which is the thirteenth lunar day of Krishna Paksha, of the Hindu month of Kartik. Lord Dhanwantari came out of the ocean with Ayurvedic on this day for the welfare of the mankind. People renovate, decorate their houses on this day and make traditional 'Rangoli' on the entrance, to welcome Goddess Lakshmi. Lamps and candles are lit throughout the night. It is considered auspicious to buy gold and silver on this day. Many people opt for buying new utensils on this day.
The second day of Diwali is Narak Chaturdashi.Lord Krishna killed the demon Narakasur on this day to make the mankind free from his fear. It is a tradition to massage the body with oil and to bathe on this day. According to an interesting saying it is believed that those who do not bathe on this day go to the Narak (hell).
The third day is the main day of the Diwali festival.On this day, people wear new clothes and share gifts and sweets with their friends and relatives. Women prepare delicacies and whole house is illuminated with 'diyas' and candles. Fireworks and crackers are the kids' favorites on this day. This day signifies end of year.
The forth day is new year day (as per Vikram Samvat). Day starts very early for all devotees as they get ready in their new cloths, visit temple, chant to the GOD, and then wish each other “Sal Mubarak” (i.e. happy new year)
The fifth day of the diwali is Bhai Dooj, the time to honour the brother-sister relationship. On this day, sisters invite their brothers and their family to their homes and treat them with delicacies. In turn, brothers offer them with gifts and sweets. Legends have it that in the Vedic era, Lord Yamaraj (the God of death) visited his sister Yamuna on this day and blessed her with a boon that if brothers visit their sisters on this day then they will be liberated from all their sins. Since then it is a tradition that brothers visit their sisters on this day and the sisters sweeten their mouths with variety of sweets. The celebration of the Bhai Dooj marks the end of the five days long festivities of Diwali.
For the benefit of my American brothers and sisters:
US President Barack Obama has joined the this grand movement by participating in ceremonial Diwali lamp at white house. Although it was Bush era back in 2003 when Diwali celebration began at white house, Obama was the first American president who had fortunate opportunity to personally inaugurate the ceremony.
Finally, for the geeks in Austin, there is great opportunity to personally attend the celebration and thereby know more about the festival. Barsanadham temple is celebrating grand festival on this Saturday, Oct, 17th 2009 beginning at 5:00 PM. Here is the published schedule:
5:00 pm Dinner prasad
6:00 pm Temple tour (in prayer hall)
7:00 pm Temple tour (in prayer hall)
7:30 pm Temple program – State Representatives & community leaders lighting the dias ceremony, kirtan, pravachan, arti
9:00 pm Grand fireworks display
9:30 pm Ras Garba – Live garba singers: Sur Sangam of Hurst, TX
Address: Barsana Dham
(SW of Austin on FM 1826, 7 miles from Hwy 290)
400 Barsana Rd.
Austin, TX 78737
(512)288-7180
I am there along with my friends and family. Be there and be part of “The Light”.
Monday, September 28, 2009
Jack has great write up on 7 s/w waste. I couldn’t kind index page which provides easy access to all of them. With all due respect to Jack Milunsky, here is my humble try
Disclaimer:- None of above is my own creation and full credit goes to Jack for it.
Wednesday, September 23, 2009
Over this weekend, I facilitated workshop on Refactoring. My company was kind enough to host the screencast for me. Earlier I posted link for ppt and demo application download here.
If you rather prefer to watch it directly at screencast site, here is the direct link
http://www.screencast.com/t/gI7XXQMQ95S
Thanks to Jeffrey Palermo, for the big favor and editing and uploading the screencast.
Monday, September 21, 2009
We at Headspring uses Tarantino for database change management. Earlier I have blog it’s ability to skip certain script file and how to use this feature.
As per the standard Headspring practice, we develop our project in the environment that facilitate close collaboration with customer. Which implies that our customer is seating next to developer team and will test user story as and when it gets completed by development team. This unique setup enable early feedback to hone the end product. Since customers are continuously testing system, they need to maintain right set of data that represent real life scenario. While testing specific scenario, customer will enter some supplemental data and perform transactions which again ends up modifying core data. This obviates need of resetting database to known state to perform further testing.
With Tarantino, deploying your application to staging environment is automatic. (If you aren’t aware of this feature of Tarantino, go and read it from here.) Hence if can capture script (both schema and data) that represent current version of database at any given time, then later on resetting database back to known state is simply mean recreate your database from this script.
Catering to this need, I have put together utility which will generate schema and data script for given database instance (Works only with SQL Server, any version as it uses SMO library which is specific to SQL Server)
We have been using this utility for over more than month and it make our database resetting step easy enough for us to forget about that step at all.
If you are curious and have similar need, you can grab the utility from the following SVN repository. You need svn client to download it. If you haven’t got it already, get one from here.
http://svn2.xp-dev.com/svn/mdmavani-DbSnapTaker/
Sunday, September 20, 2009
On this Saturday, I facilitated workshop on Refactoring. Since many participants asked for slides and demo application, here they are
presentation and demo application is at
http://austincodecamp09.googlecode.com/svn/trunk/PruningYourLegacyCode
and the final refactored version of DbSnapTaker is at
http://svn2.xp-dev.com/svn/mdmavani-DbSnapTaker
Both of them are svn repositories so you will need svn client to check out them. If you haven’t got it already, here is one.
Friday, September 11, 2009
Fascinated about terms like unit testing and TDD? Praying to work for green field project so that you, too, can do unit testing and TDD?
If these questions sounds familiar to you then let me tell you that you are not alone. While hype of automated testing, TDD, BDD is in air, not everyone is fortunate enough to work on green field project with cutting edge tools and techniques. For years, business has invested lot of money in developing and maintain those “Legacy” system, that everyone seems to hate today. Management is not ready to invest in building new system when current system is serving the purpose. After all for years, we have been hearing “If it ain't broke, don't fix it”.
Given this destiny, what we, the developers, can do to make our life easier? What would be win-win solution out of this situation? People like Martin Fowlers, has already answered these questions in his great book “Working effectively with legacy code”. If you are interested in getting some hands on experience with those trick and don’t mind handing around with like minded people, then come to ACC Campus next to highland mall on 09/19/09. I am facilitating workshop on the topic (Big thanks to AgileAustin for giving me this opportunity).
Here is link to event detail and registering for workshop. Hurry up before all the tickets are sold.
http://agileaustinrefactoring-rss.eventbrite.com/
C U there!!!!
Thursday, July 09, 2009
One of the challenge we face while developing software is database change management. We, at Headspring, have developed NAnt task to facilitate this process and is part of tarantino library, an open source project owned and managed by Kevin Hurwitz.
I do not intent to repeat same documentation as already been posted by project team. If you want to know about it’s nut and bolt then go here.
Recently we faced little different problem related to database change management. In an attempt to preserve initial set of data that we and product owner uses to test user stories, we wanted to switch from dropping database every time and regenerating it using nhibernate export schema to update only mode.
Technically what that mean is we need to change our build process to remove “dropDatabase” and “CreateDatabase” task and instead use”Update” database. However challenge was to use the same script for managing test instance of database as well. This is the db against which all our integration tests run. We wanted all schema changes to apply on this db but no data. I.e. only create/alter/drop script and no insert or update scripts.
In an attempt to solve the issue in” simplest possible things that work” manner, I decided to use convention over configuration option and added one more attribute to the “manageSqlDatabase” task in tarantino. Originally it looked like this:
<target name="manageSqlDatabase">
<tstamp></tstamp>
<manageSqlDatabase
action="${action}"
scriptDirectory="${database.script.directory}"
database="${database.catalog}"
server="${database.server}"
integratedAuthentication="${database.integrated}"
username="${database.username}"
password="${database.password}"
/>
<if test="${action != 'Drop'}">
<echo message="Current Database Version: ${usdDatabaseVersion}" />
</if>
</target>
The newer version looks like this:
<target name="manageSqlDatabase">
<tstamp></tstamp>
<manageSqlDatabase
action="${action}"
scriptDirectory="${database.script.directory}"
database="${database.catalog}"
server="${database.server}"
integratedAuthentication="${database.integrated}"
username="${database.username}"
password="${database.password}"
skipFileNameContaining="${database.skipFileNameContaining}"
/>
<if test="${action != 'Drop'}">
<echo message="Current Database Version: ${usdDatabaseVersion}" />
</if>
</target>
As you can see, the difference is skipFileNameContaining attribute. By specifying value to this attribute, you can effectively skip execution of those sql file under Update/ExistingSchema folder for which file name contains the specified word (in case sensitive manner) .
In our case we adopted convention that
- We will never put schema change and data script in same sql file
- We will include work _Data_ as part of file name when doing data insert or update
This change is available in tarantino from revision
142 onwards from trunk
Develop smartly :)
Saturday, May 30, 2009
Tomorrow I will be presenting at AustinCodeCamp 2009. Topic is “Apply Refactoring Techniques and prune your legacy code”.
Here is the Abstract:
This is session, full of code demo to demonstrate refactoring techniques mostly influenced by Michael Feathers in his book, “Working Effectively with Legacy Code”. I would prefer to keep the session lively by mean of audience interaction while demonstrating how to approach this refactoring for practical scenarios. Session will start with discussion on the topic of dependency and will go towards the direction of how to break those dependencies and introduce testing harness for any legacy code.
I have uploaded sample app and presentation in code camp repository and you can get both from here
If you don’t want to click the line here is direct instruction to checkout the code and presentation:
//Use this command to anonymously check out the latest project source code:
# Non-members may check out a read-only working copy anonymously over HTTP.
svn checkout http://austincodecamp09.googlecode.com/svn/trunk/ austincodecamp09-read-only
See you all there
Thursday, April 23, 2009
Thanks to the setup guidance I received from my buddy and Mentor, Eric Hexter, my blog is up and running here.
My earlier feed at http://feeds2.feedburner.com/MahendraMavani has been redirected to point to this new blog. Alternatively you can also subscribe to direct feed at http://www.mahendramavani.com/blog/rss.aspx
Other part of the Website is still in planning phase so I don’t know when it would be ready but I am hoping for sooner than later.
With the site and blog running smoothly, now my personal goal is to beat Jimmy Bogard, very talented buddy of mine. (I am shooting for high, you see:) )
I am planning to record my learning experiences with exciting new tools and technology/methodology. Part of that should cover usage of productivity doubling tools like R#, OSS projects like nhibernate, tarrantino, AutoMapper, NAAK and in general topics on design pattern, object oriented programming, agile/scrum/XP methodology.
All in all, stay tuned…
-Favor Smart work over hard work