I'm going to explain one approach to solving this problem here. The example I'm giving uses JSF and Facelets, but it can easily be adapted to any framework.
The first thing you'll need to do is add an entry to your web.xml and add the following entry:
<context-param> <param-name>APPLICATION.MODE</param-name> <param-value>$APPLICATION.MODE.VALUE$</param-value> </context-param>What this does is define an initialization parameter on the servlet context, which determines the environment we're in. The "param-value" will be "production" on your production machine, or anything else on your test machine.
The next step is to define a listener on the web application. This listener will take the initialization parameter we just defined and bind it in the application (=servlet) context, so it can be accessed in the entire web application. You'll need to edit your web.xml file again and add the following entry:
<listener> <listener-class>com.myorg.MyListener</listener-class> </listener>The code for the listener is as follows:
public class MyListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent event) { String mode = event.getServletContext().getInitParameter("APPLICATION.MODE"); event.getServletContext().setAttribute("APPLICATION.MODE", mode); } }As you can see, this class just takes the initialization parameter you defined and adds it as an attribute to the servlet context.
The next step is framework-specific. I'm using JSF with facelets, so I defined a facelet for a "buy now" PayPal button. The facelet is called "paypalButton.xhtml", and this is how it looks:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <ui:composition> <h:panelGroup rendered="#{applicationScope['APPLICATION.MODE'] == 'production'}"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post"><input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="hosted_button_id" value="#{prodButtonId}" /> <input type="image" src="https://www.paypalobjects.com/WEBSCR-640-20110429-1/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" /> <img alt="" border="0" src="https://www.paypalobjects.com/WEBSCR-640-20110429-1/en_US/i/scr/pixel.gif" width="1" height="1" /></form> </h:panelGroup> <h:panelGroup rendered="#{applicationScope['APPLICATION.MODE'] != 'production'}"> <form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post"><input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="hosted_button_id" value="#{testButtonId}" /><input type="image" src="https://www.sandbox.paypal.com/WEBSCR-640-20110401-1/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!" /> <img alt="" border="0" src="https://www.sandbox.paypal.com/WEBSCR-640-20110401-1/en_US/i/scr/pixel.gif" width="1" height="1" /></form> </h:panelGroup> </ui:composition> </html>As you can see, this facelet renders a live "buy now" button if the APPLICATION.MODE equals "production" or a sandbox "buy now" button otherwise. You can then call this facelet as follows (from another facelet):
<ui:include src="/paypalButton.xhtml"> <ui:param name="prodButtonId" value="XXX" /> <ui:param name="testButtonId" value="YYY" /> </ui:include>In my case I'm using buttons that are stored with PayPal, so the only parameter I need is the button id. If you're creating your own buttons, you can easily define different parameters for the facelet.
After performing these steps, you have a system renders a live or sandbox button based on the value of the APPLICATION.MODE parameter that you defined in your web.xml. To prevent having to modify this parameter by hand, you can have your build system fill it out. What I did was create 2 ant files: buildTest.xml and buildProd.xml. buildTest sets this parameter to "test", while buildProd sets it to "production". This way all I have to do is execute the correct ant file and I have the correct PayPal buttons for my environment!
Excellent post. Do you have any post for webfirmframework?
ReplyDelete