powerful browser detection and custom jsp tags with geronimo · 2010-01-15 · powerful browser...

26
Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser and OS detection scheme Skill Level: Intermediate Daniel Wintschel ([email protected]) Author and developer Freelance 13 Sep 2005 Learn how to take advantage of Apache Geronimo and Jetty to create a powerful browser and open source detection scheme. In addition to the open source (OS) Geronimo application server, this tutorial shows you how to use freely available JavaScript programs to perform browser and OS detection on the client side. Section 1. Before you start This tutorial is for developers who would like to implement some form of a browser detection API into an application. You can take advantage of Geronimo as the Java™ 2 Platform, Enterprise Edition (J2EE) application server (specifically its use of Jetty as a servlet container) as well as some client-side JavaScript. You'll be developing a few separate Java-based components including a servlet filter and two custom JavaServer Pages (JSP) tags. You'll use Apache Ant as a build tool to build the .war file that you'll deploy to Geronimo, so some familiarity with Ant is handy. You should be familiar with the concepts of filters and JSP tag libraries, and feel comfortable reading Java source code. By the end of this tutorial, you should have an idea of how to develop your own basic servlet filters and JSP tag libraries, and be able to implement a robust browser detection API into a J2EE application with the Apache Geronimo application server. About this tutorial Powerful browser detection and custom JSP tags with Geronimo © Copyright IBM Corporation 1994, 2008. All rights reserved. Page 1 of 26

Upload: others

Post on 28-May-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Powerful browser detection and custom JSP tagswith GeronimoUse Geronimo and Jetty to create a browser and OS detectionscheme

Skill Level: Intermediate

Daniel Wintschel ([email protected])Author and developerFreelance

13 Sep 2005

Learn how to take advantage of Apache Geronimo and Jetty to create a powerfulbrowser and open source detection scheme. In addition to the open source (OS)Geronimo application server, this tutorial shows you how to use freely availableJavaScript programs to perform browser and OS detection on the client side.

Section 1. Before you start

This tutorial is for developers who would like to implement some form of a browserdetection API into an application. You can take advantage of Geronimo as theJava™ 2 Platform, Enterprise Edition (J2EE) application server (specifically its useof Jetty as a servlet container) as well as some client-side JavaScript. You'll bedeveloping a few separate Java-based components including a servlet filter and twocustom JavaServer Pages (JSP) tags. You'll use Apache Ant as a build tool to buildthe .war file that you'll deploy to Geronimo, so some familiarity with Ant is handy.You should be familiar with the concepts of filters and JSP tag libraries, and feelcomfortable reading Java source code.

By the end of this tutorial, you should have an idea of how to develop your own basicservlet filters and JSP tag libraries, and be able to implement a robust browserdetection API into a J2EE application with the Apache Geronimo application server.

About this tutorial

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 1 of 26

Page 2: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

The content in this tutorial may beg the question, "Why another browser detectiontool?" or "Why not use something like BrowserHawk or one of the other availableproducts on the market?" Sometimes it is better to reinvent the wheel when aproduct doesn't meet your needs or may not integrate cleanly or easily into yourapplication. In addition, many tools, including BrowserHawk, are proprietary, which isnot necessarily a bad thing; however, some developers prefer to use more opentools so they can easily adapt them to their specific needs. Geronimo is an excellentexample of this. The Apache Software Foundation wanted to provide a completelyopen source J2EE application server to fulfill a need it felt was not being met withinthe Java developer community. Its reasoning was not that there weren't any goodJ2EE application servers around; it was because Apache wanted to build up anopen source, certified J2EE server that could be supported by the Java developercommunity.

The techniques used in this tutorial are relevant not only to browser and OSdetection; the same techniques can be used for the detection of which version ofMacromedia Flash a client may have installed or which country they're located in.There are some terrific open source JavaScript programs that provide access to thisinformation, and the same technique we're applying today with browser and OSdetection can be applied using these other scripts as well.

This tutorial is structured as follows:

• Custom JSP tags -- a refresher provides a brief overview or refreshercourse about what custom JSP tags and tag libraries are and how todevelop them.

• JavaScript for browser detection outlines the reasons behind choosingJavaScript for browser detection and the role it plays within ourapplication.

• Design strategy gives you an overall understanding of how to design thissample application and of the the final build structure that you'll deploy toGeronimo.

• Server-side components details all of the server-side Java componentsand source code within the sample application and ties together howthese components interact with each other.

• JSP components and sample usage details the JSP components usedwithin the application and provides examples of how to use the customtags developed in this application.

• Trying it out allows you to compile and build the sample application fromsource and provides all the commands necessary to deploy theapplication to Geronimo and test the functionality of the application foryourself.

