Monday, August 24, 2009

Needs Work

Page Navigation and Client Interaction

In this section, we will explore the following concepts:

Page navigation techniques

Taking input from the user

Creating a managed bean

Creating and invoking a do<action> method

These concepts will involve the use of the following JSF centric components, tags and elements:


navigaction-case entries in the faces-config file

managed-bean entries in the faces-config file

So far, we’ve played around a bit with JSF custom tags and internationalization and stuff, but all of that has been largely display generation. If all we wanted to do was display text to the user, we wouldn’t need a Servlet Engine and a JSF framework. No, the really kewl stuff happens when we start taking data from the user, and responding dynamically to the user depending on what type of data and information they deliver to us on the server side.

Two of the biggest challenges associated with building dynamic web applications is first, getting valid information and input from your clients, and secondly, providing an intelligent and informative response to the client based on the information they have provided. So, with these two tasks being the biggest challenges facing a modern day web application developer, nobody should be surprised by the fact that two of the most core features of JSF are the framework’s built-in navigation model, and the framework’s built-in facilities for simplifying the job of obtaining valid user input.

Of course, my challenge is to come up with some slick and friendly application that we could build together to effectively demonstrate the JSF framework’s page navigation and input management capabilities. To keep things fairly fun and light-hearted as we explore some fairly complicated concepts, I thought we’d prototype a little “Rock-Paper-Scissors” type of application.

I know, “Rock-Paper-Scissors” isn’t the most professional and technical of applications that we can develop, but the concept is pretty universal, and using this fun little game will help avoid having to spend too much time trying to explain all of the various use cases and non-JSF related details that might go along with an application that is more technical.

The basic idea of our implementation will be that the client will be asked to pick one of three gestures: Rock, Paper or Scissors. When the client has submitted their choice, the server will choose one of the three possible gestures, Rock Paper or Scissors. And then, the results of the game will be evaluated, and a response summarizing the results of the game will be sent back to the client. It’s all a pretty simple concept.

*Note, the term ‘gesture’ is used to describe the three choices of Rock, Paper and Scissors. The reason the term ‘gesture’ is used is because when the game is played interactively between two people, hand gestures are used to represent the choice of rock, paper or scissors.


Our online version of the Rock Paper Scissors game will involve five web pages, with the first page prompting the end user to type either Rock, Paper or Scissors into a textfield, after which, they will need to click on a submit button to initiate game play.

The game has three possible outcomes, either a win, lose, or tie. And actually, I’m going to include a fourth outcome, which is failure, which could happen if something either goes wrong, or perhaps the client hasn’t provided a valid option for game play. So, to accommodate our four possible outcomes, we will need to create an additional four JSP pages, named win.jsp, lose.jsp, tie.jsp and failure.jsp.

***Images go here.

Overall Application Flow

So, we have established that our little application needs five simple JSP pages: one for input, three to represent a potential result of win, lose or tie, and finally, a failure page to handle any errors or problems. But the question is: how do we get from the input page to the results page? I mean, there is a little bit of logic involved in order to decide whether there has been a win or a loss, and of course, we want to see the JSF framework’s neat page navigation features in action, right? Well, here’s how it is all going to work:

The first page the user will touch will have a textfield and a submit button on it. When the user types in a gesture and clicks the submit button, a request will go across the network and subsequently be captured by our application’s JSF framework. Of course, our application is going to need to first figure out what the user chose as their gesture, chose a gesture of its own, and then perform the multi-variable calculus required to figure out if the client won, lost, or tied. Of course, this is application logic, and we will need to code this application logic into a JavaBean. So, we’re going to need to create a JavaBean called the RPSBean (RPS=Rock, Paper, Scissors), and in that bean we will code a method named doRockPaperScissorsGame(). It is inside this method that we will code the required application logic.

The JSF framework will create an instance of the RPSBean for us, it will invoke the doRockPaperScissorsGame() method at the appropriate time for us, and it will take responsibility for figuring out when the Java Virtual Machine’s garbage collector will be able to get it’s greasy little fingers on the JSF created instance of the RPSBean and dispose of it. So, although we’re going to have to code a thing or two into this RPSBean class, the lifecycle of this JavaBean will be managed by the JSF framework. Given this fact, it’s not surprising that in JSF parlance, we call this type of JavaBean a ‘managed bean.’ All JSF managed beans must be described in the faces-config.xml file.

