Contributing patch to RichFaces project

This article is a kickstart written to provide information about contribution of your changes to RichFaces codebase.


We expect you already looked through the Configure Maven for RichFaces and Repository Structure Overview articles. And also we suppose that you know at least the basics about component development from CDK Developer Guide

 

This article was created in the next environment:

Jboss Tools Version: 2.0.0.CR2

Tomcat 6.0.16. Note: you could use any other application server supported by RichFaces. Only some dependencies should be changed in this case.

FireFox 3.0.8 with Firebug 1.3.3

TortoisSVN 1.4.8 client

Apache Maven 2.0.8

Issue

https://jira.jboss.org/jira/browse/RF-6736 is choosen to be implemented for this article.

Environment setup

 

Trunk codebase checked out from http://anonsvn.jboss.org/repos/richfaces/trunk.

 

Maven settings (MAVEN_HOME/conf/settings.xml) changed to add the needed profile according to Configure Maven for RichFaces .

 

Now let's build RichFaces with

mvn install 

command  to check that settings are correct.

Import the component and sample to Jboss Tools

Run

 

mvn eclipse:eclipse -DdownloadSources=true -Dwtpversion=1.5

 

in TRUNK_DIR/ui/combobox and TRUNK_DIR/samples/combobo-sample project subdirectories.

 

Start the eclipse and call File-Import... wizard

Choose "Existing Projects into Workspace" and hit "next".

Select the checked trunk directory as a root folder.

 

combobox and combobox-sample projects should appear in the list of available projects. Just check them and click "finish" on the wizard.

0.jpg"

Eclipse Problems view after import will contain many errors for a combobox project, but you should not worry about them, as it happen only because our jspx format doesn't comply to the dtd. Eclipse knows nothing about CDK conventions (for now )

Projects/Eclipse Configuration changes

1) Make sure you have the M2_REPO Eclipse variable defined properly and pointed to your local maven repository.

3.jpg

2) As the SVN plugin for eclipse wasn't used during the issue fixing - sample and component projects properties were changed in order to exclude .svn folders from publishing.

3_1.jpg

3) We need to remove combobox.jar from the build path(libraries) and add the imported combobox project instead.

1.jpg

 

Note: dependencies for this projects contain suggestionBox jars.. It should not confuse you in this case because it seems to be an artifact which still is not cleaned (developers could use some additional components when developing or testing a sample). We are not intended to work with its sources anyway, so it will be just fetched from repository during a build. Nevertheless, you should be really careful working with some components which directly depend on other components. For example, comboBox script is used by inplace components and inplaceSelect reuses some code of inplaceInput. Shuttle components (OrderingList and ListShuttle) also depend on shared code. Thus, currently you need to check such dependencies on your own and make sure you don't break any component functinality. RichFaces 4.0 version will be redesigned in order to make such dependencies more clear and to provide a project structure more convenient for the developers. Visit http://www.jboss.org/community/wiki/RichFaces40BuildSystem for more information.

 

Running Sample

Now let's publish and run the sample in order to check that all settings were defined correctly.

Note: As it was already mentioned tomcat 6 was used during writing the article but if you want to work using Jboss Application Server (e.g. 4.2 bundled to Jboss Developer Studio or higher) you will have to add the next code to the web.xml:

    <context-param>
        <param-name>WAR_BUNDLES_JSF_IMPL</param-name>
        <param-value>true</param-value>
    </context-param>

because the server is already bundled with JSF implementation and this parameter will mean that application that provides JSF implementation should be used.

4.jpg

5.jpg

Development

Now it's time to add the attribute asked by the community

 

From the beginning we should add the next code to the component config in order to define a new attribute (richfaces-trunk\ui\combobox\src\main\config\component\combobox.xml).Visit CDK Guide Component Configuration section

 

             <property>
                   <name>onlistclose</name>
                   <classname>java.lang.String</classname>
                  <description>HTML: script expression; a list is closed</description>
                   <defaultvalue><![CDATA[""]]></defaultvalue>
              </property>

Note: Since this issue has been already resolved the onlistclose setup (as all the other changes are described futher in this post) is already in place.

 

Now we should change the jspx template  which is used by CDK to generate a renderer for the component(visit CDK guide templating section for more detailed info).  We add the following code to initialization statement