Prerequisites

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 2 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 3: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

This tutorial assumes that you have basic knowledge of the Java Servlet API and theJava programming language. Some knowledge of JavaScript won't hurt either.

System requirements

To run the example code in this tutorial, you need to perform the following steps:

1. Download and install the following applications:

• Geronimo Milestone 4 or later.

• Apache ANT 1.6.5.

• J2SE 1.4.2_09.

2. Make sure that the environment variables outlined in Table 1 are definedin your shell.Table 1. Setting the environmental variables

Variable name Required setting

GERONIMO_HOME Set to the root folder of yourGeronimo installation

ANT_HOME Set to the root folder of your Antinstallation

JAVA_HOME Set to the root folder of your Javainstallation

PROJECT_HOME Set to the root folder of yourBrowserDetection application

PATH Ensure that ANT_HOME/bin is inyour PATH

3. Extract the supplied .zip file to your preferred location (this will be theproject root). The project is laid out as follows:Listing 1. Project layout

/BrowserDetect//conf/ ' contains taglib definition/deploy/ ' created by ANT (will contain WAR file)/src/ ' contains Java source code/web/ ' contains JSP, JavaScript and web.xml/build.xml ' ANT build file

If you are eager to compile and run the application, jump to the Trying it out section.

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 3 of 26

Page 4: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Section 2. Custom JSP tags -- a refresher

This section provides an overview or refresher on what a custom JSP tag is and whyyou might want to develop your own JSP tags.

Tag libraries: What and why?

Tag libraries and custom JSP tags were introduced into the JSP specification atVersion 1.1. In technical terms, the purpose of a custom tag is to create and accessprogramming objects that are used to affect the output stream that is being sentback to the user's browser. Custom tags can also help break your JSP pages downinto small components, allowing easier customization of the presentation layer.Some other examples of tasks that a custom tag may perform include flow control,form processing, accessing databases, and sending e-mail. The tag we'll look atrelates closest to a tag that performs some type of flow control, displaying one set ofdata on a browser and another set of data on a different browser.

Geronimo fits into this picture as the J2EE server that runs Jetty. Jetty is the servletcontainer that performs the execution of the custom tags you write.

Tag libraries: How?

Here's a brief description of the steps involved in creating and deploying a tag librarywithin an application. At the most basic level, you need to write a Java class thatextends javax.servlet.jsp.tagext.TagSupport orjavax.servlet.jsp.tagext.BodyTagSupport. These classes are part of thestandard servlet API and come bundled with Geronimo. Following this, write a TagLibrary Definition (TLD) file that describes to the servlet container the name of yourcustom tags, what attributes they have, and whether those attributes are mandatory.After you've created the necessary Java classes and TLD files, you're ready tobundle the tag with your application and deploy it to your application server.

In this application, the class files and TLD files that make up your tags are bundledwithin a .jar (Java ARchive) file. The .jar file is deployed with your application andcontained inside the application .war (Web ARchive) file.

Although this is a high-level overview of the process of developing custom tags, laterin the tutorial you'll see specific examples outlining Java classes that make up acustom JSP tag. You'll also see the accompanying TLD file and the structure of theWeb application that you'll deploy to Geronimo.

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 4 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 5: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Section 3. JavaScript for browser detection

This section describes why JavaScript was chosen for browser detection andoutlines other potential uses for JavaScript-based detection mechanisms.

Why JavaScript?

So why use JavaScript for browser detection instead of the user-agent string that thebrowser sends to the server with each request? In JavaScript you can detect manyadditional things that could be useful on the server side, including screen height andwidth, browser plug-ins that are installed (for example, QuickTime, Flash,Shockwave, and Java Plug-in), and the versions of all the plug-ins. This informationcan be beneficial (and sometimes necessary) to have access to the server sidewhen preparing to deliver content to a user.

The role of JavaScript in the application

Within the browser detection application, JavaScript plays a simple but importantrole. The application includes a JSP with some embedded JavaScript that analyzesdata about the user's browser and operating system. You'll have the JavaScriptassign these values to hidden HTML form fields and submit the form to the server.

The following sections describe the server-side components and how the client-sideand server-side pieces fit together.

Section 4. Design strategy

This section describes the overall design strategy for the application. Learn how theapplication is designed, and learn about the build structure of the application to giveyou a better idea of how the components work together.

Application design

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 5 of 26

Page 6: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

The example browser detection application provides browser detection functionalityto the developer, allowing the delivery of dynamic content based on the client'sbrowser. The basic request flow within the application is as follows:

1. User arrives at the Web site.

