11 Replies Latest reply on Oct 14, 2008 2:51 PM by Stan Silvert

    Seam Identity and WebClientSpec

    Daniel Nielsen Newbie

      Hi.

      When using WebClientSpec to test secure pages, I'm having an problems obtaining seam managed beans.

      The following testcase fails in the last assertNotNull:

      public void testWebClientSpecLogin() throws Exception {
       WebClientSpec wcSpec = new WebClientSpec("/login.seam");
       BlipZonesEELoginStrategy formAuth = new BlipZonesEELoginStrategy("admin", "admin");
       wcSpec.setInitialRequestStrategy(formAuth);
       JSFSession jsfSession = new JSFSession(wcSpec);
       JSFServerSession server = jsfSession.getJSFServerSession();
       assertEquals("/home.xhtml", server.getCurrentViewID());
      
       Object o = server.getManagedBeanValue("#{identity}");
       assertNotNull(o);
      }
      


      However, if I do the following, it passes correctly. The only difference is that I locate a link and click it before obtaining the identity component.

      public void testWebClientSpecLogin() throws Exception {
       WebClientSpec wcSpec = new WebClientSpec("/login.seam");
       BlipZonesEELoginStrategy formAuth = new BlipZonesEELoginStrategy("admin", "admin");
       wcSpec.setInitialRequestStrategy(formAuth);
       JSFSession jsfSession = new JSFSession(wcSpec);
       JSFServerSession server = jsfSession.getJSFServerSession();
       JSFClientSession client = jsfSession.getJSFClientSession();
       assertEquals("/home.xhtml", server.getCurrentViewID());
      
       Page page = client.getContentPage();
       assertTrue(page instanceof HtmlPage);
       HtmlPage hPage = (HtmlPage) page;
       HtmlAnchor htmlAnchor = hPage.getAnchorByHref("/blipzones/report/reportlist.seam?c=navitem_site_ReportSettings");
       assertNotNull(htmlAnchor);
       htmlAnchor.click();
      
       server = jsfSession.getJSFServerSession();
       assertEquals("/report/reportlist.xhtml", server.getCurrentViewID());
      
       Object o = server.getManagedBeanValue("#{identity}");
       assertNotNull(o);
      }
      


      The BlipZonesEELoginStrategy is a straightforward class, adapted from example code found on the JSFUnit wiki:

      public class BlipZonesEELoginStrategy extends SimpleInitialRequestStrategy {
      
      
       private String userName;
       private String password;
       private String submitComponent = "loginform:submit";
      
       public BlipZonesEELoginStrategy(String userName, String password) {
       this.userName = userName;
       this.password = password;
       }
      
      
       public void setSubmitComponent(String submitComponent) {
       this.submitComponent = submitComponent;
       }
      
       /**
       * Perform the initial request and provide FORM authentication
       * credentials when challenged.
       *
       * @param wcSpec The WebClient specification.
       * @return The requested page if authentication passed. Otherwise, return
       * the error page specified in web.xml.
       */
       public Page doInitialRequest(WebClientSpec wcSpec) throws IOException {
       HtmlPage page = (HtmlPage) super.doInitialRequest(wcSpec);
       setValue(page, "loginform:name", this.userName);
       setValue(page, "loginform:password", this.password);
       return clickSubmitComponent(page);
       }
      
       protected Page clickSubmitComponent(HtmlPage page) throws IOException {
       HtmlElement htmlElement = getElement(page, this.submitComponent);
       if (!(htmlElement instanceof ClickableElement)) {
       throw new IllegalStateException("Component with name=" + this.submitComponent + " is not a ClickableElement.");
       }
      
       ClickableElement clickable = (ClickableElement) htmlElement;
       return clickable.click();
       }
      
       protected void setValue(HtmlPage page, String elementName, String value) {
       HtmlElement element = getElement(page, elementName);
       if (!(element instanceof HtmlInput)) {
       throw new IllegalStateException("Component with name=" + elementName + " is not an HtmlInput element.");
       }
       HtmlInput inputElement = (HtmlInput) element;
       inputElement.setValueAttribute(value);
       }
      
       protected HtmlElement getElement(HtmlPage page, String elementName) {
       List<HtmlElement> elements = page.getHtmlElementsByName(elementName);
       if (elements.size() == 0) {
       throw new IllegalStateException("Component with name=" + elementName + " was not found on the login page.");
       }
       if (elements.size() > 1) {
       throw new IllegalStateException("More than one component with name=" + elementName + " was found on the login page.");
       }
      
       return elements.get(0);
       }
      
      }
      


        • 1. Re: Seam Identity and WebClientSpec
          Stan Silvert Master

          Is {#identity} the Seam identity?

          Are you certain that {#identity} really exists after login? Try putting this in your home.xhtml page:

          <h:outputText value="identity = #{identity}"/>


          Also, you don't need to call jsfSession.getJSFServerSession() after each request. There are callbacks that make the JSFClientSession and JSFServerSession stay up to date.

          Stan

          • 2. Re: Seam Identity and WebClientSpec
            Daniel Nielsen Newbie

            Hi.

            Yes, #{identity} exists and it is the seam identity component.

            The line you requested gives the following output:

            identity = org.jboss.seam.security.RuleBasedIdentity@1a76fe3
            


            Another testcase, which passes:

            public void testSuccessLogin() throws IOException {
             // Send an HTTP request for the initial page
             JSFSession jsfSession = new JSFSession("/login.seam");
            
             // A JSFClientSession emulates the browser and lets you test HTML
             JSFClientSession client = jsfSession.getJSFClientSession();
            
             // A JSFServerSession gives you access to JSF state
             JSFServerSession server = jsfSession.getJSFServerSession();
             //enter values and log in
             client.setValue("name", "admin");
             client.setValue("password", "admin");
             client.click("submit");
            
             assertEquals("/home.xhtml", server.getCurrentViewID());
             assertTrue(server.getManagedBeanValue("#{identity.loggedIn}").equals(true));
            }
            


            I am aware that I'm not required to call getJSFServerSession again, the line was a leftover from a copy&paste operation. Thank you for pointing it out.



            • 3. Re: Seam Identity and WebClientSpec
              Stan Silvert Master

              I think I see the problem. I should have a fix for you to try out shortly.

              Stan

              • 4. Re: Seam Identity and WebClientSpec
                Stan Silvert Master

                https://jira.jboss.org/jira/browse/JSFUNIT-172

                This should be fixed now. Can you do a build from SVN and give it a try?

                Stan

                • 5. Re: Seam Identity and WebClientSpec
                  Daniel Nielsen Newbie

                  That specific test case now passes.

                  Unfortunately, the fix seems to have re-introduced the spurious failures I've reported earlier. Only now, they are related to the identity component and not one of my own.

                  Failure trace from testcase:

                  Could not instantiate Seam component: org.jboss.seam.security.identity
                  
                  org.jboss.seam.InstantiationException: Could not instantiate Seam component: org.jboss.seam.security.identity
                  at org.jboss.seam.Component.newInstance(Component.java:1986)
                  at org.jboss.seam.contexts.Contexts.startup(Contexts.java:304)
                  at org.jboss.seam.contexts.Contexts.startup(Contexts.java:278)
                  at org.jboss.seam.contexts.Lifecycle.beginSession(Lifecycle.java:191)
                  at org.jboss.seam.contexts.ServletLifecycle.beginSession(ServletLifecycle.java:124)
                  at org.jboss.jsfunit.framework.WebConversationFactory.clearSession(WebConversationFactory.java:185)
                  at org.jboss.jsfunit.framework.WebConversationFactory.makeWebClient(WebConversationFactory.java:147)
                  at org.jboss.jsfunit.framework.WebClientSpec.<init>(WebClientSpec.java:115)
                  at org.jboss.jsfunit.framework.WebClientSpec.<init>(WebClientSpec.java:93)
                  at org.jboss.jsfunit.framework.WebClientSpec.<init>(WebClientSpec.java:77)
                  at org.jboss.jsfunit.jsfsession.JSFSession.<init>(JSFSession.java:57)
                  at com.blipsystems.blipzones.jsfunit.LoginTest.setUp(LoginTest.java:48)
                  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:224)
                  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:224)
                  at org.apache.cactus.server.ServletTestRedirector.doPost(ServletTestRedirector.java)
                  at org.jboss.jsfunit.framework.JSFUnitServletRedirector.doPost(JSFUnitServletRedirector.java:45)
                  at org.apache.cactus.server.ServletTestRedirector.doGet_aroundBody0(ServletTestRedirector.java:72)
                  at org.apache.cactus.server.ServletTestRedirector.doGet_aroundBody1$advice(ServletTestRedirector.java:224)
                  at org.apache.cactus.server.ServletTestRedirector.doGet(ServletTestRedirector.java)
                  at org.jboss.jsfunit.framework.JSFUnitServletRedirector.doGet(JSFUnitServletRedirector.java:51)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.jboss.jsfunit.framework.JSFUnitFilter.doFilter(JSFUnitFilter.java:122)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
                  at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
                  at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                  at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
                  at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                  at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                  at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
                  at java.lang.Thread.run(Thread.java:619)
                  Caused by: java.lang.IllegalStateException
                  at com.sun.faces.context.FacesContextImpl.assertNotReleased(FacesContextImpl.java:428)
                  at com.sun.faces.context.FacesContextImpl.getELContext(FacesContextImpl.java:172)
                  at org.jboss.jsfunit.context.JSFUnitFacesContext.getELContext(JSFUnitFacesContext.java:217)
                  at org.jboss.seam.faces.FacesExpressions.getELContext(FacesExpressions.java:36)
                  at org.jboss.seam.core.Expressions$1.createExpression(Expressions.java:106)
                  at org.jboss.seam.core.Expressions$1.toUnifiedValueExpression(Expressions.java:98)
                  at org.jboss.seam.core.Expressions$1.getValue(Expressions.java:111)
                  at org.jboss.seam.Component$ELInitialValue.getValue(Component.java:2370)
                  at org.jboss.seam.Component.initialize(Component.java:1392)
                  at org.jboss.seam.Component.instantiateJavaBean(Component.java:1318)
                  at org.jboss.seam.Component.instantiate(Component.java:1271)
                  at org.jboss.seam.Component.newInstance(Component.java:1970)
                  ... 48 more
                  


                  • 6. Re: Seam Identity and WebClientSpec
                    Daniel Nielsen Newbie

                    hi.

                    Further investigation of this issue shows that I had to revert to revision 361 in order to make my tests pass consistently.

                    This leads me to conclude that the changes introduced in revision 362 - a fix for JSFUNIT-170 breaks JSFUnit for me.

                    Regards,
                    ./Daniel

                    • 7. Re: Seam Identity and WebClientSpec
                      Stan Silvert Master

                      The stack trace you posted is showing that Seam is choking on a call I added in JSFUNIT-171 where I call Seam's ServletLifecycle.beginSession(). So there is probably some more work I need to do to make sure Seam is properly initialized.

                      I tried the application you sent me with the latest JSFUNIT build and it still passes. There are some new stack traces from Seam, but the tests themselves still pass.

                      So I think I have an idea of what is happening. If you can update your sample app to show your problem then that would be very helpful because I can't recreate what you are seeing. I probably won't be able to work on it until Monday.

                      Stan

                      • 8. Re: Seam Identity and WebClientSpec
                        Daniel Nielsen Newbie

                        I might get the time to look at the sample app this weekend.

                        Otherwise, It'll have to wait until next week.

                        Regards,
                        ./Daniel

                        • 9. Re: Seam Identity and WebClientSpec
                          Daniel Nielsen Newbie

                          Hi.

                          I've updated the example app and uploaded a new zipfile. You can get it using the same connection details as last time.

                          The change is that I now use drools for identity management.

                          The error happens about 1 in every 10 test runs.

                          Regards,
                          ./Daniel

                          • 10. Re: Seam Identity and WebClientSpec
                            Stan Silvert Master

                            Hi Daniel,

                            Just wanted to let you know that I finally figured this out. There was a ThreadLocal that was not always cleaned up properly. I need to do some regression testing, but I should be able to check in a fix this afternoon.

                            Stan

                            • 11. Re: Seam Identity and WebClientSpec
                              Stan Silvert Master

                              This should be fixed now. Please give it a try and let me know what you find.

                              https://jira.jboss.org/jira/browse/JSFUNIT-173

                              There is still one error that pops up in your test, but it only happens about 1 in 500 tests. The stack trace seems unrelated to problem above as it is a known issue that should be fixed in JSF 1.2_10. The odd thing is that I've never seen it happen in quite this way.

                              java.lang.IllegalStateException: No phase id bound to current thread (make sure you do not have two SeamPhaseListener instances installed)
                               at org.jboss.seam.contexts.PageContext.getPhaseId(PageContext.java:162)
                               at org.jboss.seam.contexts.PageContext.isBeforeInvokeApplicationPhase(PageContext.java:174)
                               at org.jboss.seam.contexts.PageContext.getCurrentWritableMap(PageContext.java:90)
                               at org.jboss.seam.contexts.PageContext.remove(PageContext.java:104)
                               at org.jboss.seam.Component.newInstance(Component.java:1984)
                               at org.jboss.seam.Component.getInstance(Component.java:1876)
                               at org.jboss.seam.Component.getInstance(Component.java:1855)
                               at org.jboss.seam.Component.getInstance(Component.java:1832)
                               at org.jboss.seam.Component.getInstance(Component.java:1827)
                               at org.jboss.seam.faces.FacesPage.instance(FacesPage.java:92)
                               at org.jboss.seam.core.ConversationPropagation.restorePageContextConversationId(ConversationPropagation.java:85)
                               at org.jboss.seam.core.ConversationPropagation.restoreConversationId(ConversationPropagation.java:58)
                               at org.jboss.jsfunit.seam.SeamRequestListener.restoreConversation(SeamRequestListener.java:70)
                               at org.jboss.jsfunit.seam.SeamRequestListener.afterRequest(SeamRequestListener.java:61)
                               at org.jboss.jsfunit.framework.JSFUnitWebConnection.notifyListenersAfter(JSFUnitWebConnection.java:102)
                               at org.jboss.jsfunit.framework.JSFUnitWebConnection.getResponse(JSFUnitWebConnection.java:83)
                               at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1477)
                               at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1435)
                               at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:327)
                               at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:388)
                               at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:373)
                               at org.jboss.jsfunit.framework.SimpleInitialRequestStrategy.doInitialRequest(SimpleInitialRequestStrategy.java:47)
                               at org.jboss.jsfunit.framework.WebClientSpec.doInitialRequest(WebClientSpec.java:236)
                               at org.jboss.jsfunit.jsfsession.JSFSession.<init>(JSFSession.java:78)
                               at org.jboss.jsfunit.jsfsession.JSFSession.<init>(JSFSession.java:57)
                               at com.example.jsfunit.LoginTest.testContains(LoginTest.java:38)
                               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:224)
                               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.JSFUnitServletRedirector.doPost(JSFUnitServletRedirector.java:45)
                               at org.apache.cactus.server.ServletTestRedirector.doGet_aroundBody0(ServletTestRedirector.java:72)
                               at org.apache.cactus.server.ServletTestRedirector.doGet_aroundBody1$advice(ServletTestRedirector.java:217)
                               at org.apache.cactus.server.ServletTestRedirector.doGet(ServletTestRedirector.java)
                               at org.jboss.jsfunit.framework.JSFUnitServletRedirector.doGet(JSFUnitServletRedirector.java:51)
                               at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
                               at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
                               at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                               at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                               at org.jboss.jsfunit.framework.JSFUnitFilter.doFilter(JSFUnitFilter.java:124)
                               at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                               at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                               at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                               at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                               at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                               at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                               at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
                               at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
                               at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                               at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                               at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                               at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                               at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                               at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
                               at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                               at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                               at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
                               at java.lang.Thread.run(Thread.java:595)