-
1. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 19, 2008 3:30 PM (in response to merlin-hst)You got this error because the previous request returned UnexpectedPage. According to the HtmlUnit javadoc, UnexpectedPage means that the server returned an unexpected content type.
You should be able to find out what that unexpected content type is by saying:
JSFClientSession.getContentPage().getWebResponse().getContentType()
Stan -
2. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 20, 2008 4:53 AM (in response to merlin-hst)Hi Stan,
thanks for your answer. ContentType is indeed "image/gif". But why ? I assume that the right page is loaded byassertEquals("/presentation/access_right_assoc.xhtml", JSFServerSession.getCurrentViewID());
That page contains a command button with the id "edit_role_assocs_generatelink". I also check that the button is rendered withassertNotNull(JSFServerSession.findComponent(id))
andassertTrue(JSFServerSession.findComponent(id).isRendered())
So for me it looks like the button is rendered correctly, but when I ty to execute a click on that button withJSFClientSession.click(id)
the exception occurs. So what I'm doing wrong ? Could it be the reason that I have to click on a gif to load the above page? I'm doing a similar test with a another with no problems.
thanks, Lothar -
3. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 20, 2008 7:19 AM (in response to merlin-hst)Are you setting the content type somewhere? Everything on the server side looks correct, but HtmlUnit is having a problem understanding the page sent back to the browser. If the content type is set to "image/gif" and it is really a "text/html" page then that is your problem. You would need to just set the correct content type.
You can call JSFClientSession.getContentPage().getWebResponse() and use the WebResponse API to dump the content and all the headers to see everything that came back from the server.
If you can post your xhtml page and your JSFUnit code I might be able to get a better idea of what is happening.
Stan -
4. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 20, 2008 12:41 PM (in response to merlin-hst)Hi Stan,
I don't set the content type by myself. I'll try to post a simplified example:public abstract class BaseJSFTestNew extends ServletTestCase { public BaseJSFTestNew(String name) { super(name); } @Override protected final void setUp() throws Exception { super.setUp(); this.afterSetUp(); } protected void afterSetUp() throws Exception { // Send an HTTP request for the initial page jsfSession = new JSFSession("/faces/presentation/login.xhtml"); jsfSession.getWebClient().setRedirectEnabled(true); client = jsfSession.getJSFClientSession(); server = jsfSession.getJSFServerSession(); } protected void doLogin( ) throws IOException { // plant_search assertEquals("/presentation/login.xhtml", getCurrentViewName()); HtmlInputText login = (HtmlInputText)findComponent( "field_logon_username"); HtmlInputSecret pwd = (HtmlInputSecret)findComponent( "field_logon_password"); assertTrue(findComponent(login.getId()).isRendered()); assertTrue(findComponent(pwd.getId()).isRendered()); getClient().setValue(login.getId(), "xxx"); getClient().setValue(pwd.getId(), "xxx"); getClient().click("logon_logon"); assertEquals("/presentation/plant_search.xhtml", getCurrentViewName()); } protected void validateComponent(String componentId, Class<? extends UIComponent> type) { UIComponent component = findComponent(componentId); assertNotNull(component); if (type != null) { assertTrue(component.getClass().equals(type) || type.isAssignableFrom(component.getClass())); } assertTrue(component.isRendered()); } ... public class PublicLinkJSFTest extends BaseJSFTestNew { public PublicLinkJSFTest(String name) { super(name); } public void testPublicLink() throws IOException { doLogin(); String id = "search_search"; validateComponent(id, HtmlCommandButton.class); getClient().click(id); ... id = "menu_nav1_item17_item22"; //it's a gif and the client id - but seems to works getClient().click(id); assertEquals("/presentation/access_right_assoc.xhtml", getCurrentViewName()); id = "edit_role_assocs_generatelink"; validateComponent(id, HtmlCommandButton.class); getClient().getContentPage().getWebResponse().getContentType(); // image/gif // System.out.println(getClient().getPageAsText()); //causes IllegalStateException: This page can not be converted to text. Page type is com.gargoylesoftware.htmlunit.UnexpectedPage getClient().click(id); //exception }
My facelets site looks like:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a="http://www.conergy.com/jsf" xmlns:c="http://java.sun.com/jstl/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:core="http://www.conergy.de/jsf/core" xmlns:ex="http://www.conergy.com/jsf/components" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j"> <f:loadBundle basename="resources.resource" var="bundle"/> <head> <link rel="stylesheet" href="#{facesContext.externalContext.requestContextPath}/css/conergy/sunreader.css" type="text/css" /> <link rel="SHORTCUT ICON" href="#{facesContext.externalContext.requestContextPath}/image/conergy/favicon.ico" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="expires" content="0" /> <!-- <t:div id="refresh" rendered="#{not authorizationController.jsfUnitRequest}"> <meta http-equiv="refresh" content="#{authorizationController.sessionTimoutInterval}; URL=#{facesContext.externalContext.requestContextPath}/loginExpired.jsp"/> </t:div> --> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/sr2.js" type="text/javascript"></script> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/alarms.js" type="text/javascript"></script> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/common.js" type="text/javascript"></script> <h:outputText value="#{authorizationController.ie7}" /> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/jquery.js" type="text/javascript"></script> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/jquery.cookie.js" type="text/javascript"></script> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/webtoolkit.jscrollable.js" type="text/javascript"></script> <script language="javascript" src="#{facesContext.externalContext.requestContextPath}/js/webtoolkit.scrollabletable.js" type="text/javascript"></script> <script> jQuery.noConflict(); </script> <title><ui:insert name="title">SunReader</ui:insert></title> </head> <body> ... <t:saveState id="save1" value="#{accessRightAssocController.plantAccess}" /> <rich:messages globalOnly="false" errorClass="errorMessage" infoClass="infoMessage"/> <c:choose> <c:when test="#{accessRightAssocController.plantAccessAssocsExist}"> <ui:include src="components/plantaccess_assoc_list.xhtml"/> </c:when> <c:otherwise> <h:outputText styleClass="text" value="#{bundle['accessrightassoc.noassocs']}" /> </c:otherwise> </c:choose> <!-- some rich: components not shown here--> <a:headerbox rendered="#{core:getWritePermission('rights')}"> <a:header title="Public link" /> <br /> <p> <a:commandButton id="edit_role_assocs_generatelink" access="rights" value="Generate Link" styleClass="formbutton" controller="#{accessRightAssocController}" action="generateLink" immediate="true" disabled="#{accessRightAssocController.publicLinkAvailable}" /> <br/><br/> <a:inputText id="text_role_assocs_generatelink" access="rights" rendered="#{accessRightAssocController.publicLinkAvailable}" size="137" styleClass="text" value="#{accessRightAssocController.publicLink}" /> </p> </a:headerbox> ...
The associated controller looks like:public class AccessRightAssocController extends AbstractController { ... public String generateLink() { publicLink = SessionUtil.getAuthorizationController().getAuthorizationService().generatePublicLink(getPlant(), getAccount()); return "access_right_assoc"; } }
The a-components are only wrapper for tomahawk-t-components.
I 've even tried to dump the content of the webresponse to a file/image, but getting only 1kb data. With IrfanView it looks like an transparent pixel of 1x1 pixel size .
Lothar -
5. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 20, 2008 1:03 PM (in response to merlin-hst)id = "menu_nav1_item17_item22"; // it's a gif and the client id - but seems to works getClient().click(id); assertEquals("/presentation/access_right_assoc.xhtml", getCurrentViewName()); id = "edit_role_assocs_generatelink"; validateComponent(id, HtmlCommandButton.class); getClient().getContentPage().getWebResponse().getContentType(); // image/gif // System.out.println(getClient().getPageAsText()); //causes IllegalStateException: This page ca n not be converted to text. Page type is com.gargoylesoftware.htmlunit.UnexpectedPage getClient().click(id); //exception
It looks to me like getClient().click("menu_nav1_item17_item22") returns a single gif in the browser. Since this is not an HTML page, you can't click on it with JSFUnit/HTMLUnit.
Stan -
6. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 21, 2008 10:28 AM (in response to merlin-hst)That sounds really strange to me. I've just tested it in the browser and it works perfectly. Also getCurrentViewName() returns the right view name (access_right_assoc.xhtml) and also the component with the id "edit_role_assocs_generatelink" (the command button) is rendered. I've tried it with JSFServerSession.findComponent(id).isRendered(). Even JSFClientSession.getContentPage().getWebResponse().getStatusCode() returns 200 ok. So I don't understand where the content type "gif" is generated and why.
What I just realised is that we have some phase-listener registered in the faces-config. But even without it, the exception occurs.
Lothar -
7. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 21, 2008 10:54 AM (in response to merlin-hst)In addition to my previous post I just did some more test:
assertEquals("/presentation/plant_overview.xhtml", getCurrentViewName()); id = "menu_nav1_item17"; getClient().click(id); String source = getCurrentViewSource(); //this works System.out.println(source); assertEquals("/presentation/plant_data.xhtml", getCurrentViewName()); id = "menu_nav1_item17_item22"; getClient().click(id); assertEquals("/presentation/access_right_assoc.xhtml", getCurrentViewName()); source = getCurrentViewSource(); //IllegalStateException: This page can not be converted to text. Page type is com.gargoylesoftware.htmlunit.UnexpectedPage System.out.println(source); id = "edit_role_assocs_generatelink"; getClient().click(id); //without the call of getViewSource here the ClassCastException occurs
As I already told in the previous post the view name is correct and the component id is found but it seems that at that point already an error occured which was not detected. But how can I find out the error ?
All "menu_nav1_xxx" id's are generated automatically and are text links generated by the tomahawk t:panelNavigation2 and t:navigationMenuItems components.
Lothar -
8. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 21, 2008 12:32 PM (in response to merlin-hst)"merlin-hst" wrote:
That sounds really strange to me. I've just tested it in the browser and it works perfectly. Also getCurrentViewName() returns the right view name (access_right_assoc.xhtml)
Yes, it is strange.
I wouldn't be looking too much at JSFServerSession to find the answer. JSFServerSession looks at things from a JSF server-side point of view. So When you say getCurrentViewName() returns the right view then what you are telling me is that JSF (and JSFUnit) is working correctly on the server side.
What is not working correctly is the client side. JSFClientSession wraps HtmlUnit. It is your application's interaction with HtmlUnit that is causing a problem. One thing you might try for debugging is to add a RequestListener and examine each request and response made by HtmlUnit.
I've just written a new wiki article that tells you how to do that:
http://www.jboss.org/community/docs/DOC-12845
Also, if you can come up with a simple example that reproduces this problem I'll be happy to take a look at it.
Stan -
9. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 22, 2008 5:06 AM (in response to merlin-hst)I got it "working" by removing all richfaces components from the site. But of course it's not a real solution to me. So why causes richfaces components problems if I try to click a "plain old" html command button ?
Another point I've just seen, I always get the following line in the log output:
INFO - org.apache.commons.httpclient.HttpMethodDirector:814 - Redirect requested but followRedirects is disabled
I'm not sure if it's needed, but I tried to enable redirect with the command:JSFSession.getWebClient().setRedirectEnabled(true);
Because of some problems with JSF we registered a PostRedirectGetListener as described http://balusc.blogspot.com/2007/03/post-redirect-get-pattern.html. So after a form submit the client will get a redirect - except for ajax requests:AjaxContext.getCurrentInstance(facesContext).isAjaxRequest(facesContext)
But even with that message it seems to work - but only without richfaces. Of course I've included the jboss-jsfunit-richfaces-1.0.0.Beta3.jar file in my test project.
Lothar -
10. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 22, 2008 7:29 AM (in response to merlin-hst)I'm sorry you are having this trouble but at least it sounds like you've narrowed it down to RichFaces. If you can figure out which RichFaces component is causing the problem (and under which circumstances), I'll open up a bug report with the HtmlUnit team so we can get this fixed. I know that they are very interested in having good support for RichFaces.
Stan -
11. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 22, 2008 9:54 AM (in response to merlin-hst)I did some more tests using a RequestListener as described earlier and found out an (maybe) explanation for the exception:
When I call the "plant_data" site which contains no RichFaces or ajax stuff I see the request (and response) for the site itself and some myFacesXX js files:faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/12246809/inputTextHelp.HtmlTextHelpRenderer/inputTextHelp.js
Now the next page "access_right_assoc" - where the error occurs - contains a rich:suggestionbox surrounded by a a4j:region tag:<a4j:region renderRegionOnly="true" id="accessrightassoc_accountNamesGroup"> .... <rich:suggestionbox id="suggestionBoxId" for="field_accessrightassoc_table_account" suggestionAction="#{adminAccountNameController.accountNames}" var="result" fetchValue="#{result.userName}"> <h:column> <h:outputText value="#{result.userName}" /> </h:column> <h:column> <h:outputText value="#{result.completePersonName}"/> </h:column> </rich:suggestionbox> ... </a4j:region>
Now I see a lot more js files in the requesta4j/g/3_2_2.GAscripts/suggestionbox.js
and at last a request for a dummy gif:a4j/g/3_2_2.GAorg/richfaces/renderkit/html/images/spacer.gif
For me it looks like that this gif "stays in mind" of JsfUnit/HtmlUnit and will used further. I've tried also to dump the content of the WebResponse after requesting the site to a file:FileUtils.writeByteArrayToFile(new File("test1.gif"),JSFClientSession.getContentPage().getWebResponse().getResponseBody()); FileUtils.writeByteArrayToFile(new File("test2.gif"),IOUtils.toByteArray(JSFClientSession.getContentPage().getWebResponse().getContentAsStream()));
The FileUtils + IOUtils class are from the apache commons project.
When I now compare the hex view of these two files with the above "spacer.gif" they are absolute identically. That's why the content type is "gif". Also the file size is identically. But what can I do to avoid it ? For now I don't need the dummy image really in my test case.
Lothar -
12. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 22, 2008 12:45 PM (in response to merlin-hst)I can change JSFUnit to ignore an UnexpectedPage, but I'm a little worried about breaking something else. I'd feel better if I had something that demonstrates the problem so I can add a new test to the JSFUnit test suite.
Is there any way you can post a simple example?
Stan -
13. Re: ClassCastException with HtmlCommandButton
merlin-hst Oct 22, 2008 1:15 PM (in response to merlin-hst)I'll try it.
But maybe it's enough if you construct a site with just a rich:suggestionbox and a command button on it and try to click the button. -
14. Re: ClassCastException with HtmlCommandButton
ssilvert Oct 22, 2008 1:28 PM (in response to merlin-hst)I made the change to JSFUnit if you want to build from SVN and try it out.
Stan