#{this:getAsEventHandler(context, component, "onlistclose")},

in order to pass the function defined in the attribute to the combobox script object (richfaces-trunk\ui\combobox\src\main\templates\combobox.jspx the statement in the end of the template).

 

Hence, the new statement will be:

var combobox = new Richfaces.ComboBox( "#{clientId}", 
"#{clientId}list", 
"#{clientId}listParent",
"#{clientId}comboboxValue",
"#{clientId}comboboxField", 
"#{clientId}comboboxButton", 
"#{clientId}comboBoxButtonBG",
"#{clientId}shadow",
new Richfaces.ComboBoxStyles(), 
comboboxUserStyles, 
"#{listWidth}", "#{listHeight}",
#{this:getItemsTextAsJSArray(context, component,items)}, 
#{directInputSuggestions}, 
#{filterNewValues}, 
#{selectFirstOnUpdate},
#{this:getAsEventHandler(context, component, "onlistcall")},

#{this:getAsEventHandler(context, component, "onlistclose")}, 

#{this:getAsEventHandler(context, component, "onselect")},
"#{defaultLabel}",
#{disabled}, #{convertedValue}, 
#{component.attributes["showDelay"]},  #{component.attributes["hideDelay"]});

Thus, there we call the function defined in

baseclass="org.richfaces.renderkit.ComboBoxBaseRenderer"

which will encode the function definition properly. You could check the base class ComboBoxBaseRenderer in order to check the method itself.

 

As we changed the config file and the template - we should run

mvn install 

from the root of combobox project in order RichFaces CDK regenerates renderers and other artifacts required to use this new attribute.

 

Now we need to change a component JavaScript code a bit to process this new custom event.

 

Open richfaces-trunk\ui\combobox\src\main\resources\org\richfaces\renderkit\html\scripts\combobox.js .

 

 

Aadd the onlistclose to prototype initialize function:

initialize: function(combobox, listId, parentListId, valueFieldId, fieldId, buttonId, buttonBGId, shadowId, commonStyles,  userStyles, 
     listWidth, listHeight, itemsText, directInputSuggestions, filterNewValue, 
     selectFirstOnUpdate, onlistcall, onlistclose, onselected, defaultMessage, isDisabled, value,
     showDelay, hideDelay)

and pass the onlistclose to combolist object constructor

this.comboList = new Richfaces.ComboBoxList(listId, parentListId, selectFirstOnUpdate, filterNewValue, this.classes.combolist, listWidth, 
     listHeight, itemsText, onlistcall, onlistclose, fieldId, shadowId, showDelay, hideDelay);

 

Also edit combolist.js which is located in the same folder.

 

At first we should add onlistclose definition to initialize a method:

initialize: function(listId, parentListId, selectFirstOnUpdate, filterNewValues, classes, width,
         height, itemsText, onlistcall, onlistclose, fieldId, shadowId,decorationId,
      showDelay, hideDelay)

Then register an observer for this event just after the same statement for onlistcall;

if (this.onlistclose) {
     this.listParent.observe("rich:onlistclose", this.onlistclose);
}

And actually we should fire the event every time we close the combobox list (hideWithDelay function):

     hideWithDelay : function() {
          this.hide();
          this.listParent.fire("rich:onlistclose", {});
     }

Running sample

     We're sure you know how to add an additional property to the sample bean which will hold the function definition. Then just add the input to the sample page bound to this property. Here we write a function to use by combobox onlistclose event. And after all add the attribute to the combobox like here (combobox-sample\src\main\webapp\pages\index.xhtml page)

onlistclose="#{bean.onlistcloseScript}"

Now we could run the sample. Type "window.status += 'New handler works' " inside the input which should store the handler definition and submit the form. Then just open the combobox and check that this string appears in the browser status every time you close the list. (Does not matter whether something was selected or the popup was closed without any selection)

6.jpg

Patch Creation

Thus, when the development is finished we are ready to submit a patch.

Use the "create" patch TortoiseSVN command:

7.jpg

Finally we have combobox-patch.patch file which should be attached to a jira issue in order to be reviewed and applied by a RF team.

 

Note: You could use any svn client in order to perform this. If you can't find the "create patch" functionality, use the commands like  "diffs" and store the result to a separate file.