Programming

18 February 2008

Relocating a jsp application

This post is about allowing your jsp web application to be installed in different folders.  Lets say the web application is called myapp and the domain is www.acmewebapps.com. We could have different locations for the application:

  1. The default folder: www.acmewebapps.com/myapp/index.jsp
  2. The root folder: www.acmewebnapps.com/index.jsp
  3. Custom folder: www.acmewebapps.com/myapp2/index.jsp

We can move the location of the web application by changing the "Context" entry in the tomcat servers.xml:

  1. Default: <Context docBase="myapp" path="myapp" reloadable="true"="org.eclipse.jst.j2ee.server:myapp" />
  2. Root: <Context docBase="myapp" path="" reloadable="true"="org.eclipse.jst.j2ee.server:myapp" />
  3. Custom: <Context docBase="myapp" path="myapp2" reloadable="true"="org.eclipse.jst.j2ee.server:myapp" />


The trouble is that changing the location of the application changes the references to pages within the application.  Probably the links in your application use relative references, but these can be tricky to get just right.

On the client side we might have different types of link like:

  • Css resource: <link type="text/css" href="includes/style.css">
  • Script link: <script type="text/javascript" src="includes/util.js">
  • Regular hyperlink: <a href="about.jsp>About</a>

We could also have server side includes like:

  • <jsp:include page="/includes/header.jsp">

The server side links are easy, just include a leading slash and tomcat will look for the page in the context root folder of the web application.

For client side includes add "<%=request.getContextPath()%>/" and then use the relative path in your web app. This will allow your web app to be redeployed to any folder.

Why this way? For client side links the full path is created by the web browser. If the relative url starts with a slash then it is added to the domain of the referring page.  If the relative url doesn't start with a slash then the it is added to the path of the referring page. Lets assume that we want to link to a style sheet with url:

www.acmewebapps.com/myapp/includes/style.css

For example consider these links from the page www.acmewebapps.com/myapp/index.jsp:

  • href="/includes/style.css" gives www.acmewebapps.com/includes/style.css Incorrect, missing web application folder
  • href="includes/style.css" gives www.acmewebapps.com/myapp/includes/style.css Correct

The first style without a leading slash works, since the context root of the web application is kept. But note that the second style, with the leading slash only works if the web application root is in the root of the domain - in this example the myapp folder is missing.

However, the first style also has drawbacks if referencing a page from a different subfolder, consider links from a page in the admin subfolder www.acmewebapps.com/admin/config.jsp:

  • href="includes/style.css" gives www.acmewebapps.com/myapp/admin/includes/style.css Incorrect, extra folder in path
  • href="/includes/style.css" still gives www.acmewebapps.com/includes/style.css Incorrect, missing web application folder
  • href="../includes/style.css" gives www.acmewebapps.com/myapp/includes/style.css Correct

This would work, but we have to always remember to add the correct number of ".." entries to the path.  Which means that we can't use server side include of standard 'boiler-plate' includes, such as menu.jsp, because the paths will change depending on where the server side include is used.

The way to do client side includes in a way that works anywhere is to explicitly refer to the web application context root in your server side generation of the include, as follows:

<%=request.getContextPath()%>

So that the full include for the style.css example looks like:

href="<%=request.getContextPath()%>/includes/style.css"

To recap - for server side includes, just start with a slash and use the relative path in your web app.  For client side includes add "<%=request.getContextPath()%>/" and then use the relative path in your web app. This will allow your web app to be redeployed to any folder.

02 February 2008

Productizing a software program

There's a big difference between a program that runs and a software product. In his book The Mythical Man Month Frederick Brooks claims that to go from a working program to a 'programming systems product' (something with APIs which is fully generalized, tested and documented) takes 9 times as much effort.  Brooks is discussing experiences of developing whole operating systems, my experience with medium sized systems is similar, it takes multiples of the time one would allow to just write code that works, to get it to code that is really ready for use in general situations.  There are three basic things needed to go from a working program, developed on perhaps one developers machine and perhaps even delivered to handful of customers, to a supportable, maintainable product.

Version Control Repository

This is to manage the code from multiple developers and manage the process of iteratively testing and refining the code.  CVS is open source and widely used or Microsoft source safe is a popular proprietary choice. My preference is Subversion which is essentially CVS with folder versioning.

Bug Tracking

The bugs should to recorded and always assigned to one person who is responsible for either fixing the bug, or assigning responsibility to someone else to fix.  Once the bug is resolved, responsiblity returns to the reporter to check it is resolved correctly and close the bug.  A web system like the open source Mantis is good for this.

Automated Build

Its no good compiling the code on the development machine and then delivering it.  The build process needs to check out the code from the CVS, with a given tag, and perform all the compilation from there.  There should be no manual input to this process at all. If this process occurs on the development machine you should ideally install a virtual machine, to ensure that the build is cleanly depending on just the CVS copy. You must also make sure that the build id (the CVS tag) is placed in the package so that when it is deployed on the customers machine it is identifiable.

The idea of eliminating any manual parts to the process is to make sure that a human error can't damage the build - although this may take some initial investment of effort, this will the long in the long term also save time.  This also means that if a customer reports a problem the version that they are using can also be reproduced from CVS.

More

Of course there's more, but I think these are the big three that I couldn't work without. The Joel Test lists 12 points and doesn't include anything on testing.

04 November 2007

Web APIs

With the advent of widespread broadband and good browser support for javascript, web browsers have now made the leap from static rendering of pages to hosting interactive applications. Applications like Salesforce (35000 users) or gmail now enjoy widespread usage.

Web browsers are becoming increasingly mature as a platform with the availability of development APIs.  Here are links to tutorials for some of the main APIs:

  • Amazon Web Services (from Java) - Scalable storage, queuing and backend compute via SOAP or REST, callable from multiple languages. Amazon provides not just the API, but also the scalable hardware to run the services.
  • Google APIs (javascript) - Strong focus on javascript, important features are website search and mapping. The javascript code is embedded in your pages and access the Google servers.
  • Facebook API (php) - Provides access to the facebook platform and data to allow creation of facebook apps.  The app itself is written in php and resides on your own servers.
  • Ebay APIs (from Java) - Ecommerce tools including shopping cart and search facilities implemented with SOAP, so available from multiple languages. Ebay Usage Stats 2005