• Use a javax.servlet.Filter implementation to check the user'sHttpSession to see if it has detected the browser information.

• If yes, then forward the request to the view.

• If no, then redirect to a browser detection JSP page.

2. At the browser detection JSP page, execute the necessary JavaScript todetermine browser information.

3. Store the detected browser information in hidden form fields, and useJavaScript to automatically post the form data back to the server.

4. The same filter handles the newly submitted browser information, stores itin the user's session, and forwards the user to the page they originallyrequested.

There are probably 500 different ways to implement this scenario into a Web-basedapplication, so feel free to adapt the example to suit your needs.

Application deployment

Because you want to deploy a Web application to Geronimo, and because theapplication does not contain any Enterprise JavaBeans (EJB) components, theapplication is deployed as a .war file. Use Ant to build the .war file using thestructure shown in Listing 2.

Listing 2. Directory structure for the .war file

browserdetection.war//detect.jsp/index.jsp/index2.jsp/js/browser_detection.js/WEB-INF/web.xml/WEB-INF/lib/browserdetection.jar

The browserdetection.jar file contains server-side components, including customJSP tags and other Java objects, as well as the TLD file describing the custom tags.It's structured as shown in Listing 3.

Listing 3. Directory structure for the browserdetection.jar file

browserdetection.jar//META-INF/taglib.tldnet/humandoing/browserdetect/BrowserDetectFilter.classnet/humandoing/browserdetect/BrowserInfo.class

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 6 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 7: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

net/humandoing/browserdetect/BrowserInfoFactory.classnet/humandoing/browserdetect/BrowserParentTag.classnet/humandoing/browserdetect/BrowserTag.class

By placing the taglib.tld file in this location, Geronimo automatically understands thatyou want to have these tag library definitions available within the application, so youdon't have to define the tag library in the web.xml file.

The next section highlights each of the server-side components, their source code,and how they interact within the application as a whole.

Section 5. Server-side components

Let's examine the server-side components that are used within the application andhow they integrate with each other to capture values from the client, transport themto the server, and associate those values with a specific user. Then you'll see how touse these captured values within a JSP page to deliver content based on the user'sbrowser and/or operating system. At a high level, here is a list of the server-sidecomponents that exist within the application:

• Bean class (BrowserInfo), a Plain Old Java Object (POJO) thatprovides information to the caller about the user's browser information.

• Factory class (BrowserInfoFactory) that creates and populatesBrowserInfo objects based on parameters it extracts from the currentexecuting HttpServletRequest.

• Filter class (BrowserDetectFilter), which is responsible forintercepting requests to the application's JSP pages to ensure that you'vestored in the user's session an object instance that represents informationabout the user's browser.

• Tag classes that consist of a parent tag (BrowserParentTag) that donothing except encapsulate one or more child tags (BrowserTag).

Bean class

The code in Listing 4 (which is greatly abridged because all the source code isavailable in the Download section) is a POJO that is used to store Boolean valuesabout a specific user's browser.

Listing 4. BrowserInfo.java class

package net.humandoing.browserdetect;

import javax.servlet.http.HttpSession;

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 7 of 26

Page 8: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

/*** A class that represents a given users browser or user-agent* for a given session.*/public class BrowserInfo {

private boolean isIE = false;private boolean isIE4 = false;private boolean isIE5 = false;private boolean isIE5x = false;

...

public BrowserInfo( boolean IE, boolean IE4, boolean IE5,boolean IE5x, boolean IE5Mac, boolean

IE5xWin,boolean IE6, boolean IE7, boolean

netscape4,boolean mozilla, boolean konqueror,boolean safari, boolean opera, boolean

opera4,boolean opera5, boolean opera6,boolean opera7, String browserName,String browserFullVersion, boolean

windows,boolean mac, boolean linux ) {

isIE = IE;isIE4 = IE4;isIE5 = IE5;isIE5x = IE5x;

...

}

/*** Utility method to grab the BrowserInfo object from a users* session, if one exists.*/

public static BrowserInfo getBrowserInfoFromSession(HttpSession session ) {

if ( session != null ) {BrowserInfo out = (BrowserInfo) session.getAttribute(

BrowserDetectFilter.BROWSER_INFO );return out;

} else {return null;

}}

public boolean isIE() {return isIE;

}

public boolean isIE4() {return isIE4;

}

public boolean isIE5() {return isIE5;

}

public boolean isIE5x() {return isIE5x;

}

...

public String toString() {StringBuffer buffer = new StringBuffer();buffer.append( "[Browser Name: " + getBrowserName() + "]\n"

);buffer.append(

"[Browser Version: " + getBrowserFullVersion() +

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 8 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 9: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

"]\n" );buffer.append( "[Is Linux? " + isLinux + "]\n" );buffer.append( "[Is Windows? " + isWindows + "]\n" );buffer.append( "[Is Mac? " + isMac + "]\n" );

buffer.append( "[Is IE? " + isIE + "]\n" );buffer.append( "[Is Opera? " + isOpera + "]\n" );buffer.append( "[Is Mozilla? " + isMozilla + "]\n" );buffer.append( "[Is Netscape4? " + isNetscape4 + "]\n" );// ... etc.return buffer.toString();

}}

