Thursday, June 14, 2012

How to Specify Source Code When Debugging in Eclipse

You can have multiple application projects in Eclipse. You can use Eclipse to start a weblogic server in the debug mode. And then you can debug your web applications deployed to the weblogic server. You may want to debug into the source code of the libraries used in your application. For example, you may want to debug into the jsf-impl.jar. You may use different versions of jsf-impl in different applications. So how to use the source code that matches the library? It is actually easy. The following are the steps.
  1. In eclipse, go to "Run --> Debug configurations...". This will open the configuration screen.
  2. In the screen, the left pane shows a list of the programs. Click on the one you are using. In this example, it is "Oracle Weblogic Server 11gR1 PatchSet 1 at localhost".The right pane will show tabs named "Server", "Source", "Environment", etc.
  3. In that right pane, click on the "Source" tab. You will see a list of the projects and files. These are the source code files that eclipse uses to show in debugging.
  4. In that right pane, you can use the "Add" button to add source code file. You can also have different versions of the source code for a library. In that case, you can use the "Up" and "Down" button to move the positions of the source code file. The one sitting higher will be picked up.

Wednesday, June 13, 2012

JSF and JSP Architecture Models

There are two models for building applications using the JSP and servlet technology.

The Model 1 Architecture

In this model, the target of every request is a JSP page. The JSP page does all the things to answer the request. It can use JavaBeans to access database or other services.

The Model 2 Architecture

This model follows the Model-View-Controller(MVC) design pattern. In this architecture, all the requests are received by the servlets first. The servlets act as the controller. They analyze the request, get the data into JavaBeans, and finally dispatch the requests to JSP pages. The JavaBeans act as the model. And the JSP pages act as the view.

What about JSF?

We know every JSP page is actually a servet. It will be compiled to a servlet class by the web container. Now in the JSF world, with all those JSF lifecyle phases, is it still following the Model 2 architecture? The answer is still "Yes" because the JSP file gives the layout and appearance of the page. But unlike the old jsp/servlet technology where the JSP writes out all the HTML text, in JSF, the servlet generated from the JSP page only produces some simple HTML text such as the header("Content-type", "text/html"). Mostly it just processes the tags and creates the object tree into the Context which are used to build the JSF component tree. Later on the faces servlet gets the component tree from the context and spits out the actual HTML text in the renderers of the components in the component tree.

Roughly speaking, in the traditional Model 2, the servlet does not do much. basically it just dispatches the requests to the JSP pages and its job is done. But in JSF, the servlet will execute the JSF life cycle for every request. At some point in the life cycle, the servlet will dispatch the request to the JSP. The JSP will do its job and save the the work into the conetxt. Then the execution will return to the servlet for the life cycle to finish.

The following is one actual stacktrace from a sample JSF application. It shows an error. But that is not the interest here. From the stacktrace, we can see how the whole thing works together. We can see the following:

  1. The faces servlet acts as the controller. The JSF lifecyle is executed in the controller.
  2. The splitting line in the stacktrace is the one containing the following: com.sun.faces.context.ExternalContextImpl.dispatch. This is where the faces servlet dispatches the request to the JSP page.
  3. After the faces servlet dispatches the request, the servlet generated by the JSP will take over the task. In the example, it is jsp_servlet.__index.class which is generated from the JSP page index.jsp. It is missing in this case. So an error occurs.
  4. The jsp_servlet processes the tags in the JSP page, creates the corresponding objects from the tags and stores them into the pageContext. The jsp_servlet does not write out the actual HTML text from the tags.
  5. Later on in the JSF lifecycle, the JSF renderers will write out the actual HTML text that will be sent to the browser. And these occurs in the faces servlet.
javax.servlet.ServletException: [HTTP:101249][ServletContext@11930454[app:spinner module:spinner path:/spinner spec-version:2.5]]: Servlet class jsp_servlet.__index for servlet /index.jsp could not be loaded because the requested class was not found in the classpath .
java.lang.ClassNotFoundException: jsp_servlet.__index.
 at weblogic.servlet.internal.ServletStubImpl.prepareServlet(ServletStubImpl.java:543)
 at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:271)
 at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:191)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:235)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
 at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502)
 at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:248)
 at  com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:410)
 at com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:469)
 at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:140)
 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
 at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
 at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
 at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
 at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592)
 at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
 at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
 at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202)
 at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108)
 at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
