Berner Fachhochschule-Technik und Informatik
Advanced Web Technologies 7) Create a new JSF Components
- Dr. E. Benoist
Fall Semester 09-10
Advanced Web Technologies 7) Create a new JSF Components 1
Advanced Web Technologies 7) Create a new JSF Components Dr. E. - - PowerPoint PPT Presentation
Berner Fachhochschule-Technik und Informatik Advanced Web Technologies 7) Create a new JSF Components Dr. E. Benoist Fall Semester 09-10 Advanced Web Technologies 7) Create a new JSF Components 1 Writing new Components for JSF Motivations
Advanced Web Technologies 7) Create a new JSF Components 1
Advanced Web Technologies 7) Create a new JSF Components 2
◮ Use an existing
◮ Create your own new Component ◮ Import (or buy) an existing component
Advanced Web Technologies 7) Create a new JSF Components Motivations 3
◮ Much like Swing’s component model
containers.
and JSP.
bindings and generates HTML renderings.
◮
parameters to the values of the component.
into the corresponding markup, that is, HTML.
Advanced Web Technologies 7) Create a new JSF Components Motivations 4
◮ Two implementation approach
decoding and encoding.
renderer that does the encoding and decoding.
with different renderers that will represent it in different ways
check boxes.
◮
UI component;
request and how it will be displayed – usually though HTML.
Advanced Web Technologies 7) Create a new JSF Components Motivations 5
Advanced Web Technologies 7) Create a new JSF Components Motivations 6
◮ UIComponent is the base class for all JSF components.
UIComponentBase,
UIComponent.
◮ Components:
faces-config.xml)
components to managed bean properties.
◮ A component can be a ValueHolder or an
◮ Components like form field components have a
Advanced Web Technologies 7) Create a new JSF Components Motivations 7
◮ Example: render tag <label>Form Test</label>
◮ Create a class that extends UIComponent ◮ Save the component state ◮ Register the component with faces-config.xml
◮ Override encode ◮ Override decode ◮ Register the renderer with faces-config.xml
◮ Return the renderer type ◮ Return the component type ◮ Set up properties that might use JSF expressions Advanced Web Technologies 7) Create a new JSF Components Write a simple component 8
◮ Creating a component ◮ Directly implementing a renderer ◮ Encoding output ◮ Associating a custom tag with a component
Advanced Web Technologies 7) Create a new JSF Components Write a simple component 9
Advanced Web Technologies 7) Create a new JSF Components Write a simple component 10
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Extend a UIComponent 11
JSF does the actual storage and state management, typically though a session, a hidden form field, cookies, etc. (This is usually a setting that you configure.). @Override public Object saveState(FacesContext context) { Object values[] = new Object[2]; values[0] = super.saveState(context); values[1] = label; return ((Object) (values)); } @Override public void restoreState(FacesContext context, Object state) { Object values[] = (Object[])state; super.restoreState(context, values[0]); label = (String)values[1]; }
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Extend a UIComponent 12
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Extend a UIComponent 13
◮ Encode the component output
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Define the renderer 14
◮ The family property shown below is used to associate
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Define the renderer 15
◮ f you’re using the JSF reference implementation from
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Define the renderer 16
◮ Bridging JSF and JSP
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Create a custom tag 17
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Create a custom tag 18
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Create a custom tag 19
[arcmind.tld] <taglib> <tlib−version>0.03</tlib−version> <jsp−version>1.2</jsp−version> <short−name>arcmind</short−name> <uri>http://arcmind.com/jsf/component/tags</uri> <description>ArcMind tags</description> <tag> <name>slabel</name> <tag−class>arcmind.simple.LabelTag</tag−class> <attribute> <name>label</name> <description>The value of the label</description> </attribute> </tag> ...
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Create a custom tag 20
Advanced Web Technologies 7) Create a new JSF Components Write a simple component: Create a custom tag 21
◮ The Field component combines the work of several
◮ The Field component combines label, text input, and
as incorrect input) and also presents an asterisk (*) to denote required fields.
required.
◮ The Field component example demonstrates the
◮ the Field component uses a separate renderer.
Advanced Web Technologies 7) Create a new JSF Components A composite Component 22
<f:view> <h2>CD Form</h2> <h:form id=”cdForm”> <h:inputHidden id=”rowIndex” value=”#{CDManagerBean.rowIndex}” /> <arcmind:field id=”title” value=”#{CDManagerBean.title}” label=”Title:” errorStyleClass=”errorText” required=”true” /> <br /> <arcmind:field id=”artist” value=”#{CDManagerBean.artist}” label=”Artist:” errorStyleClass=”errorText” required=”true” /> <br /> <arcmind:field id=”price” value=”#{CDManagerBean.price}” label=”CD Price:” errorStyleClass=”errorText” required=”true”> <f:validateDoubleRange maximum=”1000.0” minimum=”1.0”/> </arcmind:field>
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Example of JSP file 23
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Example of JSP file 24
package com.arcmind.jsfquickstart; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; /∗∗ @author Richard Hightower ∗/ public class FieldComponent extends UIInput { private String label; @Override public Object saveState(FacesContext context) { Object values[] = new Object[2]; values[0] = super.saveState(context); values[1] = label; return ((Object) (values)); }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Subclass UIInput 25
@Override public void restoreState(FacesContext context, Object state) { Object values[] = (Object[])state; super.restoreState(context, values[0]); label = (String)values[1]; } public FieldComponent (){ this.setRendererType(”arcmind.Field”);} public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } @Override public String getFamily() { return ”arcmind.Field”; } public boolean isError() { return !this.isValid(); } }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Subclass UIInput 26
◮ Field component has several attributes: label,
component,
to have them as properties in the Field component;
that only the renderer knows about.
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Subclass UIInput 27
package com.arcmind.jsfquickstart; import javax.faces.application.Application; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.el.ValueBinding; import javax.faces.webapp.UIComponentTag; /∗∗ @author Richard Hightower ∗/ public class FieldTag extends UIComponentTag { private String label; private String errorStyleClass=””; private String errorStyle=””; private boolean required; private String value=””; public String getLabel() { return label; } public void setLabel(String label) { this.label = label; }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Creating a custom tag for FieldComponent 28
@Override public String getComponentType() { return ”arcmind.Field”; } @Override public String getRendererType() { return ”arcmind.Field”; } @Override protected void setProperties(UIComponent component) { /∗ You have to call the super class ∗/ super.setProperties(component); ((FieldComponent)component).setLabel(label); component.getAttributes().put(”errorStyleClass”, errorStyleClass); component.getAttributes().put(”errorStyle”,errorStyle); ((FieldComponent)component).setRequired(required); FacesContext context = FacesContext.getCurrentInstance(); Application application = context.getApplication(); ValueBinding binding = application.createValueBinding(value); component.setValueBinding(”value”, binding); }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Creating a custom tag for FieldComponent 29
public String getErrorStyleClass() { return errorStyleClass; } public void setErrorStyleClass(String errorStyleClass) { this.errorStyleClass = errorStyleClass; } public String getErrorStyle() { return errorStyle; } public void setErrorStyle(String errorStyle) { this.errorStyle = errorStyle; } public boolean isRequired() { return required; } public void setRequired(boolean required) { this.required = required; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Creating a custom tag for FieldComponent 30
◮ label property is passed through just as it was in the
◮ the errorStyleClass and errorStyle properties are not
class and style attributes.
your component.
◮
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Creating a custom tag for FieldComponent 31
◮ This code allows the value property of the Field
Field component as follows: value="#{CDManagerBean.title}".
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Creating a custom tag for FieldComponent 32
package com.arcmind.jsfquickstart; import java.io.IOException; import java.util.Iterator; import java.util.Map; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.component.UIInput; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import javax.faces.el.ValueBinding; import javax.faces.render.Renderer; /∗∗ ∗ @author Richard Hightower ∗ ∗/ public class FieldRenderer extends Renderer { @Override public Object getConvertedValue(FacesContext facesContext, UIComponent component, Object submittedValue) throws ConverterException { //Try to find out by value binding ValueBinding valueBinding = component.getValueBinding(”value”); if (valueBinding == null) return null; Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 33
Class valueType = valueBinding.getType(facesContext); if (valueType == null) return null; if (String.class.equals(valueType)) return submittedValue; if (Object.class.equals(valueType)) return submittedValue; Converter converter = ((UIInput) component).getConverter(); converter = facesContext.getApplication().createConverter(valueType); if (converter != null ) { return converter.getAsObject(facesContext, component, (String) submittedValue); }else { return submittedValue; } } @Override public void decode(FacesContext context, UIComponent component) { /∗ Grab the request map from the external context ∗/ Map requestMap = context.getExternalContext().getRequestParameterMap(); /∗ Get client ID, use client ID to grab value from parameters ∗/ String clientId = component.getClientId(context); String value = (String) requestMap.get(clientId); FieldComponent fieldComponent = (FieldComponent)component; /∗ Set the submitted value ∗/ ((UIInput)component).setSubmittedValue(value); } Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 34
@Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { FieldComponent fieldComponent = (FieldComponent) component; ResponseWriter writer = context.getResponseWriter(); encodeLabel(writer,fieldComponent); encodeInput(writer,fieldComponent); encodeMessage(context, writer, fieldComponent); writer.flush(); } private void encodeMessage(FacesContext context, ResponseWriter writer, FieldComponent fieldComponent) throws IOException { Iterator iter = context.getMessages(fieldComponent.getClientId(context)); while (iter.hasNext()){ FacesMessage message = (FacesMessage) iter.next(); writer.write(message.getDetail()); } } private void encodeLabel(ResponseWriter writer, FieldComponent fieldComponent) throws IOException{ writer.startElement(”label”, fieldComponent); if (fieldComponent.isError()) { String errorStyleClass = (String) fieldComponent.getAttributes().get(”errorStyleClass”); String errorStyle = (String) fieldComponent.getAttributes().get(”errorStyle”); writer.writeAttribute(”style”, errorStyle, ”style”); writer.writeAttribute(”class”, errorStyleClass, ”class”); } writer.write(”” + fieldComponent.getLabel()); if (fieldComponent.isRequired()) { writer.write(”∗”); } writer.endElement(”label”); } Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 35
private void encodeInput(ResponseWriter writer, FieldComponent fieldComponent) throws IOException{ FacesContext currentInstance = FacesContext.getCurrentInstance(); writer.startElement(”input”, fieldComponent); writer.writeAttribute(”type”, ”text”, ”type”); writer.writeAttribute(”id”, fieldComponent.getClientId(currentInstance), ”id”); writer.writeAttribute(”name”, fieldComponent.getClientId(currentInstance), ”name”); if(fieldComponent.getValue()!=null) writer.writeAttribute(”value”, fieldComponent.getValue().toString(), ”value”); writer.endElement(”input”); } } Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 36
◮ The FieldRenderer’s decode method is as follows:
@Override public void decode(FacesContext context, UIComponent component) { Map requestMap = context.getExternalContext().getRequestParameterMap(); String clientId = component.getClientId(context); String value = (String) requestMap.get(clientId); FieldComponent fieldComponent = (FieldComponent)component; ((UIInput)component).setSubmittedValue(value); }
◮ The Field Renderer’s decode method grabs the clientId from the
component to identify the request parameter to be looked up.
◮ The clientId is calculated as the fully qualified name of the component
given its container path. (ex: cdForm:artist, cdForm:price, cdForm:title).
Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 37
◮ The encoding methods offer no real surprises.
Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 38
◮ The encodeLabel method is responsible for changing the color of the
label in the case of errors and using asterisks (*) to denote required fields, private void encodeLabel(ResponseWriter writer, FieldComponent fieldComponent) throws IOException{ writer.startElement(”label”, fieldComponent); if (fieldComponent.isError()) { String errorStyleClass = (String) fieldComponent.getAttributes() .get(”errorStyleClass”); String errorStyle = (String) fieldComponent.getAttributes() .get(”errorStyle”); writer.writeAttribute(”style”, errorStyle, ”style”); writer.writeAttribute(”class”, errorStyleClass, ”class”); } writer.write(”” + fieldComponent.getLabel()); if (fieldComponent.isRequired()) { writer.write(”∗”); } writer.endElement(”label”); }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 39
◮ use the method getConvertedValues to look up the associated
converter and invoke it. @Override public Object getConvertedValue(FacesContext facesContext, UIComponent component, Object submittedValue) throws ConverterException { ValueBinding valueBinding = component.getValueBinding(”value”); if (valueBinding == null) return null; Class valueType = valueBinding.getType(facesContext); if (valueType == null) return null; if (String.class.equals(valueType)) return submittedValue; if (Object.class.equals(valueType)) return submittedValue; Converter converter = ((UIInput) component).getConverter(); converter = facesContext.getApplication().createConverter(valueType); if (converter != null ) { return converter.getAsObject(facesContext, component, (String) submittedValue); }else { return submittedValue; } }
Advanced Web Technologies 7) Create a new JSF Components A composite Component: The Renderer 40
Advanced Web Technologies 7) Create a new JSF Components A composite Component: Mapping a renderer to a component 41
◮
◮ Download examples of these sildes:
Advanced Web Technologies 7) Create a new JSF Components Conclusion 42
◮ http://www-128.ibm.com/developerworks/java/
Advanced Web Technologies 7) Create a new JSF Components Conclusion 43