In this listing, a simple bean class stores data about a specific user's browser andoperating system. Within the example application, instances of this class are onlyconstructed from the BrowserInfoFactory class and, subsequently, the instanceis stored in a user's session for use by the rest of the application.

Factory class

A factory class has the sole purpose of instantiating new objects and returning thenew object instance to the caller. In the example application, you use a factory classto create instances of the BrowserInfo class. The BrowserInfoFactory, asshown in Listing 5, extracts information from the currently executingHttpServletRequest and uses these values to construct and return a populatedBrowserInfo instance to the caller.

Listing 5. The BrowserInfoFactory.java class

package net.humandoing.browserdetect;

import javax.servlet.http.HttpServletRequest;import java.util.Enumeration;

/*** This class is strictly a factory class that is responsiblefor* parsing posted JavaScript variables from a ServletRequest,and* constructing a BrowserInfo object from the resultingextracted* variables.*/public class BrowserInfoFactory {

private static final boolean DEBUG = false;

private static final String BROWSER_NAME_PARAM = "brow";private static final String MOZILLA_BROWSER_NAME_PARAM =

"moz_brow";

private static final String BROWSER_VERSION_PARAM = "nu";private static final String MOZILLA_BROWSER_VERSION_PARAM =

"moz_brow_nu_sub";

private static final String IS_IE_PARAM = "ie";private static final String IS_IE4_PARAM = "ie4";private static final String IS_IE5_PARAM = "ie5";private static final String IS_IE5X_PARAM = "ie5x";

...

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 9 of 26

Page 10: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

/*** Private constructor - this is a factory for creating

BrowserInfo* instances only.*/

private BrowserInfoFactory() {}

/*** Factory method to instantiate and populate a BrowserInfo* instance for a given request.*/

public static BrowserInfo createBrowserInfo(HttpServletRequest request ) {

if ( DEBUG ) {dumpRequest( request );

}

// Check browser family...boolean isIE = Boolean.valueOf(

request.getParameter( IS_IE_PARAM ) ).booleanValue();

boolean isNS4 = Boolean.valueOf(request.getParameter( IS_NS4_PARAM ) ).booleanValue();

boolean isMozilla = Boolean.valueOf(request.getParameter( IS_MOZILLA_PARAM ) ).booleanValue();

boolean isOpera = Boolean.valueOf(request.getParameter( IS_OPERA_PARAM ) ).booleanValue();

//Check specific browser versions...boolean isIE4 = Boolean.valueOf(

request.getParameter( IS_IE4_PARAM ) ).booleanValue();

boolean isIE5 = Boolean.valueOf(request.getParameter( IS_IE5_PARAM ) ).booleanValue();

boolean isIE5x = Boolean.valueOf(request.getParameter( IS_IE5X_PARAM ) ).booleanValue();

...

return new BrowserInfo( isIE, isIE4, isIE5, isIE5x,isIE5Mac,

isIE5Win, isIE6, isIE7, isNS4, isMozilla,isKonqueror,

isSafari, isOpera, isOpera4, isOpera5, isOpera6,isOpera7,

browserName, browserFullVersion, isWindows, isMac,isLinux );

}

...

}

The BrowserInfoFactory class demonstrates how useful a factory can be fordoing work that is tedious, repetitive, and a bit unrefined. For the sake of simplicity,no error handling has been added to this class (such as checking null conditions).But in a real-world scenario, this class would contain more logic. Now we'll move onto one of the most important components in this sample application.

Filter class

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 10 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 11: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

The code in Listing 6 is a standard and simple implementation ofjavax.servlet.Filter (with some of the interface methods cut out to savespace). This class is configured to intercept all requests made to Geronimo for JSPpages and performs some processing to see if you have already been able to detectand store the current user's browser information in the session.

Listing 6. The BrowserDetectFilter.java class

import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;