In the correct version for the example above, the class jsp_servlet._index.class is at the right location. Looking at the actual code, you can see the majority of the class is the methods of the following type:
private boolean _jsp__tagX(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.jsp.PageContext pageContext, javax.servlet.jsp.tagext.JspTag activeTag, com.sun.faces.taglib.html_basic.PanelGridTag parent) throws java.lang.Throwable
    {
The method name is _jsp__tagX, where 'X' is a number. For this particular example, there are 12 such methods. X is from 0 to 11, each corresponding to an actual tag in the JSP file.

A main method in _index.java is the following:

public final class __index extends  weblogic.servlet.jsp.JspBase  implements weblogic.servlet.jsp.StaleIndicator {
...
    public void _jspService(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) 
    throws javax.servlet.ServletException, java.io.IOException {

        javax.servlet.ServletConfig config = getServletConfig();
        javax.servlet.ServletContext application = config.getServletContext();
        javax.servlet.jsp.tagext.JspTag _activeTag = null;
        java.lang.Object page = this;
        javax.servlet.jsp.PageContext pageContext = javax.servlet.jsp.JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true , 8192 , true );
        response.setHeader("Content-Type", "text/html");
        javax.servlet.jsp.JspWriter out = pageContext.getOut();
        weblogic.servlet.jsp.ByteWriter bw = (weblogic.servlet.jsp.ByteWriter)out;
        bw.setInitCharacterEncoding(_WL_ORIGINAL_ENCODING, _WL_ENCODED_BYTES_OK);
        javax.servlet.jsp.JspWriter _originalOut = out;
        javax.servlet.http.HttpSession session = request.getSession( true );
        try {;
            bw.write(_wl_block0Bytes, _wl_block0);
            bw.write(_wl_block1Bytes, _wl_block1);
            bw.write(_wl_block1Bytes, _wl_block1);
            bw.write(_wl_block1Bytes, _wl_block1);

            if (_jsp__tag0(request, response, pageContext, _activeTag, null))
             return;
            bw.write(_wl_block9Bytes, _wl_block9);
        } catch (java.lang.Throwable __ee){
            if(!(__ee instanceof javax.servlet.jsp.SkipPageException)) {
                while ((out != null) && (out != _originalOut)) out = pageContext.popBody(); 
                _releaseTags(pageContext, _activeTag);
                pageContext.handlePageException(__ee);
            }
        }
    }
....

}
The method above calls _jsp_tag0() which will in turn calls _jsp_tag1(), .... The mehtod _jsp_tag0 is for the ViewTag. The method is as follows:
 private boolean _jsp__tag0(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response, javax.servlet.jsp.PageContext pageContext, javax.servlet.jsp.tagext.JspTag activeTag, javax.servlet.jsp.tagext.JspTag parent) throws java.lang.Throwable
    {
        javax.servlet.jsp.tagext.JspTag _activeTag = activeTag;
        javax.servlet.jsp.JspWriter out = pageContext.getOut();
        weblogic.servlet.jsp.ByteWriter bw = (weblogic.servlet.jsp.ByteWriter) out;
         com.sun.faces.taglib.jsf_core.ViewTag __tag0 = null ;
        int __result__tag0 = 0 ;

        if (__tag0 == null ){
            __tag0 = new  com.sun.faces.taglib.jsf_core.ViewTag ();
            weblogic.servlet.jsp.DependencyInjectionHelper.inject(pageContext, __tag0);
        }
        __tag0.setPageContext(pageContext);
        __tag0.setParent(null);
        __tag0.setJspId("id0");
        _activeTag=__tag0;
        __result__tag0 = __tag0.doStartTag();

        if (__result__tag0!= javax.servlet.jsp.tagext.Tag.SKIP_BODY){
            try {
                if (__result__tag0== javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED) {
                    out = pageContext.pushBody();
                    bw = (weblogic.servlet.jsp.ByteWriter)out;
                    __tag0.setBodyContent(( javax.servlet.jsp.tagext.BodyContent)out);
                    __tag0.doInitBody();
                }
                do {
                    bw.write(_wl_block2Bytes, _wl_block2);

                    if (_jsp__tag1(request, response, pageContext, _activeTag, __tag0))
                     return true;
                    bw.write(_wl_block3Bytes, _wl_block3);

                    if (_jsp__tag2(request, response, pageContext, _activeTag, __tag0))
                     return true;
                    bw.write(_wl_block8Bytes, _wl_block8);
                } while (__tag0.doAfterBody()== javax.servlet.jsp.tagext.IterationTag.EVAL_BODY_AGAIN);
            } finally {
                if (__result__tag0== javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_BUFFERED) {
                    out = pageContext.popBody();
                    bw = (weblogic.servlet.jsp.ByteWriter)out;
                }
            }
        }
        if (__tag0.doEndTag()== javax.servlet.jsp.tagext.Tag.SKIP_PAGE){
            _activeTag = null;
            _releaseTags(pageContext, __tag0);
            return true;
        }
        _activeTag=__tag0.getParent();
        weblogic.servlet.jsp.DependencyInjectionHelper.preDestroy(pageContext, __tag0);
        __tag0.release();
        return false;
    }

