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

    Seam Identity and WebClientSpec

    djn

      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
          ssilvert

          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
            djn

            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
              ssilvert

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

              Stan

              • 4. Re: Seam Identity and WebClientSpec
                ssilvert

                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
                  djn

                  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
                    djn

                    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
                      ssilvert

                      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
                        djn

                        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
                          djn

                          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
                            ssilvert

                            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
                              ssilvert

                              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)