|
|
|
03/04/2009
Following Lance Ivy's excellent post (http://codelevy.com/articles/2007/11/05/selenium-and-ajax-requests), here's an easy way to write Selenium tests for Ajax requests when you're not using Prototype directly, but using Ajax4JSF or RichFaces. Add this to your user-extensions.js:
/**
* Registers with the a4j library to record when an Ajax request
* finishes.
*
* Call this after the most recent page load but before any Ajax requests.
*
* Once you've called this for a page, you should call waitForA4jRequest at
* every opportunity, to make sure the A4jRequestFinished flag is consumed.
*/
Selenium.prototype.doWatchA4jRequests = function() {
var testWindow = selenium.browserbot.getCurrentWindow();
// workaround for Selenium IDE 1b2 bug, see
// http://clearspace.openqa.org/message/46135
if (testWindow.wrappedJSObject) {
testWindow = testWindow.wrappedJSObject;
}
testWindow.A4J.AJAX.AddListener({
onafterajax: function() {Selenium.A4jRequestFinished = true}
});
}
/**
* If you've set up with watchA4jRequests, this routine will wait until
* an Ajax request has finished and then return.
*/
Selenium.prototype.doWaitForA4jRequest = function(timeout) {
return Selenium.decorateFunctionWithTimeout(function() {
if (Selenium.A4jRequestFinished) {
Selenium.A4jRequestFinished = false;
return true;
}
return false;
}, timeout);
}
Selenium.A4jRequestFinished = false;
Instead of using pauses or waitForCondition (writing some esoteric javascript test to detect that the Ajax call ended), you can then write something as simple as: <tr> <td>watchA4jRequests</td> <td></td> <td></td> </tr> ... (command triggering the ajax call) ... <tr> <td>waitForA4jRequest</td> <td>10000</td> <td></td> </tr> </pre> For Selenium beginners, the Javascript code has to be placed in a file named user-extensions.js and passed as an attribute to the Selenium Server command line option "-user-extensions <file>". When using Selenium IDE, it can be set in the options menu (don't forget to close the IDE and restart it for this to be taken into account). I'm happy to have found an elegant (and easy) way to handle cross-validation of JSF components. The idea is to add an hidden input and bind it to a validator, passing component ids to validate as attributes:
<h:inputHidden value="needed" validator="#{myBean.validatePassword}">
<f:attribute name="firstPasswordInputId"
value="#{layout.widgetMap['firstPassword'].id}" />
<f:attribute name="secondPasswordInputId"
value="#{layout.widgetMap['secondPassword'].id}" />
</h:inputHidden>
Note that here, component ids are retrieved from the layout widget ids,
but any id bindings will do (taking example on what's done when adding a
"for" attribute to a h:message tag for instance). The validation method can then retrieve the components values:
public Object retrieveInputComponentValue(UIComponent anchor, String componentId) {
Map
Note that all components have to be in the same container for this to work properly as is (UIComponent#findComponent method restricts its search to the nearest container). Of course, this retrieval method can be adapted to handle more tricky situations, or to handle other kinds of component types. What's the improvement compared to what i've seen so far? Well I've seen recommendations to use an hidden input too, but it's retrieving the referenced components values binding the components to some fields in the backing bean. So in this case, you had to add getters and setters for each component, and you had to do it for every set of components following the same validation criterion on a given page. Other recommendations involved writing a custom component handling several other ones, assuming dependent components will be rendered in the same part of the page... overkill, right? In other words, here you can perform the same validation several times in the same page... with less code. And it's prettier ;-)
07/03/2008
The Nuxeo application extensively uses JSF facelets and Seam for its rendering:
Even though last versions of Seam offer a very clean integration with Richfaces/ajax4jsf JSF libraries, the Google Web Toolkit (http://code.google.com/webtoolkit/) looks like a good alternative when dealing with the more complex screens. For instance, rendering a table of documents with pagination, sorting and selection support is not straight-forward with JSF facelets. While JSF goal to separate logic and rendering can be seen as too restrictive for a framework like Nuxeo EP, GWT makes it possible to keep this separation and not lose any expressivity because a GWT application is written in Java. Also, JSF has a quite steeper learning curve than GWT. Integrating GWT with Nuxeo EP is an attempt to get the best of both worlds: keep JSF for its integration with Seam, third-party JSF libraries, easy deployment/override of xhtml pages as well as existing Nuxeo modules relying on it, and use GWT for some specific complex screens. An addon has been written as a proof-of-concept. Documents are retrieved from the Nuxeo application via a Seam component and information for their rendering is serialized on the GWT client side to display them in a paginated table. Seam made life easier by providing a remoting service interacting with the GWT service framework: from GWT rendering classes, it's possible to call a standard Seam component that will implement server logic.Some code has been added to restore the conversation when calling the Seam component, as we want to display the list of current folder children. The conversation id is retrieved on client side thanks to javascript code parsing the url. It is passed alongside when calling the remote service. Packaging was not a problem thanks to maven plugins that perform the GWT compilation and make it possible to include them in the nuxeo.war folder at deployment. Integrating the GWT module within standard xhtml pages was easy: the javascript simply needs to be included in the page as mere html code.
Here's a screenshot of rendered table:
What's next?
For better understanding of these technologies, I strongly recommend the excellent article written by Rob Jellinghaus (Seam / JSF / GWT Integration: What, Why, and How: http://unrealities.com/seamgwt/article_0.2.html). The addon code is at http://hg.nuxeo.org/addons/nuxeo-platform-gwt/. It currently only works with the Nuxeo Seam 2 branch that should be merged in the 5.2 branch shortly.
09/04/2007
2009 update: you should be looking at jboss-el if you'd like to get an esay integration of parameters handling in your application. The usual way to use EL expression in JSF could seem a little too restrictive for some of us who are used to scripting languages. For instance, if you'd like to display a bean property, you will write a getter on it:
public class MyBean {
String myProperty;
public String getMyProperty() {
return myProperty;
}
}
Then you'll be able to write the following value expression in a template:
<h:outputText value="#{myBean.myProperty}" />
Now imagine that your bean has to perform a more complex task to retrieve the property, like calling a service, and pass parameters to it. Even if there is always the possibility to pass the parameter using a "f:parameter" tag, the bean API will look kind of awkward. The more natural way to do so is to write a method with this parameter, and find a way to call it from the template. For instance, we could have:
public String getMyProperty(String param) {
// execute any function to get the result
return function(param);
}
<h:outputText value="#{myBean.getMyProperty('foo')}" />
Sadly, there is no way to do that using "pure" JSF implementations. That's where facelets can be very handy. In a very nice blog post, Andrew Robinson explains how to pass method bindings to children components using the facelet user tag system. I will explain how Nuxeo uses the same tricks to invoke method expressions with parameters as regular value expressions. First let's define the famous MethodValueExpression class, that will behave as a regular value expression but will invoke a method expression when trying to resolve the value:
public class MethodValueExpression extends ValueExpression implements
Externalizable {
public MethodValueExpression(MethodExpression methodExpression,
Class[] paramTypesClasses) {
this.methodExpression = methodExpression;
this.paramTypesClasses = paramTypesClasses;
}
...
@Override
public Object getValue(ELContext context) {
// invoke method instead of resolving value
Object res;
try {
return methodExpression.invoke(context, paramTypesClasses);
}
catch(Throwable t) {
return null;
}
}
}
Nuxeo benefits from an extension to the EL provided by Seam: it makes it possible to use parameters on any method expression without having to configure parameter types. That's why parameter types classes are never actually set in the Nuxeo code. When this is done, we can use facelets meta rules to use this class instead of the generic one. This is done via a component handler:
public class GenericHtmlComponentHandler extends HtmlComponentHandler {
...
protected MetaRuleset createMetaRuleset(Class type) {
MetaRuleset m = super.createMetaRuleset(type);
if (ValueHolder.class.isAssignableFrom(type)) {
m.addRule(GenericValueHolderRule.Instance);
}
return m;
}
}
This configuration tells to use the GenericValueHolderRule class when setting a component attributes. This rule does not do much but use our MethodValueExpression when appropriate, e.g. when brackets are detected. We can configure tags to use this handler in a facelet taglib:
<tag>
<tag-name>outputText</tag-name>
<component>
<component-type>javax.faces.HtmlOutputText</component-type>
<renderer-type>javax.faces.Text</renderer-type>
<handler-class>org.nuxeo.ecm.platform.ui.web.tag.handler.GenericHtmlComponentHandler</handler-class>
</component>
</tag>
Note that there is no need to use another term than "value" as shown in this code (using "genericValue") as the last rule added to the MetaRuleSet will apply first and override the default behaviour. The nxh taglib, using the namespace "http://nuxeo.org/nxweb/html" redefines all basic jsf html tags to use this handler. We could add any number of attributes to be dealt in the same way than "value": for instance, being able to write <nxh:outputText rendered="#{myBean.getProperty('foo')}" /> can be handy too. Now it can a little painful to define a new taglib with this handler when reusing custom tag libraries. The Nuxeo tag library defines a new tag "nxu:methodResult", that will make the result of the given expression available in the variable map:
<nxu:methodResult name="prop" value="#{myBean.getMyProperty('foo'}">
<h:outputText value="foo" rendered="#{prop == 'bar'}" />
</nxu:methodResult>
The variable named "prop" is available inside the methodResult tag, as a row variable in a "h:dataTable" tag. This behaviour is achieved using a specific tag handler that will use the MethodValueExpression presented above:
public class MethodResultTagHandler extends MetaTagHandler {
private final TagAttribute name;
private final TagAttribute value;
public MethodResultTagHandler(TagConfig config) {
super(config);
name = getRequiredAttribute("name");
value = getRequiredAttribute("value");
}
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException {
String nameStr = name.getValue(ctx);
// parameter types evaluation not needed using Seam
MethodExpression meth = value.getMethodExpression(ctx, Object.class,
new Class[0]);
ValueExpression ve = new MethodValueExpression(meth, paramTypesClasses);
ctx.getVariableMapper().setVariable(nameStr, ve);
this.nextHandler.apply(ctx, parent);
}
}
This tag handler is linked to the MethodResult tag in a taglib file: <tag> <tag-name>methodResult</tag-name> <handler-class>org.nuxeo.ecm.platform.ui.web.tag.handler.MethodResultTagHandler</handler-class> </tag> Nice, huh? Nuxeo Tag Library documentation: http://maven.nuxeo.org/nuxeo-platform-parent/nuxeo-platform-ui-web/tlddoc/. Complete code mentioned above is available here:
Posted by Anahide Tchertchian @ 09/04/2007 04:13 PM.
-
Categories:
nuxeo5
-
0 comments
09/30/2005
A new Zope product, CPSRelation, has been designed to handle RDF relations
within the CPS framework: it gives access to any kind of content RDF
indexation and serialization, as well as querying features.
CPSRelation offers RDF features installing a tool, portal_relations, that is able to manage several kinds of graphs. Another tool, portal_serializer, has been designed to provide object serializations via pluggable TALES expressions. We've been using IOBTree graphs to handle relations between documents, using their docid in the repository as unique identifiers. Now we can also handle RDF relations, provided by the rdflib Python library and the Redland framework. We have tested Redland graphs to index and serialize CPS content, and query relations created in the graph. The mechanism is rather simple:
The product's SVN repository is here: http://svn.nuxeo.org/trac/pub/browser/CPSRelation/trunk/ And can be downloaded using svn co http://svn.nuxeo.org/pub/CPSRelation/trunk CPSRelation Additional information:
Posted by Anahide Tchertchian @ 09/30/2005 09:38 PM.
-
Categories:
cps,
rdf,
semantic_web
-
0 comments
06/16/2005
Woke up this morning, can't believe what I saw: CPSWorkflow documentation
was out !
You can find it at the following URL: http://www.cps-project.org/sections/documentation/developers/cpsworkflow/switchLanguage/en A Zope product comes with this documentation, as it is constructed as a tutorial. I hope the document construction makes it easy to understand how CPS workflows work, and how powerful they can be. The sample workflow is quite simple because I did not want to present a complicated example. Hope you'll enjoy, any kind of feedback is very welcome.
Posted by Anahide Tchertchian @ 06/16/2005 12:24 PM.
-
Categories:
cps
-
0 comments
Last modified:
05/10/2005 04:17 AM
|
Nuxeo Bloggers: Log in! Search Nuxeo Blogs
About this blog
Anahide Tchertchian
About this blog
Categories
Nuxeo Bloggers
Photos and Pictures
|
|
Nuxeo -
Indesko -
Nuxeo 5 Project
All content is copyrighted by their author. CPSSkins is Copyright © 2003-2006 by Jean-Marc Orliaguet. | CPS is Copyright © 2002-2006 by Nuxeo SAS. |