Christopher Lee

All | General | Java | Ruby
XML
20080629 Sunday June 29, 2008
When planning goes right and the customer reaps the rewards..

Preface

As a software engineer, you (hopefully) strive to design things in a such a way that they first and foremost satisfy the customer's requirements. But a close second is designing and implementing an application that can be easily understood and changed by your team or the lucky person who may inherit it down the road, say four years later..

Now, as a software engineer, I have only on one occasion seen how my choices impacted someone down the road, but down the road was the day after I left, and the knowledge transfer was sufficient enough. The inheriting developer of my application was able to get up and running and meet new requirements for the customer with my application as the base with just a few days of downtime (getting to know the language).

The Problem

However, it is being on the other end of things that I want to discuss. I recently was asked to help another project migrate their four year old application from WebLogic to the cheaper, faster (shh.. no fighting allowed), cheaper (did I say cheaper?) Tomcat.

When you get asked to do something like this, your mind goes about 200mph to thoughts of, oh no - the application was running in WebLogic, how much WebLogic is welded to the infrastructure of the application, how much EJB is involved, and will a happy hour be involved? Okay, maybe not the last one, but depending on the the answers to the first two, you may quickly start thinking about the third.

Acceptance

So I gladly take on this interesting challenge, hoping for the best, but expecting to be elbow deep in the worst possible situation. When I get on site, the developer who inherited the application, four years after its deployment, and who has been asked to migrate from WebLogic to Tomcat is only tangentially familiar with its inner-workings. I breathe a little sigh of relief in that it's good to have two fresh minds ready to tackle this problem. The other developer knows what the application is supposed to do, has some documentation from the original developer, and has a whole bunch of tools, passwords, database schemas et al ready to go for our debugging efforts.

As I start delving into the code to see how much WebLogic was able to dig its claws into the code, I am getting the impression things are so much better than they could have been. Why might you ask? Well, the original developer decided not go the proprietary route (read WEBLOGIC and EJB), and instead when with good ol' JNDI. I was thrilled! I quickly scoured through the code and verified that all the data sources were JNDI provided, and plain ol pojos and jdbc were the flavor of design. I pulled up the documentation on WebLogic JNDI setup, migrated it to Tomcat JDNI providers and that was that.

Quick Resolution

From that point forward, after spending a little more time to deal with some 2-way SSL and some customer provided infrastructure problems that I did not anticipate, I had that application deployed to development, test, and production environments in a little over a day. Something that the customer had feared would take weeks was done in less than two days. Beautiful.

Lesson Learned

So when you are coding your next application and you are juggling between ideas of how to do things, think twice about who is going to be dealing with your code later on, and the possibility that it might not get to use that super-slick couple (ok 25,000) thousand dollar application server and all of its bells and whistles. Don't throw the biggest weapon you have in your development arsenal at the problem when only a fly-swatter is needed. Explore other routes of getting the job done, cheaper, with deep roots in the open source community and hopefully the next time you or a colleague have to help migrate an old application you or they have never heard of, it'll just be so easy.


Posted by clee Jun 29 2008, 09:53:03 PM EDT
20080531 Saturday May 31, 2008
Chris's Blog Bytes - Best of both worlds: Hot and orderly deployment

The Problem:


On a project I am currently involved in, the architecture is such that 6 web applications are dependent on the same managing (JNDI populating) application. This means the dependency had to be loaded by the container before it loaded the rest of the dependent applications.
If the arbitrary loading sequence of Tomcat failed to load the manager first, then the subsequent deployments of other applications will fail. Keep in mind that the number of dependencies from this point forward will balloon from 6 to over 75 in the near future, so the size of this problem is only going to continue to grow.

Possible solutions:

  • Continue as-is, removing/undeploying all dependent applications prior to starting up the container.
  • Mock out fake dependency place-holders for the dependent applications.
  • Turn off hot deployment in Tomcat and specify each web application's context in server.xml
  • Deploy JBoss inside of Tomcat which would provide JBoss web application deployment capability.

Problems with each option:

  • Too many applications (quite possibly 75+). Imagine having to undeploy everything just to re-deploy them.
  • This is a pretty viable option, but technically it appeared to be an annoying challenge.
  • Maintaining the server.xml would be yet another annoying headache. The complexity of the entire application does not need another configuration file.
  • Possible, but getting it work right would just add another task to our ever growing backlog.

So, how'd it finally work?