/*** This filter is configured to capture all .jsp requests and* then checks to see if the session attached to the current* request contains an instance of a BrowserInfo object. If* not, it does some redirecting and captures some browser* information from the client, stores it in their session, and* subsequently redirects them to the page they initially* requested.*/public class BrowserDetectFilter implements Filter {

/*** True/false depending on whether or not you want the debug* logging messages to get printed to the console based on* the UBER-simple logging method found below.*/

private static final boolean DEBUG = false;

/*** String used as a Key for the key-value pairing to store

the* BrowserInfo object in the users session.*/

public static final String BROWSER_INFO ="__Browser__Info__";

public void init( FilterConfig filterConfig )throws ServletException {

//initialize stuff here...}

/*** Perform the appropriate filter action. If there is no

browser* info, stop the filter-chain and redirect to a page that

will do* some browser detection.*/

public void doFilter( ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain ) throws

IOException,ServletException {

HttpServletRequest request = (HttpServletRequest)servletRequest;

HttpServletResponse response =(HttpServletResponse) servletResponse;

HttpSession session = request.getSession();String requestURI = request.getRequestURI();if ( session.getAttribute( BROWSER_INFO ) != null ) {//carry on - nothing to see here...filterChain.doFilter( servletRequest, servletResponse );

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 11 of 26

Page 12: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

} else if (requestURI.equals("/browserdetection/BrowserDetect") ) {

//we just finished doing the detection and we're gettingthe

//results posted from the JavaScript, do something aboutit,

//and pass the user on to the previous page theyrequested.

BrowserInfo browserInfo =BrowserInfoFactory.createBrowserInfo(

request );session.setAttribute( BROWSER_INFO, browserInfo );request.getRequestDispatcher(

request.getParameter( "requested_page" ) ).forward( request, response );

} else {//no browser info was found - forward the client to our

detection//jsp page for some browser detection action.request.setAttribute( "RequestURI",

requestURI.substring(request.getContextPath().length() ) );

request.getRequestDispatcher( "/detect.jsp" ).forward(servletRequest, servletResponse );

}}

public void destroy() {//destroy stuff here...

}}

Listing 6 is slightly abridged to show only the portions relevant to the browserdetection application. In a real-world scenario, you wouldn't have hard-coded stringsin this class, and you would do a little more error checking (especially for nullconditions). The main action in this listing takes place in the doFilter method.You've retrieved a reference to the user's session object to see if there is aninstance of the BrowserInfo object in the session. If the BrowserInfo objectexists, then you know that browser detection has already taken place, and you cansimply carry on the filter chain. The other two conditions in the if/else statementare indicative of the following scenarios:

1. Browser detection has just finished executing, and now you need toextract the browser information from the current request.

2. There is no browser information at all.

In the first scenario, the request Uniform Resource Identifier (URI) is checked toensure that it's equal to a certain string("/browserdetection/BrowserDetect"). This URI is checked because thedetect.jsp page (covered next) posts an HTML form to that URI after it has executedthe script used for browser detection. So you know (unless a user keyed in that URImanually) that if you get a request to that specific URI, you have some browserinformation you can parse out of the request. At this point you can also see how theBrowserInfo and BrowserInfoFactory classes fit into this part of theapplication. In this listing, the BrowserInfoFactory is used to create theBrowserInfo object, and then the filter class inserts the newly created instanceinto the current user's HttpSession.

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 12 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 13: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

In the second scenario, you need to get the browser information somehow, so youforward the user to the detect.jsp page. This page contains the HTML andJavaScript responsible for performing the browser detection and posts a form backto the server.

Custom tag classes

The following two listings are the custom JSP tag classes created and used withinthe browser detection application. The class outlined below in Listing 7 is simply theparent tag class. The only responsibility it has is ensuring that all uses of theBrowserTag class are wrapped within a BrowserParentTag class.

Listing 7. The BrowserParentTag.java class

package net.humandoing.browserdetect;

import javax.servlet.jsp.tagext.TagSupport;

