Copyright ©May 2008 |
Tutorial: Using NetBeans or Eclipse with JDK 6, Apache Tomcat and JavaServer Faces
|
Three weeks ago, failing to complete several JSF tutorials for Eclipse launched me off on a tangent to learn about the deeper internals of JSF and then to Maven, whose promise was that it could set me up a blank but working JSF project that I could then just modify.
Here are my emerging notes for a JSF tutorial. What I learned here is relevant to Eclipse use also. In the end, it's more about learning JSF than Eclipse or NetBeans although tools often get in the way. And, at the present time, I'm spending pretty much all my time in Eclipse as I work through a new book, Essential JSF, Facelets & JBoss Seam.
Bibliography, Tutorials, Source Code and Other, Related Resources
Click here for an exhaustive
bibliography and other helps.
I bought the book, Core JavaServer Faces by David Geary and Cay Horstmann. It took me a long time to get it going. I tried and failed over and over again in Eclipse. This is what led me, first to Maven, and then to NetBeans.
The authors waffled on the source code details throwing a great deal of confusion into the process. It wasn't until I carefully waded through the different possibilities and chose one that I got it working. Click here for the details.
I also have the book, JavaServer Faces in Action, by Kito Mann which also has a sample in its first chapter. I haven't finished getting that one going; there's one last problem. I do have most of it working and I learned some crucial, if now trivial, things along the way. Click here for the details.
Now I have to try my own application. Click here for the details.
|
An excellent tutorial I'm going through at present is in the first two chapters of Essential JSF, Facelets & JBoss Seam, by Kent Tong. Those chapters are available to read free of charge here. I, however, purchased the whole book. At this writing, I'm going through it (it's only $19.95 on-line). It seems well-worth the price (if you're as desperate as I). You don't get bogged down in deep explanations, but the instructions seem to work and I've learned more than a couple of things. |
Here are some things I've learned that I didn't know and whose absence from my wisdom caused me no end of trouble (probably why I went to NetBeans originally).
<url-pattern> /faces/* </url-pattern>instead of
<url-pattern> *.faces </url-pattern>which you will find in many books. Getting confused between what these older books say and what modern practice is can lead to HTTP errors and frustration. This has a particular effect upon the path typed into the browser address line.
/WEB-INF/faces-config.xml Faces Servlet javax.faces.webapp.FaceServlet /faces/*
Here are some random notes I'll incorporate into something worth reading one day.
- In a JSF application, a page is defined by a JSP file and identified by a view id or the relative path to the page from the root (kept as WebContent in Eclipse).
- Each JSP tag belongs to a certain tag library (including the main ones). These libraries are identified by URL. Before you use a tag, you must introduce a prefix or short-hand for the URL and then use it to qualify the tag name.
- When a warning appears in the text portion under the Web Page Editor looking at a JSP, and you've done everything right, save all files, drop Eclipse and relaunch it. If you've done everything right, the warning will sometimes disappear. If not, look harder. One sign is to try to run it anyway; if it works, it probably isn't your fault and bouncing Eclipse may fix the problem.
When you fix a warning or error (or suspect one is already fixed, or just want to see), choose Project -> Clean and clean the current project. If invalid (unless an Eclipse bug), the warning or error should disappear.
- If you're using an external browser to test with, you may need—at very least—to drop the page you're running before running again after some modifications. This is because Eclipse can't clean up and redeploy. I create a new tab, run and then discard the tab every time to make certain I don't have any of the deployed files (principally under WebContent/WEB-INF/lib) still open.
- Over and over again, I learn that web.xml is king and if there's the smallest typo in this file, “FacesServlet” instead of “Faces Servlet”, etc., the worst possible thing will happen, i.e.: an HTTP 404 error or some such thing.
- If web.xml is king, then faces-config.xml is minister of foreign affaires. Anything amiss in this file and the JSF wiring doesn't work and neither does your application.
- The JSF engine goes through the following phases during a form submission:
If there is any error in the Process Validations phase or the Update Domain Values phase, the JSF engine will jump to the Render Response phase directly. Tong addresses this with pretty good detail in chapter 2, especially his StockQuote example.
I intend to go over the preceeding list and define in some detail each phase.
- Managed beans gain access to each other via the <managed-property>. It is important to ensure that the referring bean has a shorter or same lifetime (scope) than the referred so that resources don't disappear from underneath it.
A domain class is a Java class that models the logic and/or concepts in the domain. The Request class is one such class.
“Domain” means the logic and concepts surrounding the business operations concerned: e.g.: the postage is $10 per kg, some patrons may have discounts, etc.
In contrast, there are other classes that deal with getting input from the user to displaying output to the user. Such classes are called “UI classes”.
In such an application if later we decide to use a new UI technology (e.g.: one from JSF to some new technology), the domain classes can be reused but the UI ones can't. This is still much better than if a class is involved with both domain logic and UI because then as the UI technology needs to change, the code won't be reusable.
- Never let a session-scoped bean refer to any other managed bean because when the session bean is written out to disk, the other bean won't be (since it's not session-scoped) and when read back in, the reference inside the session bean will be nil. See Essential JSF, Facelets & JBoss Seam, page 135 (chapter 4).
- Information can be hidden on forms in a special hidden JSF HTML tag (<h:inputHidden>).
- A facet is a child component that is subjected to special processing by its parent. In the shop site example (Essential JSF, chapter 4), the data rows of the catalog are facets and contain <h:outputText> tags. The summary on page 160 makes some important points about creating tables whose row data can only be determined at run time.
java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConfigThis error came from failing to copy the following files down under WebContent/WEB-INF/lib:
org.apache.jasper.JasperException: /getrequest.jsp(18,36) Unterminated <h:inputText tagThis error came from the following inputText tag; it was a mistake that the over-enthusiastic Eclipse editor put in (because I'm not used to an editor rushing ahead of me to do my job):
<h:inputText value="#{req.weight}"}></h:inputText>
org.apache.jasper.JasperException: /getrequest.jsp(22,2) Attribute validator invalid for tag outputText according to TLDThis error came because I typed in the validator on the wrong tag. This is an inputText tag attribute.
<h:outputText value="Patron code:" validator="#{req.validatePatron}">
should have been:
<h:inputText value="#{req.patfonCode}" validator="#{req.validatePatron}">
This error came because there was an Apache Tomcat server created, but no project was associated with it.
You can tell no project is associated when the Console output at start-up (of the server) is black instead of red at the bottom-center of the Eclipse workbench.
...and how I eliminate them. If I don't show these, then I'll always sit mystified in front of them. This way, I check back to remind myself how I solved them. After a while, I'll start remembering. Mostly, however, errors are always due to a misalignment between Java classes, JSF elements in the JSP file and the definitions in faces-config.xml.
The first one went away when I corrected something in faces-config.xml.
The second one occurs commonly, but goes away after establishing the correct navigation rule (what determines “actions,” etc.). In this case, it was the link (in pictorial java-faces.xml) from productdetails back to showcatalog. See here.
This error went away after using Project->Clean... a few times or after relaunching Eclipse.
This one isn't too clear; it went away when I corrected ShowCartHelper.setCart from SetCart to setCart. I guess the moral is, “Be careful that no method names are misspelled in the bean class.”
This error never went away; perhaps it's a bug in Eclipse. The code seemed to work anyway. And yet, this seems like a pretty important definition to be missing. What is in these XML-file headers that we just copy naïvely and expect to work? What is the “validator” that does this, what is the list of what it can validate, and where are the additional data-type definitions (DTDs) put when we can find them?
I found the solution to this problem; it's recorded down below here at An Eclipse DTD Trick.
This error never went away and it's pretty straightforward: is there some JAR missing? It probably creates the other errors in the project. Maybe it stems, itself, from the previous error that wasn't so harmless after all.
These errors never went away and they kept the project from working. They probably cascade from the error that jsfc isn't a defined attribute.
Here is a URL that walks up to the question a little bit without actually answering it: http://www.mojavelinux.com/blog/archives/2006/12/facelets_tag_completion_in_eclipse/.
Advised to ignore the Eclipse errors immediately above, that the undefined jsfc attribute is not in any namespace and that missing it is harmless, I continue to do the exercices.
On page 193, after modifying listfaq.xhtml so that there are no remaining JSF tags (all JSF work is reduced to jsfc and other attributes in mostly span tags, I do a View Source in Firefox, but I don't get what the tutorial claims I should.
Editing Properties->Validation for the FaqFacelets2 project, removing HTML Syntax Validator, the yellow triangles disappeared from qa.xhtml, but not from listfaq.xhtml. Indeed, when I eliminated all validation from the project, the error/warning did not disappear from this file.
It would appear on this basis that these errors cannot be ignored and they clearly indicate that Eclipse will not do the right thing as long as they are not resolved. As shown here, launching on listfaq.xhtml, instead of listfaq.jsf is supposed to give nothing, but viewing the source should reveal
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:foo="http://foo.com">
<body>
<span jsfc="foo:qa" q="#{faqService.q1}" />
</body>
</html>
and not what it actually does reveal. So, this exercise doesn't work and I'm left wondering if the rest of what's going on in this chapter is really working or only appearing to work. I do have to work with an artist and perhaps page designer, potentially in Dreamweaver, so I can't easily ignore this problem.
The proof that this doesn't work for certain arises from the exercise on page 194 when web.xml is set up to deny access to the source view for listfaq.xhtml and trying to view the source has the same result as before.
See my cry of Aaaaargh below; I found a solution to the problem (sort of).
This error occurred because when I created productdetails.xhtml, it ended up on the path WebContent/WEB-INF because the wizard put it there and I wasn't paying attention until I got this error.
Facelets is a developer friendly enhancement of JavaServer Faces (JSF) eliminating a lot of mucking around in the complicated faces-config.xml file and making the whole process more designer friendly. The latter question is simply that life is very hard for the Dreamweaver-based page and graphics designer when he has to work on JSF pages whose elements (tags) make Dreamweaver choke.
Facelets corrects this problem with templating, re-use and ease of development. JSF is, after all, the platform developers want to use instead of developing to JSP, creating their own tags (that Dreamweaver will choke on anyway) and having to do all the hard work over and over again.
Facelets can use any container; you do not tie yourself to Tomcat, JBoss, or GlassFish, etc. when you code to Facelets.
The components of Facelets include a JAR, jsf-facelets.jar, makes use of the UIComponents in the JavaServer Faces API and a single modification to faces-config.xml:
<view-handler> com.sun.facelets.FaceletViewHandler </view-handler>
as well as statements in web.xml like:
<context-param> <param-name> javax.faces.DEBUG_SUFFIX </param-name> <param-value> .xhtml </param-value> </context-param>
Facelets use the “EL-API” specification with JSF, meaning that
#{ ... } or ${ ... } to reference beans.
You do still create beans for reference in the web page code just as for JSP and JSF, but you don't have to maintain the laborious faces-config.xml for this with the risk of name mismatches between this file, code, JSP files, etc.
Facelets lets you set up your own component libraries. This is a little like writing C preprocessor macros to subsume a bunch of lines of code that you don't want to type over and over again.
<facelet-taglib> <namespace> http://www.mycompany.com/jsf </namespace> <tag> <tag-name> bar </tag-name> <component> <component-type> javax.faces.Data </component-type> <renderer-type> com.mycompany.Bar </renderer-type> </component> </tag> </facelet-taglib>
You put this kind of definition into a file named like bar.taglib.xml under project-name/JavaSource/META-INF.
The jsfc attribute that can be included with any standard HTML element tag like span, form, etc. makes it so that these tags get handled as server-side components by the Facelets view handler.
I'm reproducing this here because I fear (with no particular foundation) that the URL might disappear one day. This is by Dan Allen and it very much affects chapter 6 of Essential JSF, Facelets and JBoss Seam. Starting at the top of page 189 is the text to foo.taglib.xml and it needs the document type definition (DTD) referred to in this trick. The solution was dated January 31, 2006. I'm using it in June, 2008 and it appears to stop the little yellow triangle from appearing.
|
Love it or hate it, Eclipse is very insistent on going out to the web to fetch DTDs to validate the active XML file. When it can't find one, it whines, complains and puts an ugly yellow mark on your file, tagging it as a warning condition. Perhaps this is a small itch, but I felt like scratching it, so I have included an equally small solution to the problem. The problem with DTDs is (and has always been?) that they don't necessarily point to actual internet resources. Authors use DTD URIs as namespaces to keep the elements in one definition totally seperate from ones (perhaps with the same name) in another. In the early days, it was even encouraged that authors just make up any old URL, as long as it was, and would remain to be, unique. Well, maybe Eclipse missed that day in class, so we hack on. The question remains, where can you find the DTD in a consistent location, from whereever you are? Sure, you can load it into your local catalog, but as soon as you are on another computer, the problem is back. We want a permanent solution. The source code repository, of course! These servers are always available, serve up the files without interference from a website rebranding, and better yet, they are already versioned! Brilliant! Simply use the "download" link from the web-based CVS/SVN tool that points to the DTD file in the source code repository in your DOCTYPE definition at the top of the file (we have to at least assume the author checked it in!). I will leave you with an example: <?xml version="1.0"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd"> |
Okay, this is pretty much disasterous confusion; what I've found by doing Chapter 6 all over again a fourth time in a new workspace all alone is...