Notice that line in red "weblogic.servlet.jsp.DependencyInjectionHelper.inject(pageContext, __tag0);". This looks like to process the tag and save the values into the pageContext. The other methods _jsp_tagX() are similar.

Understanding the Java Stack Trace

The java stacktrace often contains something like "... 10 more Caused by". What does the number in this string mean? The following is the javadoc of the class Throwable. It has a good explanation. It can be found online at http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Throwable.html.

pringStackTrace

public void printStackTrace()
Prints this throwable and its backtrace to the standard error stream. This method prints a stack trace for this Throwable object on the error output stream that is the value of the field System.err. The first line of output contains the result of the toString() method for this object. Remaining lines represent data previously recorded by the method fillInStackTrace(). The format of this information depends on the implementation, but the following example may be regarded as typical:
 java.lang.NullPointerException
         at MyClass.mash(MyClass.java:9)
         at MyClass.crunch(MyClass.java:6)
         at MyClass.main(MyClass.java:3)
This example was produced by running the program:
 class MyClass {
     public static void main(String[] args) {
         crunch(null);
     }
     static void crunch(int[] a) {
         mash(a);
     }
     static void mash(int[] b) {
         System.out.println(b[0]);
     }
 }
The backtrace for a throwable with an initialized, non-null cause should generally include the backtrace for the cause. The format of this information depends on the implementation, but the following example may be regarded as typical:
 HighLevelException: MidLevelException: LowLevelException
         at Junk.a(Junk.java:13)
         at Junk.main(Junk.java:4)
 Caused by: MidLevelException: LowLevelException
         at Junk.c(Junk.java:23)
         at Junk.b(Junk.java:17)
         at Junk.a(Junk.java:11)
         ... 1 more
 Caused by: LowLevelException
         at Junk.e(Junk.java:30)
         at Junk.d(Junk.java:27)
         at Junk.c(Junk.java:21)
         ... 3 more
Note the presence of lines containing the characters "...". These lines indicate that the remainder of the stack trace for this exception matches the indicated number of frames from the bottom of the stack trace of the exception that was caused by this exception (the "enclosing" exception). This shorthand can greatly reduce the length of the output in the common case where a wrapped exception is thrown from same method as the "causative exception" is caught. The above example was produced by running the program:
 public class Junk {
     public static void main(String args[]) { 
         try {
             a();
         } catch(HighLevelException e) {
             e.printStackTrace();
         }
     }
     static void a() throws HighLevelException {
         try {
             b();
         } catch(MidLevelException e) {
             throw new HighLevelException(e);
         }
     }
     static void b() throws MidLevelException {
         c();
     }   
     static void c() throws MidLevelException {
         try {
             d();
         } catch(LowLevelException e) {
             throw new MidLevelException(e);
         }
     }
     static void d() throws LowLevelException { 
        e();
     }
     static void e() throws LowLevelException {
         throw new LowLevelException();
     }
 }

 class HighLevelException extends Exception {
     HighLevelException(Throwable cause) { super(cause); }
 }

 class MidLevelException extends Exception {
     MidLevelException(Throwable cause)  { super(cause); }
 }
 
 class LowLevelException extends Exception {
 }
But be careful about the accuracy here. The following is also from the javadoc about the method
public StackTraceElement[] getStackTrace()
Provides programmatic access to the stack trace information printed by printStackTrace().

Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method. Generally speaking, the array returned by this method will contain one element for every frame that would be printed by printStackTrace.

Reference

1. http://stackoverflow.com/questions/1043378/print-full-call-stack-on-printstacktrace

Tuesday, June 12, 2012

How is a converter wired to a JSF tag?