Well, I ended up going down the route of defining deployment contexts in the server.xml. The directions to do this include disabling hot deployments (of course, if I'm going to tell you want to deploy, why would you hot deploy anything?). Well, that worked and the management application deployed first. Then I figured, hey, why not just enable hot deployment and keep the context definition for the management application in server.xml. Maybe then it will deploy that application first, then hot deploy the rest.

And what do you know? It worked! Now you can hot deploy like it's going out of style and don't need to worry about your JDNI management providing application being deployed second or third or 75th.

Good luck with your own Tomcat deployments. If worse comes to worst, just do what you want in the context file and it might just work!
Posted by clee May 31 2008, 03:56:45 PM EDT
20080414 Monday April 14, 2008
Add a little Velocity to the speed of those Word exports

In a few of the corporate environments I've been privileged to be a developer within, I have been exposed to the ever popular requirement of the user needing a web application screen and export it to word. If you developed solutions to this problem, you know they aren't the hardest things to get working quickly, but they are one of the more tedious things to get working in the manner the user wants. From different fonts, to formats, to inner-tables to whatever else they want, those "power" Word users know what Word can do, and they expect it from their ever popular "developers".

One of my most recent excursions into development of a Word exports had me using the iText libraries. iText libraries can be used in a few types of document rendering application situations. With respect to the most recent application, I was asked to provide both PDF and Word document exports.

iText provides a couple different document writer classes for both PDF and Word document creation, as well as a generic package for document creation. The export-type specific classes for each PDF and Word both provide different types of specific implementation options for each respective export type. For specific implementations, they are great options to go with.

Unfortunately, if you have to create both PDF and Word document export options, leveraging each specific implementation class to get those features that each specific implementation offers results in largely the same amount of functionality, through different classes to get two exports (PDF and Word) that look the same.

Now you may be thinking, why not just use the generic document builder offered from iText for each export? Well, you could do that, but you lose some implementation offerings for both PDF and Word if you go with the generic version. And in those cases where the PDF and Word exports are simple, this may be a viable option. But in my case, for reasons outside my control, the exports were complicated. And due to one specific thing the user wanted, inner tables, I didn't even have the option of using iText's RTF2Writer class because it doesn't even support inner tables.

So looking down the barrel of two different implementations of exporting (PDF and Word) and a complicated Word document, I looked at something else: Velocity.

Velocity is a template-ing engine. In short, you can give it a template (or document in my case), scattered with some Velocity Template Language (VTL), a context full of key/value pairs that will be put into the document via the VTL and voila, you have a document built of a template full of specific values based on whatever the user wanted.

But how does it work?

First off, you need a template engine. In our simple case, create a Word document and place the following text in it. But in the real world, this would be a complicated table, picture, and everything-else-Word-has-to-offer filled document that you don't want to build back from scratch in iText.

Hello World, My name is ${firstName} and I work for ${company}.

Save the document as whatever named you'd like (i.e. simplecase) and save it as a Word XML document.

Now that we have a template document

Here is a snippet of code that shows the creation of a Velocity Processor (the engine), a context (what will be put into the template to create the document), and the processing of the template into a document.

    VelocityProcessor vcp = new VelocityProcessor();
    VelocityContext vc = new VelocityContext();

    vcp.setTemplateFile("simplecase.xml");
     
    vc.put("firstName", "Chris");
    vc.put("company", "Near Infinity");

    ByteArrayInputStream bias = (ByteArrayInputStream) vcp.mergeData(vc);

Let's take a look at the code and discuss, briefly, what it does.

This block of code creates the Velocity processor and Velocity context. The processor will consume the template and the context, process the template, and output the processed document. The third line creates a Velocity context which will be used store key/value pairs of data. In the next snippet of code, you will see how this used.

     VelocityProcessor vcp = new VelocityProcessor();
     VelocityContext vc = new VelocityContext();

This block of code tells the processor (vcp) which template file to process via setTemplateFile(..). And the last two lines tell the context what to replace ${firstName} and ${company} with when processing the template file.

     vcp.setTemplateFile("simplecase.xml");
     
     vc.put("firstName", "Chris");
     vc.put("company", "Near Infinity");

This last block of code is the actual processing directive. Calling mergeData(..) on the processor, passing in the context to process with, sends the processor on its way to merging in the context to the template file. The output of this call is a byte array stream.

     ByteArrayInputStream bias = (ByteArrayInputStream) vcp.mergeData(vc);

And that's it! Now we have created a byte array stream with the new document, processed with the context. Simply write this stream out to a file and open it with Word. You will see the contents of the document are:

    Hello World, My name is Chris and I work for Near Infinity.

Now how did this benefit me in ways that iText could not? Well, in this example, even though it's pretty simple, I turned probably 10-15 lines of iText code into 6, adding in the file output code would bring it to a shade over 10. But more importantly, had this document been more complicated with tables, tables inside of tables, pictures, graphics, different fonts and the like, it could have been created inside of Word by one of your design department persons, and then given to you and retrofitted with VTL. Then, you would pass the context and template file to Velocity and voila, a Word export. And that's a lot simpler than coding hundreds of lines of iText code to create a document that, more likely not, will not be the same as the intended Word document.

Using Velocity, even if you design the Word document yourself, moves a lot of heavy lifting off to Word, instead of writing the code in iText, which in the end can save lots of time. If you, like me, had to provide PDF and Word exports, this virtually eliminates half of the code by allowing you to leverage the PDF specific implementations of iText, and not rewrite the code into a RTF or generic implementation of iText as well. And, if you don't have to write PDF implementations, all the better!

But what's the catch?

Well, the catch is editing the document after you have gone back into the XML the first time, and coded in VTL. Unfortunately, Word will strip out the VTL from your template file if you were to open it in Word to try and edit it after the fact. This means if you want to edit the file after the you have gone back in and inserted VTL, you will have to following a process similar to this:

  • Make a backup of your template file (the file with VTL in it).
  • Open the template file in Word and make your desired changes.
  • Save the template file as a new (XML Word) file, or you could just save it back to the old file because you have a back-up.

Now you have two choices. You can go back into the new file (via Word) and add the VTL back in, or you can go into the old file and retrofit back in the new changes to the Word document by working with the Word XML. When it comes to change the XML vs. adding back in the VTL, it's really going to be dependent on your situation. If you have so much VTL (loops, conditionals and variables) in your document, it may be worth it to work with the XML. If you have just variables (${}) to replace, then working inside of Word will be quicker and is obviously more desirable (especially after you see the Word XML).

Working with the XML may seem like a pain. But I would argue that programatically changing iText when people want visual changes to a Word document is just as painful, and quite frankly more difficult seeing as it's more likely than not that when dealing with complicated Word documents, using iText will force your users to make concessions based on the limits of the iText API.

Not to mention removing all that iText code from your code base is always an extra plus too!

Here are a couple resources to check out in your exploration of Word and PDF exports: Good Luck!

Posted by clee Apr 14 2008, 06:30:48 PM EDT