/*** A parent tag for the BrowserTag (Can have multiple* nested BrowserTag instances). Nothing exciting to* note here.*/public class BrowserParentTag extends TagSupport {

public int doStartTag() {return EVAL_BODY_INCLUDE;

}

public int doEndTag() {return EVAL_PAGE;

}

Listing 8 is another important part of the browser detection application being built.

Listing 8. BrowserTag.java class -- section one

package net.humandoing.browserdetect;

import javax.servlet.jsp.JspException;import javax.servlet.jsp.tagext.BodyTagSupport;import java.lang.reflect.Method;

/*** This tag is used to evaluate a body for a browser version or* combination as required by set tag attributes.** @author Daniel Wintschel*/public class BrowserTag extends BodyTagSupport {

/*** This is the value that the JSP programmer can use when

they wish* to have a "default" value to appear if none of the other

values* used in the set of BrowserDetect tags evaluates to true.*/

private static final String DEFAULT = "default";

/*** The parent tag - nothing exciting here.*/

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 13 of 26

Page 14: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

private BrowserParentTag parent = null;

/*** The attribute we need to check from the BrowserDetect JSP

tag.*/

private String check;

public String getCheck() {return check;

}

public void setCheck( String check ) {this.check = check;

}

Listing 8 shows the first few lines from the BrowserDetectTag. Note that the tag'ssingle attribute is named check, and its value is set in any JSP page that this tag isused. Valid values of the check attribute include any public method names withinthe BrowserInfo class that return a Boolean value (that is, isIE, isLinux, and soon). An additional valid value for the check attribute is default. This value may beused as a default value if the BrowserInfo instance doesn't exist within the user'ssession. In our application, the value default doesn't act as a final else or a finaldefault as you would find in a switch statement. However this functionality couldbe added to the tag without much difficulty, as shown in Listing 9.

Listing 9. BrowserTag.java class -- section two

public int doStartTag() throws JspException{doParentCheck();BrowserInfo browserInfo = (BrowserInfo)

pageContext.getSession().getAttribute( BrowserDetectFilter.BROWSER_INFO );

This ensures that this BrowserTag is embedded within a BrowserParentTag. Ifnot, an exception is thrown. The next piece of code pulls the BrowserInfo objectout of the user's session (if it exists).

The BrowserInfo object

Listing 10 contains the portion of the implementation that writes data back to theclient's browser based on whether or not certain expressions evaluate to true. Hereyou can see if the BrowserInfo object exists or not; if it doesn't exist, and the userhas specified default as the check value, write the data nested in this JSP tag tothe output stream. If, however, you do have the BrowserInfo object, things areslightly more interesting. In this case, use reflection to get a reference to the methodname in the BrowserInfo class that corresponds to the value of the checkattribute, and execute that method against the BrowserInfo object. If the valuereturned is true, then it writes the content within that tag to the output stream. If thevalue is false, the content is ignored. Let's take a look at the code.

Listing 10. BrowserTag.java class -- section three

if ( browserInfo == null && check != null

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 14 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 15: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

&& check.equals(DEFAULT ) ) {

return EVAL_BODY_INCLUDE;} else {try {

Method method = browserInfo.getClass().getMethod( check,null );

Object result = method.invoke( browserInfo, null );if ( result != null && result instanceof Boolean ) {Boolean evaluate = (Boolean) result;if ( evaluate.booleanValue() ) {

return EVAL_BODY_INCLUDE;} else {

return SKIP_BODY;}

} else {throw new JspException(

"You have chosen a value for the 'check' " +"attribute that does not correspond to an " +"available attribute in the BrowserInfo class" );

}} catch ( NoSuchMethodException e ) {

throw new JspException("You have chosen a value for the 'check' attribute

" +"that does not correspond to an available " +"attribute in the BrowserInfo class" );

} catch ( Exception e ) {e.printStackTrace();throw new JspException(

"Something bad definitely happened... Try some " +"better exception handling next time." );

}}

The code in Listing 10 decides whether the data embedded in the JSP page in thebody of the BrowserTag is either written back to the user or discarded until a userwith the appropriate browser comes along. The final variables that you reference inthe tag are entitled EVAL_BODY_INCLUDE and SKIP_BODY. These constantvariables are declared in the superclassjavax.servlet.jsp.tagext.BodyTagSupport. EVAL_BODY_INCLUDEmeans to write the contents contained in the body of this tag back to the outputstream, while SKIP_BODY means to skip the contents in the body of this tag.

Section 6. JSP components and sample usage

This section briefly outlines the JSP components within the application and providestwo examples of sample usage of the custom tags you've developed.

Detection JSP -- JavaScript

The only real JSP component to worry about is the detect.jsp page. The other JSPcomponents are just simple examples of how to use the BrowserTag. Thedetect.jsp page is the page that the BrowserDetectFilter forwards to whenthere is no BrowserInfo object associated with the current user's session.

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 15 of 26

Page 16: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Listing 11. The detect.jsp page

<%String originallyRequestedPage =

(String) request.getAttribute( "RequestURI");%><html><head><title>Detecting Browser Information...</title></head><body>

<form name="detect" method="post" action="BrowserDetect"><input type="hidden" name="brow" value="" /><input type="hidden" name="moz_brow" value="" /><input type="hidden" name="nu" value="" />... // more hidden form field...... // omitted for the sake of brevity...

</form>

<script type="text/javascript" language="JavaScript">

<%--Include our open source browser detection javascript

Credit given to Harald Hope and Tapio Markula

JavaScript from below is taken from the filebrowser_detection.jswhich is included in this project and is released under the GNULGPL.

http://techpatterns.com/http://techpatterns.com/downloads/javascript_browser_detection.php

Lesser GPL license text:http://www.gnu.org/licenses/lgpl.txt--%>

//initialization, browserInfo, os detectionvar d, dom, nu='', brow='', ie, ie4, ie5, ie5x, ie6,

ie7;... // lots more variable declarations...... // omitted for the sake of brevity...

d=document;n=navigator;nav=n.appVersion;nan=n.appName;nua=n.userAgent;old=(nav.substring(0,1)<4);mac=(nav.indexOf('Mac')!=-1);win=( ( (nav.indexOf('Win')!=-1) ||

(nav.indexOf('NT')!=-1) ) && !mac)?true:false;lin=(nua.indexOf('Linux')!=-1);

...// lots more variable assignments and browsertesting...

... // omitted for the sake of brevity...

document.detect.requested_page.value ='<%=originallyRequestedPage%>';

document.detect.brow.value = brow;document.detect.moz_brow.value = moz_brow;document.detect.nu.value = nu;document.detect.moz_brow_nu_sub.value =

moz_brow_nu_sub;

... // lots more assignments that assign values to

... // hidden form field elements...

... // omitted for the sake of brevity...document.detect.submit();

//--></script>

</body></html>

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 16 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 17: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Listing 11 contains HTML, JavaScript, and Java snippets that can be found indetect.jsp. The page executes line by line and:

1. Prints out an HTML form with hidden form fields.

2. Declares JavaScript variables.

3. Uses the functions and abilities given by JavaScript to assign values tothe declared variables that are indicative of the browser name, browserversion, and operating system with which the user is making this request.

4. Assigns the detected values to the hidden form field elements.

5. Submits the HTML form back to the server automatically.

The action of the HTML form is BrowserDetect, and given the application context,it translates into "/browserdetection/BrowserDetect". This works in theexample application because there are no subdirectories within its context.

Sample usage

Listing 12 and Listing 13 show simple JSP pages that act as the entry point to theapplication and examples of how to use the custom JSP tags created in this tutorial.

Listing 12. The index.jsp page

<%@ tagliburi="/WEB-INF/lib/browserdetection.jar" prefix="bd" %><html><head><title>Browser Detection Test</title></head><body>This is a basic server-side check of the browser usingsession-persisted valuesthat were previously determined from an open-source JavaScript.

<br><br>

<bd:Browser><bd:BrowserDetect check="isIE">Look Ma!!! I'm Internet Explorer... Woof!</bd:BrowserDetect><bd:BrowserDetect check="isMozilla">Look Ma!!! I'm some kinda Mozilla Browser... Yum!</bd:BrowserDetect>

</bd:Browser>

<br><br>

Let's see what else:

<a href="index2.jsp">Check OS</a>

</body></html>

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 17 of 26

Page 18: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Listing 12 is the entry page -- or index page -- of the application. This is a simpleexample of your final BrowserTag in action. If the user's browser is Microsoft®Internet Explorer, then the application prints Look Ma!!! I'm InternetExplorer... Woof!. If the browser is Mozilla, then Look Ma!!! I'm somekinda Mozilla Browser... Yum! prints. It's worth noting again that theexample application does not provide an else function. For example, if the user isnot using Internet Explorer or Mozilla, then no output is displayed. To achieve this,you need to add a little more functionality to the BrowserTag.

Listing 13 is similar to index.jsp, but demonstrates how to achieve operatingsystem-specific content as opposed to browser-specific content.

Listing 13. The index2.jsp page

<%@ tagliburi="/WEB-INF/lib/browserdetection.jar" prefix="bd" %><html><head><title>Browser Detection Test</title></head><body>This is a server-side check of the operating system usingsession-persisted valuesthat were previously determined from an open-source JavaScript.

<br><br>

<bd:Browser><bd:BrowserDetect check="isWindows">I'm running on Windows</bd:BrowserDetect><bd:BrowserDetect check="isLinux">Linux is us, and we're you're friend</bd:BrowserDetect><bd:BrowserDetect check="isMac">Mac - what else can we say? Yum!</bd:BrowserDetect>

</bd:Browser>

</body></html>

Section 7. Trying it out

Now you're ready to build and run the example application.

Building and running the application

To build the application, make sure you've downloaded and installed the appropriateapplications and set the appropriate environment variables, as detailed in thePrerequisites section. Open a shell, and execute the following commands:

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 18 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 19: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

% cd %PROJECT_HOME%

% ant build-deployment-war

The above command runs the Ant build file (included in the attached resources asbuild.xml) and executes the build-deployment-war target. This compiles all thesource code from the tutorial and bundles it into the .jar and .war files in theappropriate format as covered in the Application deployment section.

The following command starts Geronimo, the application server.

% java -jar "%GERONIMO_HOME%\bin\server.jar"

The following command deploys the browser detection application to make itaccessible for use.

% java -jar "%GERONIMO_HOME%\bin\deployer.jar" deploy"%PROJECT_HOME%\deploy\browserdetection.war"

After you type the last command, you're prompted for a user name and password tobe able to deploy the application to Geronimo. Enter the default user name issystem and the default password manager.

Reference environment variables as %ENV_VAR% on Microsoft Windows and as$ENV_VAR on Linux®, UNIX, and Mac OS X.

Provided you have executed the above steps successfully, you should now be ableto open a browser up and test the application at the following URL:

http://localhost:8080/browserdetection/index.jsp

This example only works with Internet Explorer- and Mozilla-based browsers, butyou can easily extend the code to deal with other browsers, including Safari andOpera. See how the examples in Figure 1 and Figure 2 differ based on the browserused. Figure 2 shows an example of providing the user with operatingsystem-specific content.

Figure 1. Firefox browser accessing index.jsp

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 19 of 26

Page 20: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Figure 2. Firefox browser accessing index2.jsp

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 20 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 21: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

To test the functionality of the application, try accessing the page using a differentbrowser. See Figure 3 for the result when using Internet Explorer to access theapplication instead.

Figure 3. Internet Explorer browser accessing index.jsp

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 21 of 26

Page 22: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Section 8. Summary

This tutorial takes advantage of Geronimo's support for servlet filters and customJSP tag libraries to demonstrate one way in which browser detection can beintegrated into a Web-based Java/J2EE application. This manner of integrationmakes the detected information easily available to Java code executing on theserver. In addition, you've implemented a custom JSP tag library that allows JSPdevelopers to provide browser- or operating system-specific content to clients andend users. In no way has this been an exhaustive look at the subject, but simply oneof many ways to implement a robust browser detection API into a J2EE applicationwith open source tools, such as the Apache Geronimo application server.

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 22 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 23: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 23 of 26

Page 24: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Downloads

Description Name Size Download method

Source code for the browser detectionapplication

browserdetect.zip60 KB HTTP

Information about download methods

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 24 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.

Page 25: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

Resources

Learn

• Read "JSP taglibs: Better usability by design" (developerWorks, December2001), covering better leveraging of JSP custom tag libraries.

• See "J2EE Pathfinder: Filtering with Java Servlets 2.4" (developerWorks,January 2004) for an introduction to the servlet filter architecture.

• Take a guided tour through the Geronimo maze in "Geronimo! Part 1: The J2EE1.4 engine that could" and its companion article, "Geronimo! Part 2: Tame thisJ2EE 1.4 bronco" (developerWorks, May 2005).

• Visit the developerWorks Open source zone for extensive how-to information,tools, and project updates to help you develop with open source technologiesand use them with IBM's products.

• Visit the developerWorks Apache Geronimo project area to access resourcesfor Geronimo developers.

• Browse all the free Apache tutorials available in the developerWorks Opensource area.

Get products and technologies

• Visit the official Apache Geronimo site to download the latest release.

• Visit the official site for the Apache Ant build tool.

• Access a number of browser detection scripts.

• Get scripts that detect Flash and QuickTime objects.

• Download Gluecode Standard Edition, an open source application server basedon Apache Geronimo.

• Innovate your next open source development project with IBM trial software,available for download or on DVD.

• Learn about the Apache Geronimo support offering, which gives you thetechnical support you need to confidently develop and deploy your Web andJ2EE applications using Apache Geronimo.

Discuss

• Participate in the discussion forum for this content.

About the author

Daniel WintschelDaniel Wintschel is a regular guy who derives great excitement from solving businessproblems, streamlining processes, and writing all sorts of Java code. He loves coffee

ibm.com/developerWorks developerWorks®

Powerful browser detection and custom JSP tags with Geronimo© Copyright IBM Corporation 1994, 2008. All rights reserved. Page 25 of 26

Page 26: Powerful browser detection and custom JSP tags with Geronimo · 2010-01-15 · Powerful browser detection and custom JSP tags with Geronimo Use Geronimo and Jetty to create a browser

and is currently seeking development opportunities on a telecommuting basis fromSingapore. If you are bored one day, you can read more about him.

developerWorks® ibm.com/developerWorks

Powerful browser detection and custom JSP tags with GeronimoPage 26 of 26 © Copyright IBM Corporation 1994, 2008. All rights reserved.