Custom component renderer failing
Hello,
I am trying to implement a file upload custom component by using the Core JSF book. Right now, when I try to access the page where my custom component is, I am getting the following error:
[ServletException in:/jsps/tiles/User.jsp] com.highmark.qcr.app.customtags.UploadRenderer' ]
My renderer class for the Tag is set up as:
package com.highmark.qcr.app.customtags;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import javax.faces.FacesException;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import javax.faces.render.Renderer;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
publicclass UploadRendererextends Renderer{
public UploadRenderer(){
System.err.println("UploadRenderer cstr");
}
publicvoid encodeBegin(FacesContext context, UIComponent component)
throws IOException{
System.err.println("UploadRenderer");
if (!component.isRendered())
return;
ResponseWriter writer = context.getResponseWriter();
String clientId = component.getClientId(context);
writer.startElement("input", component);
writer.writeAttribute("type","file","type");
writer.writeAttribute("name", clientId,"clientId");
writer.endElement("input");
writer.flush();
}
publicvoid decode(FacesContext context, UIComponent component){
System.err.println("decode");
ExternalContext external = context.getExternalContext();
HttpServletRequest request = (HttpServletRequest) external.getRequest();
String clientId = component.getClientId(context);
FileItem item = (FileItem) request.getAttribute(clientId);
Object newValue;
ValueBinding binding = component.getValueBinding("value");
if (binding !=null){
// sometimes item is null, due to being hidden
if (item !=null){
if (binding.getType(context) ==byte[].class){
newValue = item.get();
}
if (binding.getType(context) == InputStream.class){
try{
newValue = item.getInputStream();
}catch (IOException ex){
thrownew FacesException(ex);
}
}else{
String encoding = request.getCharacterEncoding();
if (encoding !=null)
try{
newValue = item.getString(encoding);
}catch (UnsupportedEncodingException ex){
newValue = item.getString();
}
else
newValue = item.getString();
}
}else
newValue ="";
((EditableValueHolder) component).setSubmittedValue(newValue);
}
Object target;
binding = component.getValueBinding("target");
if (binding !=null)
target = binding.getValue(context);
else
target = component.getAttributes().get("target");
if (target !=null){
File file;
if (targetinstanceof File)
file = (File) target;
else{
ServletContext servletContext = (ServletContext) external.getContext();
file =new File(servletContext.getRealPath("/"), target.toString());
}
try{// ugh--write is declared with "throws Exception"
item.write(file);
}catch (Exception ex){
thrownew FacesException(ex);
}
}
}
}
I also have it defined in faces-config as:
<component>
<component-type>Upload</component-type>
<component-class>com.highmark.qcr.app.customtags.UploadRenderer</component-class>
<attribute>
<attribute-name>target</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
<attribute>
<attribute-name>value</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</component>
And I am calling it on my JSP as:
<%@taglib uri="/WEB-INF/my-custom.tld" prefix="qcr" %>
<qcr:upload target="c:/" value="c:/"/>
Any ideas as to what I'm missing?