And speaking of the faces-config.xml file, there are a few other salacious entries that we are going to have to make in there if we want our application to work properly. You see, when our doRockPaperScissors() method executes, it must return a String. The String, which for us will simply be the words ‘win’, ‘lose’, ‘tie’ or ‘failure’, map to a navigation-rule from-outcome entry in the faces-config.xml file. The JSF framework then uses the returned String from the doRockPaperScissorsGame() method to figure out which JSP page will be invoked in order to produce a response. When the JSP is invoked, the appropriate markup gets created, and the response is then sent back to the user.

So, in summary, when the client clicks submit, a request is captured by the JSF framework. The JSF framework will look at the request, and not only create in instance of the appropriate JavaBean, but it will also invoke the method needed to implement the required application logic. When the logic is complete, the method will spit out a text String, and based on a corresponding text entry in the faces-config.xml file, the framework will figure out which JSP page will be called upon for generating a response that will get sent back to the client. And that’s it!

***Diagram showing the flow

The Landing Page

The landing page which is first viewed by the client is tasked with providing a textfield and a submit button, along with a bit of directions, to the end user.

<%@taglib uri="" prefix="f"%>
<%@taglib uri="" prefix="h"%>

    Please chose between Rock Paper and Scissors:
    <h:form id="rpsgame" >
        <h:inputText id="gesture" value=”#{rpsbean.clientGesture}”> </h:inputText>
        <h:commandButton id="submit" type="submit" value="Play!" action="#{rpsbean.doRockPaperScissorsGame}" ></h:commandButton>


There isn’t too much magic on this page. The required taglib directives decorate the top of the page, we have the standard form tag which then wraps both the h:inputText and the h:commandButton tags.

    <h:form id="rpsgame" >
        <h:inputText id="gesture" value= ”#{rpsbean.clientGesture}” > </h:inputText>
        <h:commandButton type="submit" value="Play!"

action="#{rpsbean.doRockPaperScissorsGame}" ></h:commandButton>


The first thing to notice here is the value attribute of the inputText tag. We need to be able to take whatever the client types into the textfield and have that transferred to the server, where we can process it. The ”#{rpsbean.clientGesture}” entry for the value attribute tells the JSF framework that whatever is typed into this textfield should be transferred to a property named clientGesture in a JavaBean that is running on the server that is named rpsbean.

The second thing that needs to be pointed out here is the action attribute of the h:commandButton tag. Notice how the action attribute is set to "#{rpsbean.doRockPaperScissorsGame}"

The hash code sign, #, is a signal that tells the JSF framework that some JSF-specific processing is required. In this case, the JSF framework recognizes the fact that any time a submit button is clicked, processing logic is required, and in this case, the JSF framework will invoke the doRockPaperScissorsGame method of the rpsbean.

Another thing worth pointing out here are the id attributes that have been assigned to the form and inputText elements. JSF links elements and sub-elements according to their names or ids, in a ancestor:parent:child type of syntax. So, when we do processing and try to figure out what a user typed into the textbox, we can identify the inputText field with the id of gesture, inside the form named rpsgame, with the name rpsgame:gesture.

The syntax used here to specify the value of the action attribute is known as JSF expression language, and while the result of using this syntax will be to have the JSF framework invoke a method on a JavaBean, it is worth nothing that the syntax we see here is not a Java syntax. JSF expression langugage is intended to look and feel more like a scripting language, helping to keep JSP pages look cleaner, be free from actual Java code, and subsequently making JSPs easier to write and maintain.

So, our h:inputText tag is looking for a JavaBean named rpsbean so, it would probably be prudent to create such a JavaBean that will fill this need.

The basic outline of the JavaBean will look like this:

package com.mcnz.jsf.bean;

import javax.faces.context.*;

