1 2 Previous Next 21 Replies Latest reply on Sep 17, 2007 8:16 AM by ssilvert

    Problems with taglibs in JSFUnit

    sai001

      Hi, I'm a developer that's currently using JSFUnit for JSF testing purposes.

      I've downloaded and tested your example (hellojsf-jsfunit) without any problems UNTIL I added personalised tags, including of course their definition in the header of the jsp file as follows:
      <%@ taglib uri="/WEB-INF/Blv.tld" prefix="componentes"%>
      <%@ taglib uri="jsf-jup-comp" prefix="Componentes-jupiter"%>

      The problem is, I can't only have access to the elements that are declared with my own "propietary" tags like this:
      <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
      denominacion="#{enged1id.codusu}"
      id="codusu"
      ..../>

      but when these are added, I can't even access the elements I used before without any problems! I mean, those that were declared in the average <h:...> tags!!!
      For example, the jsp file I'm using has an inputText tag named "ejerta":

      <h:inputText id="ejerta" value="#{enged1id.ejerta}" size="6" styleClass="camponormal" maxlength="4">
      </h:inputText>

      When testing a very simple variant of this jsp file I have no problems,

      client.setParameter("ejerta","2010");
      works OK and the test succeeds, but when I add other tags different than <h:...> and <f:...>, JSFUnit doesn't recognize the form that has been declared in the jsp page, and client.setParameter(...) fails. I get a NullPointerException (see the trace below)


      java.lang.NullPointerException
      at org.jboss.jsfunit.facade.ClientFacade.setParameter(ClientFacade.java:176)
      at pruebas.testJSF.testInput(testJSF.java:111)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at org.apache.cactus.internal.AbstractCactusTestCase.runBareServer(AbstractCactusTestCase.java:153)
      at org.apache.cactus.internal.server.AbstractWebTestCaller.doTest(AbstractWebTestCaller.java:119)
      at org.apache.cactus.internal.server.AbstractWebTestController.handleRequest_aroundBody0(AbstractWebTestController.java:93)
      at org.apache.cactus.internal.server.AbstractWebTestController.handleRequest_aroundBody1$advice(AbstractWebTestController.java:217)
      at org.apache.cactus.internal.server.AbstractWebTestController.handleRequest(AbstractWebTestController.java)
      at org.apache.cactus.server.ServletTestRedirector.doPost_aroundBody2(ServletTestRedirector.java:101)
      at org.apache.cactus.server.ServletTestRedirector.doPost_aroundBody3$advice(ServletTestRedirector.java:217)
      at org.apache.cactus.server.ServletTestRedirector.doPost(ServletTestRedirector.java)
      at org.jboss.jsfunit.framework.JSFUnitCactusRedirector.doPost(JSFUnitCactusRedirector.java:67)
      at org.jboss.jsfunit.framework.JSFUnitCactusRedirector.doGet(JSFUnitCactusRedirector.java:78)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
      at com.evermind.server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:846)
      at com.evermind.server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:397)
      at com.evermind.server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:866)
      at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:451)
      at com.evermind.server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:218)
      at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:119)
      at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:112)
      at oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:245)
      at oracle.oc4j.network.ServerSocketAcceptHandler.procClientSocket(ServerSocketAcceptHandler.java:231)
      at oracle.oc4j.network.ServerSocketAcceptHandler.access$1000(ServerSocketAcceptHandler.java:33)
      at oracle.oc4j.network.ServerSocketAcceptHandler$AcceptHandlerHorse.run(ServerSocketAcceptHandler.java:820)
      at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
      at java.lang.Thread.run(Thread.java:595)


      And the big question is:
      Is JSFUnit unable to handle other tags different than
      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> and
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>??

      I hope not!

      Thanks a lot in advance for your replies and thanks also for sharing this neat piece of testing sotware with the rest of the world.

      Cheers.

        • 1. Re: Problems with taglibs in JSFUnit
          ssilvert

          Hi. Thanks for your interest in JSFUnit.

          The problem is not with the kind of tag you are using. I think the problem is with the NamingContainer you set up in the ClientFacade. You are probably using a component that is a NamingContainer.

          Frankly, it looks like this is something I need to improve. Of course, this is pre-alpha code so I ask your forgiveness. :-)

          Anyhow, to fix the problem for now, you need to know the NamingContainer path to the component you are setting. You can find this out if you look at the HTML source of the page. The full NamingContainer path will be the ID of the component in the HTML source.

          For instance, if I had:

          <f:view>
           <h:form id="form1">
           <f:subview id="subview1">
           <m:mycomponent id="mine" value="2009"/>
           </f:subview>
           </h:form>
          </f:view>


          form1 and subview1 are both components that are NamingContainers. So the NamingContainer path to mine is "form1:subview:mine". To reference this component with the ClientFacade, you need to say

          clientFacade.setNamingContainer("form1:subview");
          clientFacade.setParameter("mine","2010");


          or, you can just say:
          clientFacade.setParameter("form1:subview:mine", "2010);
          


          I'm going to be available infrequently for the next week. But I'll try to follow up as much as I can if you are still having trouble.

          Regards,

          Stan

          • 2. Re: Problems with taglibs in JSFUnit
            sai001

            Thanks for your advice, but unfortunately the solution you proposed didn't solve the problem.

            I think there really is an issue with tag handling in JSFUnit, when using tags different than h: and f:.

            Let me show you the code I'm working in.
            On the one hand, we have this jsp file:

            <!DOCTYPE HTML PUBLIC "-//W3C//Dtd HTML 4.01 Transitional//EN" "http://www.w3.org/tr/html4/loose.dtd">
            <%/******************************************************************************
            ** Pagina: Enged1id
            ** Descripción: Abrir de entradas a la gestión
            ** Autor: POC001
            ** Fecha: 08-03-2007
            /********************************************************************************/%>
            <%@ page contentType="text/html;charset=windows-1252" language="java" errorPage="/jsp/generales/error3.jsp" %>
            <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
            <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
            <%@ taglib uri="/WEB-INF/Blv.tld" prefix="componentes"%>
            <%@ taglib uri="jsf-jup-comp" prefix="Componentes-jupiter"%>
            
            <script type="text/javascript">
             function clear_formulario ()
             {;}
            </script>
            
            <f:view>
            
             <h:form id="formulario" >
             <table id="tabla1" border="0" cellpadding="0" cellspacing="0" class="datos" width="762">
             <tr>
             <td valign="top" COLSPAN="2" class="datos">
             <br></br>
             </td>
            
             <tr>
             <td valign="top" class="datos" colspan="2">
            
            
             <table id="tabla2" width="700" border="0" class="datos" ALIGN="center">
             <tr align="LEFT" class="fila_par" height="26">
             <td width="207">
             <h:outputText value="Usuario:"/>
             </td>
             <td colspan="2">
            
             <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
             denominacion="#{enged1id.codusu}"
             id="codusu"
             onBlur="this.value = this.value.toUpperCase();denominacion(\'codusu\',\'desc_codusu\','','',\'USURV3LN\')"
             onClick="abrirUsurk1dn(\'codusu\',\'desc_codusu\');return(false);"/>
            
             </td>
             </tr>
            
             <tr align="LEFT" class="fila_par">
             <td width="207">
             <h:outputText value="Ejercicio:"/>
             </td>
             <td colspan="2">
             <h:inputText id="ejerta" value="#{enged1id.ejerta}" size="6" styleClass="camponormal" maxlength="4">
             </h:inputText>
             </td>
             </tr>
             </table>
             <p>
             <table width="700" border="0" align="center">
             <tr>
             <td align="center">
             <%-- <h:commandButton id="aceptar" image="../../../../estilos/images/botones/jupiter/aceptar.gif" action="#{enged1id.aceptar}"/> --%>
             <h:commandButton id="aceptar" action="#{enged1id.aceptar}"/>
            
             </td>
             <td align="center">
             <h:commandButton onclick="cancelar();return(false);" id="cancelar" />
             </td>
             <td align="center">
             <h:commandButton action="#{enged1id.salir}" immediate="true"/>
             </td>
             </tr>
             </table>
             <h:inputHidden id="accion" value="aceptar"/>
             <h:inputHidden id="denominacion"/>
             </td>
             </tr>
             <tr>
             <td> </td>
             </tr>
            
             </table>
             </h:form>
            </f:view>


            (btw, that tag was added to solve another problem we faced during our initial testing, the program required a "clear_form" function in order to work!)

            As you can see in the code, we are working with a not-too-complex jsp file, consisting of a form including two nested tables that contain two tags: an average tag named ejerta:
            <h:inputText id="ejerta" ...>

            and a "customised" tag named codusu:
            <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
             denominacion="#{enged1id.codusu}"
             id="codusu"...>

            This last tag is of course defined in one of the taglibs declared in the header.
            We also have three buttons: aceptar (accept), cancelar (cancel) and salir (exit) (No need to thank me for the brief course on spanish lol)
            Only the aceptar button is id'ed, because it's the only one we use for testing, and submitting works fine with simpler JSFUnit tests not involving our customised tags.

            On the other hand, we have our testing code. A very simple testing code, in fact:
            public class testJSF extends ServletTestCase
            {
            
             private ClientFacade client;
             public void setUp() throws IOException, SAXException
             {
             try
             { this.client = new ClientFacade("/enged1id.faces"); //only works with scope = session!!
             }
             catch(Exception e){System.out.println("ERROR: No se crea bien el ClientFacade");}
             }
            
             public static Test suite()
             {
             return new TestSuite(testJSF.class);
             }
            
             public void testInput() throws IOException, SAXException
             {
            ServerFacade server = new ServerFacade("formulario");
            client.setNamingContainer("formulario");
            //client.setNamingContainer("formulario:tabla1:tabla2");
            client.setParameter("ejerta","2010");
            //client.setParameter("ejerta","2010");
            //client.setParameter("formulario:tabla1:tabla2:ejerta","2010");
            
            client.submit("aceptar");
            assertEquals("2010",server.getManagedBeanValue("#{enged1id.ejerta}"));
            }
            }


            (I've commented the code I used when trying your solution)

            The facts are:
            -When executing this test, it fails in the way I showed on my first post.
            -When deleting this element the test suceeds:
            <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
            denominacion="#{enged1id.codusu}"
            id="codusu"...>
            -I don't know if the nested tables in my jsp files have something to do with the problems I'm facing... they are probably NOT part of the problem as deleting them and keeping the "codusu" component does still generate the same exception, and only deleting that component makes the test succeed.

            As you can see, the problem seems to be the use of customised tags.

            Thank you again for your time and dedication, I hope these problems help to improve your JSF testing tool, which is by far the best and most intuitive of those I've tried.

            Have a nice weekend!

            • 3. Re: Problems with taglibs in JSFUnit
              sai001

              Oops... it seems that a part of the previous message was somehow "lost in space"

              In the missing part of the message I described the different components of the JSP file: two nested tables including a personalised tag and an average h:input tag AND I pointed out that I had to add this script to solve a previous issue:

              function clear_formulario ()
              {;}

              We were required to define a "clear_form" function to avoid another Exception.

              I hope you can throw light upon the problem...

              • 4. Re: Problems with taglibs in JSFUnit
                ssilvert

                I think I can shed light on the problem. Right now, ClientFacade doesn't actually know anything about tags or JSF. ClientFacade is a facade for HttpUnit. So if you are getting a NullPointerException in the ClientFacade API then it is actually a problem with the way we are fronting HttpUnit. It's a bug that needs to be fixed.

                I'm back home for now. Hopefully, I can get it fixed today.

                Stan

                • 5. Re: Problems with taglibs in JSFUnit
                  ssilvert

                  BTW, if you look at the test HelloJSFIntegrationTest, it shows how to do testing without the ClientFacade and ServerFacade. SimplifiedHelloJSFIntegrationTest is a newer version of the same tests written using the Facades. The Facades were created to make these tests easier to write. But at this point the Facades are a bit unstable.

                  Bug reference: http://jira.jboss.com/jira/browse/JSFUNIT-5

                  Stan

                  • 6. Re: Problems with taglibs in JSFUnit
                    ssilvert

                    This won't get done today. I'm going to make some big changes to ClientFacade. I want to make it so that the user of the ClientFacade doesn't need to know anything about a NamingContainer. The Facade will just try to find the component based on the last part of the ID and then do the right thing.

                    I won't be able to work on this at all next week though. After that, I should be able to devote most of my time on JSFUnit for several weeks. Stay tuned.

                    Stan

                    • 7. Re: Problems with taglibs in JSFUnit
                      sai001

                      Hi again, Stan.
                      I tried doing the same thing using HelloJSFIntegrationTest as my base code. And a couple of very interesting things are happening here:
                      -Again, the test fails. The WebRequest and WebResponse objects are created (they aren't null at least), but the object form is null when I try
                      WebForm form = webResponse.getFormWithID("formulario");
                      -The problem vanishes and the test succeeds if I delete the following code from my jsp file:

                       <tr align="LEFT" class="fila_par" height="26">
                       <td width="207">
                       <h:outputText value="Usuario:"/>
                       </td>
                       <td colspan="2">
                      
                       <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
                       denominacion="#{enged1id.codusu}"
                       id="codusu"
                       onBlur="this.value = this.value.toUpperCase();denominacion(\'codusu\',\'desc_codusu\','','',\'USURV3LN\')"
                       onClick="abrirUsurk1dn(\'codusu\',\'desc_codusu\');return(false);"/>
                      
                       </td>
                       </tr>
                      


                      So it seems that whatever is going wrong with the tags (at least with all that are different than h: or f:) is not JSFUnit's fault, but something going wrong with httpUnit when parsing personalised tags.
                      What a shame! :(

                      Thanks once more for your time.

                      • 8. Re: Problems with taglibs in JSFUnit
                        ssilvert

                        Have you looked at the HTML generated with your JSP? That is what you need to see to properly set fields using HTTPUnit.

                        Even if it is a problem with HTTPUnit, it will get fixed one way or another - even if I have to do it myself. But alas, I can't work on it until next week.

                        Stan

                        • 9. Re: Problems with taglibs in JSFUnit
                          sai001

                          Yes, I took a look at the HTML code, and the tags inside the form had this format: "form:tag", therefore ignoring being nested or not on tables.
                          So... the problem remains unsolved:
                          adding a personalised tag like this will make the test fail. Otherwise, it'll succeed.

                          <componentes:Blv value="#{enged1id.codusu}" maxLength="6"
                           denominacion="#{enged1id.codusu}"
                           id="codusu"
                           onBlur="this.value = this.value.toUpperCase();denominacion(\'codusu\',\'desc_codusu\','','',\'USURV3LN\')"
                           onClick="abrirUsurk1dn(\'codusu\',\'desc_codusu\');return(false);"/>
                          


                          The Exception being thrown is:
                          java.lang.NullPointerException
                          at org.jboss.jsfunit.facade.ClientFacade.setParameter(ClientFacade.java:176)
                          and client.getNamingContainer() returns nothing!

                          I repeat, this problem doesn't happen when testing the code with average h:... and f:... tags.

                          We'll wait for the upgrades, thanks for your time and support.


                          • 10. Re: Problems with taglibs in JSFUnit
                            sai001

                            I've done some additional research and this is what I've found:
                            -When the taglibs that define the personalised tags on the jsp header (such as "<%@ taglib uri="/WEB-INF/Blv.tld" prefix="componentes"%>") are deleted and the personalised tag is not used in the test (i.e. it's not checked for results), the test SUCCEEDS. Duh!
                            -When the taglibs are deleted and the tag is used in the test, the test returns the following Exception: No parameter named 'formulario:codusu' is defined in the form. Is the logical result to obtain, because we are making use of a non defined tag.
                            -When the taglibs are present on the jsp file but the tag is deleted and of course not queried on the test, the test succeeds (this means, the big problem underneath the use of personalised tags is not related to a failure in the parsing of taglibs definitions, the error only shows up when making use of them)

                            The bottom line is the same as always: JSFUnit doesn't support the use of customised tags, neither does httpUnit.

                            PS. Converting the personalised tags into simpler "h:inputText" tags solves the problem... but we want to test the original JSP file, not the result of modifying it in order to be accepted by the test suite! :)

                            • 11. I think it's now solved.
                              ssilvert

                              I've just committed a refactored version of the ClientFacade and ServerFacade. Now, whenever you call a method that takes a componentID, it will search the JSF component tree for a match. This way, you don't need to specify the entire client ID unless the componentID is used twice on the same page (very rare).

                              You will need to build JSFUnit from the latest source. There are instructions for that at http://www.jsfunit.com. Let me know if you need any help.

                              So now I think your original code will work. Please let me know. If it still doesn't work then I want to work more closely with you to get it fixed. Thanks for your early feedback. It has been very valuable.

                              Stan

                              • 12. Re: Problems with taglibs in JSFUnit
                                ssilvert

                                I was looking through your code again and I realized something I should have asked you a long time ago. Is the custom tag library a JSF tag library? Does it implement/extend the JSF component interfaces/classes? If no, then the new JSFUnit code won't help because it relies on the JSF component tree to find the proper client ID.

                                If it is not a JSF tag library then one option would be to convert your library to JSF so that it can be managed by the JSF lifecycle. That has some obvious advantages, but it might take some time to do.

                                Even if this is an ordinary taglib, all hope is not lost. You should be able to use JSFUnit to get handles to the HttpUnit objects that you need to manipulate the HttpRequest. I know that you tried this before, but I'm willing to take a closer look to see if it can be done.

                                If the end result of your tag is that it puts a field on a form then there is no reason that HttpUnit shouldn't be able to set that field. It's just a matter of giving it the right field name. If not, I'm missing something and I need to see your HTML and possibly your taglib code.

                                Stan

                                • 13. Re: Problems with taglibs in JSFUnit
                                  sai001

                                  Hi, i know i didn't write for a long time but i was on holidays and i don't have a lot of free time, i tried the new classes but the problem continues.

                                  If i use my personal tag, the execution fail but i eliminate everything what keep relation with my personal tags, works again.

                                  what can i do ? because one of the best point of view is use the personal tags.

                                  thanks for your time

                                  • 14. Re: Problems with taglibs in JSFUnit
                                    ssilvert

                                    If this is not a JSF tag then you don't want to use the ClientFacade with it. ClientFacade is only for JSF.

                                    But you can drop down one level of abstraction to HttpUnit and I'm sure it will work. It's a little harder because you will deal with your tag at the HTML level. So you need to look at the tag-generated HTML and see the name or ID of the field or fields you want to set. Then submit the form. If you send me the HTML page that your custom tag helped create, I can suggest some sample code to do this.

                                    Regards,

                                    Stan

                                    1 2 Previous Next