The following is a piece of sample code in JSF that uses converter:
 <h:inputText id="date" value="#{payment.date}"> 
      <f:convertDateTime pattern="MM/yyyy"/>
 </h:inputText>
The convertDateTime converter is an independent object from the inputText tag handler class. Then how does the inputText tag know to use the convertDateTime converter to process the date value? The secret is in the component class. We know the tag handler class has an API method
   public String getComponentType() {...}
 
that tells its component class. The component class has an API method
   public String getRenderType(){...}
 
that tells the renderer class. The renderer class has the API method
   public Object getConvertedValue(FacesContext context,
                                       UIComponent  component,
                                    Object       submittedValue)
   {...}
 
that converts the value. So it is the responsibility of the renderer class to convert the value. For example, the standard component class UIInput uses the specified converter. If you need to create a customer renderer, you will need to set the converter in the renderer.

Monday, June 11, 2012

How Are the JSF Tags Processed In The JSF Lifecycle

When the browser first connects to a jsp page, JSF will execute two phases Restore_View and Render_Response. It creates the view in the Restoer_View phase. But here it is just an empty ViewRoot and it is put into the facescontext. In the Render_Response phase, JSF will creates the actual UI components and build the view. It will also save the view into the session using the class com.sun.faces.application.StateManagerImpl. Here is what happens in the Render_Response phase.

(A) It calls ViewHandlerImpl.executePageToBuildView(...)

  1. The servlet reads the page.
  2. The page contains JSF tags. Each tag has an associated tag handler class. As tags are read, the tag handler classes are executed.
  3. The tag handlers collaborate with each other to build a component tree.
Now let's see some more details in step 2. How are those tag handler classes identified and retrieved? A jsp page declares the tag libraries it used in the beginning of the page. It may use one of the following two formats:
  • <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
  • <jsp:root xmlns:h="http://java.sun.com/jsf/html">
The uri value is used as the identifier by the servlet to locate the TLD file. The TLD file defines its uri value inside itself. The servlet will search for the TLD files at the standard locations to find the matching TLD file.

The TLD file also declares the class name for the tag. That is the tag handler to be invoked. The servlet can just use to class name to load the class.

The tag handler has an instance field for each attribute and the corresponding setter method. When the tag is processed, each tag attribute value is converted to a ValueExpression object, and the setter method is called.

The tag handler also knows the corresponding component class. It has the following method:

public String getComponentType(){...}
The implementation of the tag handler class returns a type value. However this type value is not necessarily the classname of the component class. It is used as an ID to find the class name in the faces-config.xml file. An example is as follows:
<component>
  <component-type>
     com.foo.Xyz
  </component-type>
  <component-class>
     com.foo.UIXyz
  </component-class>
</component>
The tag handler class uses the setProperties(UIComponent component) method to save the attribute values into the component class.

Note: A tag handler may not have a component class. For example, the <f:view> tag has the tag handler class com.sun.faces.taglib.jsf_core.ViewTag. Its getComponentType() method is as follows:

 /**
     * This should never get called for PageTag.
     */
 public String getComponentType() {
        assert (false);
        throw new IllegalStateException();
    }
The javadoc of this class says the following:
/**
 * All JSF component tags must be nested within a f:view tag.  This tag
 * corresponds to the root of the UIComponent tree.  It does not have a
 * Renderer. It exists mainly to provide a guarantee that all faces
 * components reside inside of this tag.
 */

The JSF tags implement the JSP Tag interface. So basically this is the JSP technology. What is different in JSF is that many of the JSF tags have associated component class. And these component classes are put together to form a component tree, which is a center piece in JSF technology.

In the JSP technology, a JSP tag can also have attributes. The tag implementation also needs the setter method for each of the attributes. When the JSP engine encounters the attributes in the tag, it calls the setter methods. Then when the doStartTag() method or other methods of the Tag interface is called, it can print out the attribute value or do anything related to the attribute. In JSF, there are also the setter methods for the attributes. But the tag handler has a new method setProperties(), where the attributes are saved to the component class of the tag.

So compared to the JSP technology, the basic strategy of JSF seems to be that instead of processing the tags and the attributes immediately, it temporarily saves the attribute values into the component tree, and then processes these values in different phases in the JSF lifecycle.

All the above happens in step (A). Now the next step is step (B).

(B) It calls ViewHandlerImpl.renderView(....) to render the page