public class RPSBean {

I’ve placed the bean in a package named com.mcnz.jsf.bean, I have been generous to myself and imported javafaces.context.*, and I have created a simple class named RPSBean. When you create your own class, make sure the RPSB is all capitalized – case is important!

Now, after coding the class declaration, the next thing you’ll want to think about are any instance variables the class might need. Our little RPSBean will probably need to keep track of the client gesture, and the computer’s gesture, so making two String variables, one named computerGesture and the other named clientGesture, probably wouldn’t be such a bad idea.

Now, one thing to note about methods called from the action attribute of a custom tag is the fact that those methods must return a text String.

The text String is supposed to provide the JSF framework some type of guidance as to how to mitigate page navigation, so in our case, we will have four possibilities, the Strings: “failure”, “win”, “lose” and “tie”.

It’s always a good habit to start off your do<action> method by explicitly setting a String named result to a valid value, which in this case we set to failure, and then specifying what will be the last line of code in the method, return result;

package com.mcnz.jsf.bean;

import javax.faces.context.FacesContext;

public class RPSBean {
    public String doRockPaperScissorsGame() {
        String result = "failure";
/*Method implementation logic will go here. */
        return result;


Of course, we need to keep track of what the client selected, and what the computer has selected, so we’ll add two instance variables of type String to our RPSBean. We will add the setters and getters as well.

Saturday, August 8, 2009

Chapters 1 & 2 Rough Cuts JSF Made Easy

Chapter 1

JSF – Getting Started

***much of this is at the end of the portlet book*

If you want to start working with JSF, the first thing you need to do is set up some sort of development environment. There are plenty of great Java development environments out there, ranging from Sun’s NetBeans to Eclipse to IBM’s various Rational Application Developer offerings. Unfortunately, I have neither the time or the patience to discuss how to configure every Java development enviroment in existence, so instead, I’m just going to describe how to get started with Java ServerFaces development with the cheapest, most simple and basic environment one could muster on a Windows based computer. If you can get a JSF application working with nothing more than Wordpad, a JDK installation, and the latest distribution of Apache’s Tomcat Servlet engine, well, you should be able to take that knowledge and apply it to just about any development environment.

So, here’s the basic minimum that you need in order to start developing and testing a JSF application on a Windows machine:

Java Development Kit, version 5 (aka 1.5) or higher

A Servlet Engine supporting servlet 2.5 and JSP 2.1 (Tomcat 6 or better will more than fit this bill)

A JSF Implementation (jsf-api.jar and jsf-impl.jar files)

The JSTL implementation jar files (standard.jar and jstl.jar)

A text editor such as Wordpad

The command prompt to compile and run our JSF applications

For this book, I have downloaded the Java Development Kit version 1.6 (Java6) with update 15. I just installed it into a directory off the root of C named _jdk1.6 After installing the JDK, don’t forget to set the JAVA_PATH environment variable to C:\_jdk1.6.

With the JDK installed, and the JAVA_PATH environment varible conifigured, you need to get going on a web based runtime environment that will allow you to deploy and test your JSF applications. Perhaps the most universally loved Servlet Engine is Tomcat, which can be found at the website.

I simply downloaded the Tomcat Core Binary distribution, version 6.0.20, and extracted the contents of the zip file to the C:\ drive. Once that was done, I renamed the folder _tomcat6. Opening a command prompt, and scooting over to the tomcat\bin directory and running startup.bat should get tomcat running. You’ll want to confirm that you’ve got a functional Tomcat instance by opening http://localhost:8080 in a web browser and making sure the Tomcat welcome page appear.

*** Do we really need sources for JSF 1.2*** xxx

Now, technically speaking, JSF is a specification. JSF is simply a document and a set of APIs and JavaDocs that describes a technology that can be used to develop web based enterprise applications in Java. To actually use JSF, you need an implementation of the JSF specification, that is, somebody must have taken the time to implement all of the things defined in the specification. Fortunately for us, Sun provides a ‘freely’ downloadable JSF implementation through what is affectionately known as the Mojarra project. A working link at the time of writing for the project is: (who knows when this will change?)

From the downloads page, there are two JSF 1.2 resources you need to download, that is, the mojarra 1.2 source zip file, and the mojarra 1.2 binary zip file. Download both of these, and then unzip them to a smart location on your hard drive. I unzipped my files to C:\_jsf12

The first thing you should to after unzipping these two files is find the index.html file in the javadocs folder of the binary distribution. Bookmark that page, because you will come back to it very often. It’s nice having the JavaDocs for the JSF API on your local machine and readily accessible.

Finally, the last thing you’ll want to take note of is the lib folder in the binary download folder. This folder contains a number of resources, not the least of which are the jsf-api.jar and jsf-impl.jar files. These are the most important files in the entire JSF download, as they pretty much represent the bytecode embodiment of the implementation of the JSF specification. These two jar files will need to be added to the runtime and designtime classpaths of any JSF application that is developed and deployed.

To just test that your configuration is working, you can take the jsf-guessNumber war file and move it into the webapps folder of the tomcat6 installation. Be warned though, a few changes must be made to get this little application to work.

When the jsf-guessNumber application gets deployed, tomcat extracts the contents of the war file to a new folder in the webapps directory named appropriately, jsf-guessNumber. (Tomcat needs to be started for this extraction to happen.)

Unfortunately, the two JSF and the two JSTL jar files that are required by this app are not on the classpath. So, to get the JSF application to work, you need to create a new folder named \lib under the WEB-INF directory of the jsf-guessNumber folder that has been created in the webapps directory. Copy jsf-impl.jar, jsf-api.jar, jstl.jar and standard.jar into the lib folder you have just created, stop and restart the tomcat6 server, and then point your browser at this application when tomcat is started by using the following URL:


You will see dude there in all of his glory, asking you to pick a number between one and ten. Go ahead and play! It means your tomcat server, and your JSF files, are all working properly together.


Chapter 21

A Simple JSF Application

Let’s put together a very simple JSF application, using the opportunity to examine the structure of a JSF application, while at the same time, testing our ability to create and deploy applications to our test environment.

JSF applications are simply standard web applications that conform to the requirements of the Servlet and JSP specifications. As such, every JSF application needs an application root. For this book, I’m going to create a new folder off of the root of C:\ named _easyjsf that will act as the root of my JSF application. C:\_easyjsf

Under the root of a Java web application there is always a folder named WEB-INF, and that folder must always containt a deployment descriptor for the web application named web.xml. This web.xml file provides information to the runtime environment, such as tomcat or any other servlet engine, information about how to configure the environment in which the application will run.

Now, JSF isn’t a built in feature of a servlet engine, and it’s certainly not part of the Servlet and JSP specification. So, if you want to create a web application that will leverage JSF technology, you need to add the various jar files that provide an implementation of the JSF specification. Furthermore, these jar files need to go in a very specific directory – a directory named lib that resides directly under the WEB-INF folder of your web application.

The four jar files that need to go in this folder are:





The jsf-api.jar and jsf-impl.jar files were downloaded from Sun as part of the binary JSF distribution zip file. The jstl.jar and standard.jar files can either be downloaded from, or more easily, they can be found in the lib folder of various sample applications that are also included in the binary JSF distribution obtained from Sun.

Furthermore, any Java code that gets compiled and distributed with your JSF application will go in a classes directory that also resides under the WEB-INF folder. Although we won’t have any compiled Java code in this example, it is worthwhile adding in the classes folder while we’re puttering around in WEB-INF.

For a JSF application, the web.xml file can be pretty lean, after all, there’s a special file named faces-config.xml that contains all of the JSF centric configuration data. However, there are two extremely important parts of a web.xml file that pertain to JSF.

The web.xml file of a JSF application must reference the FacesServlet. In a JSF application, all JSF centric requests go through a single, central Servlet which is uncreatively named FacesServlet. All JSF centric requests that come into a given web based application are routed through this single, monolithic servlet, which then is responsible for handling the incoming request, and generating a response that will get sent back to the client:

<servlet id="JSF_Front_Controller_Servlet">

<servlet-name>Faces Servlet</servlet-name>



Now, I mentioned that the all JSF centric requests that come into a given web application go through the FacesServlet. However, that begs the question, “how does a given application know that an incoming request is a JSF centric request?” Well, that’s an easy question to answer.

In a web application, all JSF based requests will share a common extension. So, rather than requesting a .jsp file, or an .html file, JSF requests will end with an extension such as .faces. This is known as an ‘extension mapping’ or a ‘servlet mapping’, and like the mapping of the FacesServlet, the mapping of requests having a given file extension back to the FacesServlet, is configured in the deployment descriptor of the web application.


<servlet-name>Faces Servlet</servlet-name>



Notice how the servlet-name in the <servlet-mapping>, Faces Servlet, matches the exact name used when configuring the FacesServlet in the <servlet> entry of the web.xml file.

Along with the <servlet> and <servlet-mapping> entries, the web.xml file should include a <display-name> element. We’re just going to use the simple display name of JSFWeb


All of the elements, starting with the <display-name> tag, and ending with the <servlet-mapping> go within a fairly verbose <web-app> tag that includes version, schema name, and schema location elements. As I said, it’s fairly verbose, and typing it out by hand is simply insane. If you look at the various web.xml files that are in the WEB-INF folder of the various sample applications that come with the JSF binaries, you’ll find plenty of examples of the web-app entry that you can copy and paste into your own deployment descriptor.

Also notice the ?xml element at the top of the file.

<?xml version='1.0' encoding='UTF-8'?>






<servlet id="JSF_Front_Controller_Servlet">

<servlet-name>Faces Servlet</servlet-name>






<servlet-name>Faces Servlet</servlet-name>




Alongside the web.xml file, any JSF application also needs a faces-config.xml file stored right there in the WEB-INF folder. As the name implies, the faces-config.xml file contains a variety of salacious nuggets of information about your JSF application, and as your application grows, so does the number of elements and entries within the faces-config.xml file. For now, however, our faces-config.xml file will be pretty much nascent, with nothing more than the <?xml> entry, and the top level <faces-config> tag, along with the verbose and intimidating namespace, version, and schema location attributes. Again, these faces-config attributes are so long and tedious, it’s practically impossible to type them out by hand without some type of mistake. It’s best to just copy the full <faces-config> element and attributes from one of the sample applications that get extracted from the binary distribution of the JSF implementation that was downloaded from Sun in the previous chapter.

The simple JSP page

With the basic configuration stuff done, it’s time to write a little ‘Hello World’ page that will get served up by the JSF framework that we have so diligently set up. We’re not going to win any programming awards with this rudimentary JSF page, but it will introduce a few basics to us, and it will also help verify that indeed, we can get a basic JSF page working in our local environment.

<%@taglib uri="" prefix="f"%>
<title>Simple JSF Page</title>

    <p>Hello World!</p>

So, there’s really nothing too intimidating here.

First of all, we see a taglib declaration at the start of the page. There are two tag library sets provided by the JSF framework, the first of which is the ‘core’ library, and the other is the ‘html’ tag library. This little ‘Hello World’ page is only going to use one JSF tag, the <f:view> tag, and since that tag is in the ‘core’ taglibrary module, only the core taglibrary, which by convention uses the prefix ‘f’, needs to be declared at the top of the page.

Following the taglib declaration we have standard HTML tags, namely the <html> tag itself, and a header tag which contains the page title. The page is simply titled “Simple JSF Page.”

Of course, the guts of this html page is the body that gets displayed in the web browser, and one of the rules of JSF development is that any visual elements that exist on a webpage need to be enclosed within a <f:view> tag. You’ll notice that in this example, the <f:view> tag surrounds theentire body, ending after the ‘body close’ tag, </body>, and just before the end html tag. </html>

Inside the body of the page, we don’t have anything earth shattering. All we have is a little “Hello World” declaration surrounded by paragraph tags. As I said, this isn’t going to win us any programming awards, but it is going to help verify the veracity of our test environment.

Type this code into any standard text editor, such as Microsoft’s Wordpad, and save the file as helloworld.jsp in the application root folder, which for me, is C:\_easyjsf. Now, remember, we save the file as helloworld.jsp, NOT helloworld.jsf!

By the way, it’s a good idea to keep our pages as xHTML compliant as possible. As a good housekeeping measure, and to keep our pages xHTML compliant, it’s not a bad idea to put the following doctype tag at the top of our helloworld.jsp:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">

With your application configured and your helloworld.jsp file coded and saved to the root of your web application, it’s time to ‘war up’ your JSF application. A war file, or web application archive, is the standard format for distributing and deploying J2EE/JEE web based applications.

The jar utility that comes with the JDK is great at compressing your web applications into war files that can be deployed directly to Tomcat. To war up your application, simply navigate a command prompt to the C:\_easyjsf> folder, and issue the following command:

C:\_easyjsf>C:\_jdk1.6\bin\jar -cvf easyjsf.war *.*

Now, this relies on the fact that the JDK has been installed into C:\_jdk1.6. If you have a different folder location, you will need to reference that JDK intallation folder explicitly. Alternatively, you could also just use the JAVA_HOME environment variable as so:

C:\_easyjsf>%JAVA_HOME%\bin\jar -cvf easyjsf.war *.*

Regardless of how you run the command, once the command is issued successfully, a war file will be created in the application root, named easyjsf.war. Copy this file to the webapps directory of your Tomcat server, start your Tomcat server if it is not already started, and wait a moment for the application to be deployed.

Looking at the log file from tomcat, you should see some information about the JSF 1.2 context being successfully initialized for your easyjsf application. (You may need to stop and start your Tomcat server to have the application loaded properly the first time.)

INFO: Initializing Mojarra (1.2_13-b01-FCS) for context '/easyjsf'

Aug 8, 2009 9:21:16 PM org.apache.catalina.startup.HostConfig deployWAR

INFO: Deploying web application archive ifnavigation.war

Aug 8, 2009 9:21:16 PM com.sun.faces.config.WebConfiguration processInitParameters

With the context successfully initialized, it’s time to navigate to your JSF application. You can invoke your application using the following URL:


The key elements here are the ip address and port (localhose:8080), the context root, which is easyjsf, which matches the name of the war file (minus the .war extension), and then the name of the JSP we are invoking. However, you should notice that the url says helloworld.faces, not helloworld.jsp.

Remember, for our application, only requests that end with the .faces extension are handled by the FacesServlet, and subsequently, the Java ServerFaces framework. By putting the .faces extension on our URL, the JSF framework knows to locate a resource named helloworld, which in this case, is our helloworld.jsp, and as a result, we see our little ‘Hello World’ message in the web browser.

Alternatively, if we tried to access the jsp directly, we’d get all sorts of esoteric errors. Here’s what I got when I tried to invoke our jsp by name with the following URL:


The server encountered an internal error...

JasperException: An exception occurred at line 8

5: <title>Simple JSF Page</title> 6: 7: </head> 8: <f:view> 9: <body> 10: <p>Hello World!</p> 11: </body>

Stacktrace: JspServletWrapper.handleJspException(


root cause

java.lang.RuntimeException: Cannot find FacesContext


Friday, August 7, 2009

Tomcat6 and JSF2.0

I was just wondering if JSF2.0 would work with Tomcat 6 without any problems, and indeed, it did. I downloaded the from, and then installed Tomcat on JDK 1.6, update 15, and then deployed the samples that came with the mojarra download to tomcat. I put the jsf-impl and jsf-api jars in the WEB-INF\lib folders, and each of the projects seemed to work, with the exception of ifnavigation and one example named polls.jsf or something. But, there were alot of other projects/examples, so I'm happy to say it's all working on Tomcat.

Can you run JSF2.0 on Tomcat 6.x?

So, I want to try out some JSF2.0 stuff, but I want to do it on Tomcat instead of Glassfish. Should it be hard? Well, here are the requirements for JSF 2.0:

JSF is based on the following Java API specifications:
■ JavaServer Pages™ Specification, version 2.1 (JSP™) <>
■ Java™ Servlet Specification, version 2.5 (Servlet) <>
■ Java™2 Platform, Standard Edition, version 5.0 <>
■ Java™2 Platform, Enterprise Edition, version 5.0 <>
■ JavaBeans™ Specification, version 1.0.1 <>
■ JavaServer Pages™ Standard Tag Library, version 1.2 (JSTL) <>
Therefore, a JSF container must support all of the above specifications.

From the Tomcat release notes, we get Tomcat 6 supporting the folowing APIs:

* annotations-api.jar (Annotations package)
* catalina.jar (Tomcat Catalina implementation)
* catalina-ant.jar (Tomcat Catalina Ant tasks)
* catalina-ha.jar (High availability package)
* catalina-tribes.jar (Group communication)
* el-api.jar (EL 2.1 API)
* jasper.jar (Jasper 2 Compiler and Runtime)
* jasper-el.jar (Jasper 2 EL implementation)
* jasper-jdt.jar (Eclipse JDT 3.3 Java compiler)
* jsp-api.jar (JSP 2.1 API)
* servlet-api.jar (Servlet 2.5 API)
* tomcat-coyote.jar (Tomcat connectors and utility classes)
* tomcat-dbcp.jar (package renamed database connection pool based on Commons DBCP)

Hmmm...I thought I was alright until I saw the reference to J2EE up there in the spec. That' can't be true!

My Question on JavaRanch



Angels without wings?

I never knew there were angels that didn't have any wings