Extending MyFaces components

I am fairly new to JSF, and have a requirement to extend JSF components to enable or disable themselves without having to explicitly do this via JSF expression language.

I was thinking the best way to do this was to overide getRendered(), and setRendered(). Apart from this method, I don't need to change any other part of the components behaviours.

I am currently using apache's myfaces implementation and ideally wanted to create simple extensions of all their common tags such as links and button, but looking at the documnentation it appears you have to extend the UIComponentBase class which is more work than simply extending a Link component or a button component for example.

Does anyone have experience of directly extending MyFaces components, or could suggest how I'd go about this?

thanks

Paul

[846 byte] By [bronze-starDukes] at [2007-11-26 12:12:47]
# 1

I think it works like this:

It all starts with your web.xml, where you define your taglib for your app. something like:

<taglib>

<taglib-uri>http://mycompany.com</taglib-uri>

<taglib-location>/WEB-INF/mytags.tld</taglib-location>

</taglib>

now you need to invent some tag and tie it to a tag class in your mytags.tld. let's say you wanted to inherit from datatable:

<tag>

<name>myDataTable</name>

<tag-class>mypackage.MyDataTableTag</tag-class>

<body-content>JSP</body-content>

<!-- all standard attributes of the dataTable tag -->

<!-- UIPanel attributes -->

<!-- UIComponent attributes -->

<attribute><name>id</name><required>false</required><rtexprvalue>false</rtexprvalue><type>java.lang.String</type>

<description>Every component may have an unique id. Automatically created if omitted.</description>

</attribute>

<attribute><name>rendered</name><required>false</required><rtexprvalue>false</rtexprvalue><type>java.lang.String</type>

<description>If false, this component will not be rendered.</description>

</attribute>

<attribute><name>binding</name><required>false</required><rtexprvalue>false</rtexprvalue><type>java.lang.String</type>

<description>Component binding.</description>

</attribute>

<!-- HTML 4.0 universal attributes -->

<attribute><name>dir</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>lang</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>style</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>title</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>styleClass</name><required>false</required><rtexprvalue>false</rtexprvalue>

<description>Corresponds to the HTML class attribute.</description>

</attribute>

<!-- HTML 4.0 event-handler attributes -->

<attribute><name>onclick</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>ondblclick</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onmousedown</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onmouseup</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onmouseover</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onmousemove</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onmouseout</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onkeypress</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onkeydown</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>onkeyup</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<!-- HTML 4.0 table attributes -->

<attribute><name>align</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>border</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>bgcolor</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>cellpadding</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>cellspacing</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>datafld</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>datasrc</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>dataformatas</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>frame</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>rules</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>summary</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>width</name><required>false</required> <rtexprvalue>false</rtexprvalue></attribute>

<!-- UIData attributes -->

<attribute><name>value</name><required>false</required><rtexprvalue>false</rtexprvalue>

<description>Supported types see JSF Spec 4.1.3</description>

</attribute>

<attribute><name>var</name><required>true</required><rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>rows</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>first</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

<!-- TableRenderer attributes -->

<attribute><name>columnClasses</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>footerClass</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>headerClass</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

<attribute><name>rowClasses</name><required>false</required><rtexprvalue>false</rtexprvalue></attribute>

</tag>

It's worth noting that the tag definition is basicaly a huge copy/paste hack from the MyFaces tld, but, it's xml goo, and we needed a different <tag-class>, and i'm not smart enough to do it differently.

Now in mypackage.MyDataTableTag.java we can start extending some stuff:

public class MyDataTableTag extends org.apache.myfaces.taglib.html.HtmlDataTableTag {

public String getComponentType() {

return "mypackage.MyDataTable";

}

public String getRendererType() {

return "javax.faces.Table";

}

}

This guy is basicaly just another goo layer that ties in to the component class (where most of the work happens), renderers, and so forth.

HtmlDataTableTag is an eventual child of UIComponentBodyTag, but it's a ride to trace it.

Now you need more xml goo in your faces-config.xml to tie that string to a class:

<component>

<component-type>mypackage.MyDataTable</component-type>

<component-class>mypackage.MyDataTable</component-class>

</component>

