Один из лучших (но не самых простых) способов расширения некоторых компонентов JSF и добавления поведения без потери атрибутов - использование плагина JSF PrimeFaces.Некоторая информация об этом находится здесь: http://code.google.com/p/primefaces/wiki/BuildingFromSource. Хотя он имеет некоторые жестко закодированные значения (имя лицевой стороны taglib и путь к выходному каталогу, куда помещается сгенерированный taglib) и может быть изменен и восстановлен локально. Вот пример PF jsfплагин
<!-- Primefaces maven plugin -->
<plugin>
<groupId>org.primefaces</groupId>
<artifactId>maven-jsf-plugin</artifactId>
<version>1.2.1-SNAPSHOT</version>
<executions>
<execution>
<id>generate-ui</id>
<phase>generate-sources</phase>
<configuration>
<uri>http://www.mycompany.com/tags</uri>
<name>rstk-tag</name>
<jsfVersion>2</jsfVersion>
<templatesDir>src/main/java-templates</templatesDir>
<componentConfigsDir>src/main/resources-maven-jsf/ui</componentConfigsDir>
<!-- <standardFacesConfig>src/main/resources-maven-jsf/standard-faces-config.xml</standardFacesConfig> -->
<!-- These are new attributes added manually to plugin source code! -->
<standardFaceletsTaglib>src/main/resources-maven-jsf/standard-facelets-taglib.xml</standardFaceletsTaglib>
<faceletsOutputDirectory>target/generated-sources/maven-jsf-plugin/META-INF</faceletsOutputDirectory>
</configuration>
<goals>
<goal>generate-components</goal>
<goal>generate-facelets-taglib</goal>
</goals>
</execution>
</executions>
</plugin>
После этого для генерации могут использоваться следующие XML-метаданные:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component SYSTEM "../misc/component.dtd" [
<!ENTITY standard_uicomponent_attributes SYSTEM "../entities/standard_uicomponent_attributes.xml">
<!ENTITY output_component_attributes SYSTEM "../entities/output_component_attributes.xml">
<!ENTITY input_component_attributes SYSTEM "../entities/input_component_attributes.xml">
]>
<component>
<tag>enumSelectOneMenu</tag>
<tagClass>com.rstk.kasko.component.EnumSelectOneMenuTag</tagClass>
<componentClass>com.rstk.kasko.component.EnumSelectOneMenu</componentClass>
<componentType>com.rstk.kasko.component.EnumSelectOneMenu</componentType>
<componentFamily>javax.faces.SelectOne</componentFamily>
<rendererType>javax.faces.Menu</rendererType>
<parent>javax.faces.component.html.HtmlSelectOneMenu</parent>
<description>The tag for select one menu, which renders the enumerations list. No children necessary for this</description>
<attributes>
&input_component_attributes;
</attributes>
</component>
Это вместе с EnumSelectOneMenuTemplate.java (шаблон, который вставляется в сгенерированный код компонента) позволяетдля генерации:
- taglib.xml со ВСЕМ стандартным html выберите один атрибут меню
- Класс компонента, который содержит пользовательские логики для рендеринга clidhren:
public class EnumSelectOneMenu extends HtmlSelectOneMenu {
... // Generated staff here
public boolean getRendersChildren() {
return true;
}
/**
* @see javax.faces.component.UIComponentBase#encodeBegin(javax.faces.context.FacesContext)
*/
@Override
public void encodeBegin(FacesContext context) throws IOException {
super.encodeBegin(context);
if (context.isPostback()) {
return;
}
UISelectItems selectItems = new UISelectItems();
try {
selectItems.setValue(getEnumValuesList());
} catch (Exception e) {
log.error("Failed to create enum list", e);
}
getChildren().add(selectItems);
}
/**
* Creates the list of select items of format [ENUM, enum.getDisplay()]
* @return
*/
private List getEnumValuesList() {
List result = new ArrayList();
ValueExpression ve = getValueExpression("value");
Class enumClass = ve.getType(getFacesContext().getELContext());
Method method = ReflectionUtils.findMethod(enumClass, "getDisplay", null);
for (Object e : ve.getType(getFacesContext().getELContext()).getEnumConstants()) {
result.add(new SelectItem(e, (String) ReflectionUtils.invokeMethod(method, e)));
}
return result;
}
}
Тогда этот компонент можно использовать как простой JSF для выбора одного компонента (со ВСЕМИ стандартными атрибутами), но не требует, чтобы элементы выбора добавлялись каждый раз, и позволяет помещать туда любые другие дочерние элементы:
<s:enumSelectOneMenu value="#{polis.osMatrixType}" id="registryType">
<p:ajax listener="#{osagoPolisBean.rollOsagoEndDate}" update="osagoUsagePeriod" process="osagoTable" event="change"/>
</s:enumSelectOneMenu>