In this step, all text in the JSP file that is not a JSF tag is passed through. The component classes execute the following render mehtods to produce the HTML text:

  1. encodeBegin()
  2. encodeChildren()
  3. encodeEnd()
These methods basically print out the HTML text.They use the attributes that the tag handlers have saved into them in step (A).

Next the encoded page is sent to the browser.

The browser displays the page. The user fills in the form fields and submits the page.

The JSF framework calls the RestoreView phase and then the ApplyRequestValues phase.

In the ApplyRequestValues phase, the decode() method of the component classes are executed. What does the decode() method do? The method will use the FacesContext to get the request parameter, process it, and calls the method setSubmittedValue(Object). This method is inherited from the class javax.faces.component.UIInput. Notice that this method takes only one parameter. So it seems that an UIInput tag can only deal with one value.

So the submitted value is stored in the component regardless if it is valid or not. But the decode() method will set a flag if it is valid. Subsequently in the JSF life cycle, the value will be converted and validated by the JSF framework.

The component class sets the converter for itself. It can also set its renderer.

References

1. Core JavaServer Faces second edition
2. http://java.sun.com/javaee/javaserverfaces/reference/docs/customRenderKit.html

Monday, May 21, 2012

The basic Code of Ajax

When developing web application using Ajax and JavaScript, the following are the three ways to start the Ajax code.
  • Use the "button" button. The following is some sample JSF code:
      <h:commondButton type="button" value="xyz" onclick="myAjaxFunction();" />
    
    Notice the button's type is "button", which means it is a push button and not a submit button. When a user activates that button, JSF does not submit the surrounding form. You can also use other non-button tags such as inputText to invoke Ajax. As long as an event causes a JavaScript event handler to run, you can put the Ajax code in that event handler to do the work.
  • Use the "submit" button. The following is some sample code used by IceFaces:
       <input type="submit" value="Submit" onclick="iceSubmit(form,this,event);return false;" />
    
    Notice that here the onclick function has to return false to disable the form submission.
  • Use the "submit" button, the JSF action, and the onclick function. The following is the sample code.
       <h:commandButton value="xyz"
     action="#{yourBean.doSomething}" onclick="return myAjaxFunction();" />
    
    Notice that this is a "submit" button because the default type of commandButton is "submit". But if the onclick function returns the value "false", the form will not be submitted, and the JSF "action" won't be invoked. If it returns true, the form will be submitted and the JSF "action" will be executed on the server side.
Now how to make the Ajax call in the web browser and get the response from the server? Basically you need to create a request object ( XMLHttpRequest for a non-IE browser or ActiveXObject for IE) , specify the parameters needed by the HTTP protocol( URL, HTTP method, etc) and send the request. You also attach a handler to the request object that will process the response from the server. There is the built-in function in the request object that will repeatedly invoke the handler with the news of the request's progress. In the handler, you check the status value and perform the action if the status indicates the response is ready.

So the special request object (XMLHttpRequest or ActiveXObject) is not just an object to send the request to the server, it is also an object that will process the response from the server using its built-in mechanism.

The sample code is below.


function myAjaxFunction(){
   var xhr;
   if (window.XMLHttpRequest){
      xhr = new XMLHttpRequest();
   }else if ( window.ActiveXObject){
      xhr = new ActiveXObject("Microsoft.XMLHTTP");
   }

   xhr.onreadystatechange = myHandler;
   xhr.open("GET", "myUrl", true);
   xhr.send(null);
}

function myHandler(){
  if ( xhr.readState == 4 ){
     if ( xhr.status == 200 ){
         var fooComponent = window.document.getElementById("fooComponentId");
         fooComponent.innerHTML = xhr.responseText;
     }
  }
}

In the above code, the URL value "myUrl" can be any URL value you want. For example, you can use "xyz.ajax". And you can use ".ajax" as the suffix for all the URLs used in Ajax. And then on the server side, you can map all such URLs to a servlet that will process all the Ajax requests. The following is a sample servlet for the Ajax request.
   public class AjaxServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
            response.setContentType("Text/plain");
            response.setHeader("Cache-Control", "no-cache");
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWritter().write("some content text here");
        }
 
   }

Friday, May 11, 2012

A Case Of Debugging On JSF

The getWriter() Error