(If it seems dumb that's because it is. Although if you wanted to override an existing myfaces component, this is where you'd do it. And there's probably good reasons why you might consider that in just this sort of case.) Anyway, now that you know <myDataTable> will end up using MyDataTable.java, you can finally do what you wanted to (I think)

public class MyDataTable extends javax.faces.component.html.HtmlDataTable {

public MyDataTable() {

super();

}

public boolean isRendered() {

return {some custom code};

}

}

The last major concern (that i'll mention) is that you're basicaly being a cheat by extending faces code. It'll work as long as your MyFaces implementation doesn't pull the rug out from under you by changing their class hierarchy and so forth. That's the price you pay for playing in someone else's sandbox. Your other option is to not be so lazy and have your tag class and component class not extend anything and behave entirely independant of (though perhaps similar to) faces classes. That would require kicking over more turds than we have already and require an understanding of the faces lifecycle, which is beyond the scope of this post.

I hope some of that was useful.

bronzestar at 2007-7-7 14:13:09 > top of Java-index,Archived Forums,Socket Programming...
# 2

> I think it works like this:

>

> It all starts with your web.xml, where you define

> your taglib for your app. something like:

> > <taglib>

><taglib-uri>http://mycompany.com</taglib-uri>

> <taglib-location>/WEB-INF/mytags.tld</taglib-location>

>

> </taglib>

>

>

> now you need to invent some tag and tie it to a tag

> class in your mytags.tld. let's say you wanted to

> inherit from datatable:

> > <tag>

><name>myDataTable</name>

> <tag-class>mypackage.MyDataTableTag</tag-class>

><body-content>JSP</body-content>

> <!-- all standard attributes of the dataTable tag

> -->

><!-- UIPanel attributes -->

> <!-- UIComponent attributes -->

> <attribute><name>id</name><required>false</required><r

> texprvalue>false</rtexprvalue><type>java.lang.String<> type>

> <description>Every component may have an unique

> id. Automatically created if omitted.</description>

> /attribute>

>

> attribute><name>rendered</name><required>false</requir

> ed><rtexprvalue>false</rtexprvalue><type>java.lang.Str

> ing</type>

> <description>If false, this component will not be

> rendered.</description>

> /attribute>

>

> attribute><name>binding</name><required>false</require

> d><rtexprvalue>false</rtexprvalue><type>java.lang.Stri

> ng</type>

><description>Component binding.</description>

> tribute>

> <!-- HTML 4.0 universal attributes -->

> <attribute><name>dir</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>lang</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>style</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>title</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>styleClass</name><required>false</requ

> ired><rtexprvalue>false</rtexprvalue>

> <description>Corresponds to the HTML class

> attribute.</description>

> /attribute>

> <!-- HTML 4.0 event-handler attributes -->

> <attribute><name>onclick</name><required>false</requir

> ed> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>ondblclick</name><required>false</requ

> ired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onmousedown</name><required>false</req

> uired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onmouseup</name><required>false</requi

> red> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onmouseover</name><required>false</req

> uired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onmousemove</name><required>false</req

> uired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onmouseout</name><required>false</requ

> ired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onkeypress</name><required>false</requ

> ired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onkeydown</name><required>false</requi

> red> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>onkeyup</name><required>false</require

> d> <rtexprvalue>false</rtexprvalue></attribute>

> <!-- HTML 4.0 table attributes -->

> <attribute><name>align</name><required>false</required

> > <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>border</name><required>false</required

> > <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>bgcolor</name><required>false</require

> d> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>cellpadding</name><required>false</req

> uired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>cellspacing</name><required>false</req

> uired> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>datafld</name><required>false</require

> d> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>datasrc</name><required>false</require

> d> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>dataformatas</name><required>false</re

> quired>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>frame</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>rules</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>summary</name><required>false</require

> d> <rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>width</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

><!-- UIData attributes -->

> <attribute><name>value</name><required>false</require

> ><rtexprvalue>false</rtexprvalue>

> <description>Supported types see JSF Spec

> 4.1.3</description>

> /attribute>

>

> attribute><name>var</name><required>true</required><rt

> exprvalue>false</rtexprvalue></attribute>

>

> attribute><name>rows</name><required>false</required><

> rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>first</name><required>false</required>

> <rtexprvalue>false</rtexprvalue></attribute>

> <!-- TableRenderer attributes -->

> <attribute><name>columnClasses</name><required>false<> required><rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>footerClass</name><required>false</req

> uired><rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>headerClass</name><required>false</req

> uired><rtexprvalue>false</rtexprvalue></attribute>

>

> attribute><name>rowClasses</name><required>false</requ

> ired><rtexprvalue>false</rtexprvalue></attribute>

> </tag>

>

>

> It's worth noting that the tag definition is basicaly

> a huge copy/paste hack from the MyFaces tld, but,

> it's xml goo, and we needed a different <tag-class>,

> and i'm not smart enough to do it differently.

>

> Now in mypackage.MyDataTableTag.java we can start

> extending some stuff:

> > public class MyDataTableTag extends

> org.apache.myfaces.taglib.html.HtmlDataTableTag {

>

>public String getComponentType() {

>return "mypackage.MyDataTable";

> }

>

>public String getRendererType() {

>return "javax.faces.Table";

> }

>

> }

>

>

> This guy is basicaly just another goo layer that ties

> in to the component class (where most of the work

> happens), renderers, and so forth.

> HtmlDataTableTag is an eventual child of

> UIComponentBodyTag, but it's a ride to trace it.

>

> Now you need more xml goo in your faces-config.xml to

> tie that string to a class:

> > <component>

> <component-type>mypackage.MyDataTable</component-typ

> e>

> <component-class>mypackage.MyDataTable</component-cl

> ass>

> </component>

>

>

> (If it seems dumb that's because it is. Although if

> you wanted to override an existing myfaces component,

> this is where you'd do it. And there's probably good

> reasons why you might consider that in just this sort

> of case.) Anyway, now that you know <myDataTable>

> will end up using MyDataTable.java, you can finally

> do what you wanted to (I think)

>

> > public class MyDataTable extends

> javax.faces.component.html.HtmlDataTable {

>public MyDataTable() {

>super();

> }

>

>public boolean isRendered() {

>return {some custom code};

>

> }

>

>

> The last major concern (that i'll mention) is that

> you're basicaly being a cheat by extending faces

> code. It'll work as long as your MyFaces

> implementation doesn't pull the rug out from under

> you by changing their class hierarchy and so forth.

> That's the price you pay for playing in someone

> else's sandbox. Your other option is to not be so

> lazy and have your tag class and component class not

> extend anything and behave entirely independant of

> (though perhaps similar to) faces classes. That

> would require kicking over more turds than we have

> already and require an understanding of the faces

> lifecycle, which is beyond the scope of this post.

>

> I hope some of that was useful.

Thanks for this, your email looks very useful. And I will try out the code you have suggested.

You also make a very good point about playing about using code that is not part of the faces API, and the option to create my own components is in an ideal world the best one, but it may come down to time constraints.

Paul

bronzestar at 2007-7-7 14:13:09 > top of Java-index,Archived Forums,Socket Programming...