Recently I was investigating a simple JSF web application that was deployed to weblogic 10 and got the following error
]] Root cause of ServletException.
java.lang.IllegalStateException: strict servlet API: cannot call getWriter() after getOutputStream()
 at weblogic.servlet.internal.ServletResponseImpl.getWriter(ServletResponseImpl.java:309)
 at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:186)
 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:108)
 at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:266)
 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:159)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
 at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
......
Since the first line says about weblogic, I thought it must be some problem caused by the weblogic. Later on, I found the error was actually caused by the isf-impl.jar library. The second line in the stack trace is
com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:186)
The class ViewHandlerImpl is from jsf-impl-1.2.jar (Implementation-Version: 1.2-b20-FCS). The method renderView() has the following code at line 186:
 responseWriter = newWriter.cloneWithWriter(response.getWriter());
The variable "response" here is the vendor implementation specific. And here it is the weblogic ServletResponseImpl. When it calls getWriter(), error happens. The problem here is actually not the class ServletResponseImpl. The ViewHandlerImpl should not have called resonse.getWriter(). After I changed the jar from jsf-impl-1.2.jar to jsf-impl-1.2_15.jar, the application worked fine. I checked the source code of ViewHandlerImpl.java in the new jar. This time there is no call to the response.getWriter().

A lesson from this is that the final place that gives error is not necessarily the place where the error needs to be fixed. Sometimes the error is caused by the upper stream class that does not follow the rule.

Another Stack Trace

The following is the starcktrace of another error related to the jar jsf-impl-1.2.jar. I listed it here so we can see the steps that lead to the compiling of a jsp page
Error 500--Internal Server Error 
weblogic.servlet.jsp.CompilationException: Failed to compile JSP /CustomerSearch.jsp
CustomerSearch.jsp:23:128: The method setVar(String) in the type DataTableTag is not applicable for the arguments (ValueExpression)
   
                                                                                                                               ^--------^

 at weblogic.servlet.jsp.JavelinxJSPStub.reportCompilationErrorIfNeccessary(JavelinxJSPStub.java:226)
 at weblogic.servlet.jsp.JavelinxJSPStub.compilePage(JavelinxJSPStub.java:162)
 at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:246)
 at weblogic.servlet.jsp.JspStub.prepareServlet(JspStub.java:191)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:235)
 at weblogic.servlet.internal.ServletStubImpl.onAddToMapException(ServletStubImpl.java:408)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:318)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
 at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:502)
 at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:248)
 at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:414)
 at com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:455)
 at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:139)
 at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:108)
 at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:266)
 at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:159)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
 at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
 at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
 at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592)
 at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
 at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
 at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202)
 at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108)
 at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
 
We can see that the weblogic uses its own classes to compile the jsp page from the following line and the lines before it:
at weblogic.servlet.jsp.JavelinxJSPStub.compilePage
(JavelinxJSPStub.java:162)
My conclusion is the following.
  1. Weblogic has its own JSP compiler implementation to compile a JSP file.
  2. When weblogic compiles a JSP page, it refers to the tld file to generate the java code for the tags used in the JSP page. The tld files can be contained in the jsf-impl jar file. However Weblogic does not need the java class files in the jsf-impl jar file. It just needs the tld file as the specification to generate the java code for JSP.
  3. The jsf-impl jar file contains both the tld file and the tag class files.
  4. In the error case shown in the stacktrace above, the java code generated by the weblogic JSP compiler and the tld file html_basic.tld in jsf-impl-1.2.jar does not match the tag class DataTableTag.class in jsf-impl-1.2.jar. So error occurs.

More on the TLD File

According to the book "Core JavaServer Faces, 2nd edition", page 373, the JSF implementation searches for TLD files in the following locations:
  • The WEB-INF directory or one of its subdirectories
  • The META-INF directory or any JAR file in the WEB-INF/lib directory
In the jsp file, you use one of the following formats to declare the tag library:
  <%@ tablib uri="http://java.sun.com/jsf/core" prefix="f" %>
or something like the following
  <html 
 xmlns:f="http://java.sun.com/jsf/core"
 >
You can see that it does not specify the location of the TLD file. So how does the server find the exact TLD file that matches the declaraion? The answer is to use the URI. In this case, the URI is http://java.sun.com/jsf/core. The TLD file has to define the URI attribute. The following is from the jsf-core.tld file:

  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>f</short-name>
  <uri>http://java.sun.com/jsf/core</uri>
  <description>
    The core JavaServer Faces custom actions that are independent of
    any particular RenderKit.
  </description>