title: Trying to create my own image uploader (JSF)
body: <p>I want to upload images from the client to the server. I already managed to do it using gadgets like primefaces. But this time, i want to try to do it on my own i found information on the web on how to do it, but i am kind of stuck. 
  My current problem is that the browser says to me that the tag that i created for doing the upload, is not bound. I would like to understand, why the application does not find it and how should i fix it.</p>
  
  <p>I will paste all i did till now so you can help me find the mistake:</p>
  
  <p><strong>1.Added commons-fileupload-1.2.1.jar and commons-io-1.4.jar to the lib folder(Automatically get added to the classpath)</strong></p>
  
  <p><img src="https://i.stack.imgur.com/VnEcM.png" alt="enter image description here"></p>
  
  <p><strong>2.Created an xml that wil make the tag library available(This is placed inside WEB-INF folder)</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;facelet-taglib version="2.0"
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"&gt;
     &lt;namespace&gt;http://corejsf.com&lt;/namespace&gt;
     &lt;tag&gt;
        &lt;tag-name&gt;upload&lt;/tag-name&gt;
        &lt;component&gt;
           &lt;component-type&gt;javax.faces.Input&lt;/component-type&gt;
           &lt;renderer-type&gt;com.corejsf.Upload&lt;/renderer-type&gt;
        &lt;/component&gt;
     &lt;/tag&gt;
  &lt;/facelet-taglib&gt;
  </code></pre>
  
  <p><strong>3.Create a package for the implementation of the tag and place in a new package called com.corejsf;</strong></p>
  
  <p><img src="https://i.stack.imgur.com/Ww5bs.png" alt="enter image description here"></p>
  
  <p>Here is the source:</p>
  
  <pre><code>package com.corejsf;
  
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.UnsupportedEncodingException;
  import javax.el.ValueExpression;
  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.render.FacesRenderer;
  import javax.faces.render.Renderer;
  import javax.servlet.ServletContext;
  import javax.servlet.http.HttpServletRequest;
  import org.apache.commons.fileupload.FileItem;
  
  @FacesRenderer(componentFamily="javax.faces.Input",
     rendererType="com.corejsf.Upload")
  public class UploadRenderer extends Renderer {
     public void encodeBegin(FacesContext context, UIComponent component)  
        throws IOException {
        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();
     }
  
     public void decode(FacesContext context, UIComponent component) {
        ExternalContext external = context.getExternalContext(); 
        HttpServletRequest request = (HttpServletRequest) external.getRequest();
        String clientId = component.getClientId(context);
        FileItem item = (FileItem) request.getAttribute(clientId);
  
        Object newValue;
        ValueExpression valueExpr = component.getValueExpression("value");
        if (valueExpr != null) {
           Class&lt;?&gt; valueType = valueExpr.getType(context.getELContext());
           if (valueType == byte[].class) {
              newValue = item.get();
           }
           else if (valueType == InputStream.class) {
              try {
                 newValue = item.getInputStream();
              } catch (IOException ex) {
                 throw new 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(); 
           }
           ((EditableValueHolder) component).setSubmittedValue(newValue);  
           ((EditableValueHolder) component).setValid(true);  
        }
  
        Object target = component.getAttributes().get("target");
  
        if (target != null) {
           File file;
           if (target instanceof File)
              file = (File) target;
           else {
              ServletContext servletContext 
                 = (ServletContext) external.getContext();
              String realPath = servletContext.getRealPath(target.toString());
              file = new File(realPath); 
           }
  
           try { // ugh--write is declared with "throws Exception"
              item.write(file);
           } catch (Exception ex) { 
              throw new FacesException(ex);
           }
        }
     }   
  }
  </code></pre>
  
  <p><strong>4.Then I added a servlet  filter, to distinguish to intercept the requests and placed it in the same package as the custom tag implementation</strong></p>
  
  <p><img src="https://i.stack.imgur.com/mXmdj.png" alt="enter image description here"></p>
  
  <p>This is its source:</p>
  
  <pre><code>package com.corejsf;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import javax.servlet.Filter;
  import javax.servlet.FilterChain;
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletRequestWrapper;
  import org.apache.commons.fileupload.FileItem;
  import org.apache.commons.fileupload.FileUploadException;
  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  import org.apache.commons.fileupload.servlet.ServletFileUpload;
  
  public class UploadFilter implements Filter {
     private int sizeThreshold = -1;
     private String repositoryPath;
  
     public void init(FilterConfig config) throws ServletException {
        repositoryPath = config.getInitParameter(
           "com.corejsf.UploadFilter.repositoryPath");
        try {
           String paramValue = config.getInitParameter(
              "com.corejsf.UploadFilter.sizeThreshold");
           if (paramValue != null) 
              sizeThreshold = Integer.parseInt(paramValue);
        }
        catch (NumberFormatException ex) {
           ServletException servletEx = new ServletException();
           servletEx.initCause(ex);
           throw servletEx;
        }
     }
  
     public void destroy() {
     }
  
     public void doFilter(ServletRequest request, 
        ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
  
        if (!(request instanceof HttpServletRequest)) {
           chain.doFilter(request, response);
           return;
        }
  
        HttpServletRequest httpRequest = (HttpServletRequest) request;
  
        boolean isMultipartContent 
           = ServletFileUpload.isMultipartContent(httpRequest);
        if (!isMultipartContent) {
           chain.doFilter(request, response);
           return;
        }
  
        DiskFileItemFactory factory = new DiskFileItemFactory();
        if (sizeThreshold &gt;= 0)
           factory.setSizeThreshold(sizeThreshold);
        if (repositoryPath != null) 
           factory.setRepository(new File(repositoryPath));
        ServletFileUpload upload = new ServletFileUpload(factory);
  
        try {
           @SuppressWarnings("unchecked") List&lt;FileItem&gt; items 
              = (List&lt;FileItem&gt;) upload.parseRequest(httpRequest);
           final Map&lt;String, String[]&gt; map = new HashMap&lt;String, String[]&gt;();
           for (FileItem item : items) {
              String str = item.getString();
              if (item.isFormField())
                 map.put(item.getFieldName(), new String[] { str });
              else
                 httpRequest.setAttribute(item.getFieldName(), item);
           }
  
           chain.doFilter(new 
              HttpServletRequestWrapper(httpRequest) {
                 public Map&lt;String, String[]&gt; getParameterMap() {
                    return map;
                 }                   
                 // busywork follows ... should have been part of the wrapper
                 public String[] getParameterValues(String name) {
                    Map&lt;String, String[]&gt; map = getParameterMap();
                    return (String[]) map.get(name);
                 }
                 public String getParameter(String name) {
                    String[] params = getParameterValues(name);
                    if (params == null) return null;
                    return params[0];
                 }
                 public Enumeration&lt;String&gt; getParameterNames() {
                    Map&lt;String, String[]&gt; map = getParameterMap();
                    return Collections.enumeration(map.keySet());
                 }
              }, response);
        } catch (FileUploadException ex) {
           ServletException servletEx = new ServletException();
           servletEx.initCause(ex);
           throw servletEx;
        }      
     }   
  }
  </code></pre>
  
  <p><strong>5.Then I registered the filter in the web.xml. (I wanted to use an annotation but I didn’t know how, does someon know how can I do that with an annotation?) 
  Also added the corejsf.taglib.xml</strong></p>
  
  <pre><code>&lt;!-- NEEDED FOR FILE UPLOAD --&gt;
  &lt;filter&gt;
        &lt;filter-name&gt;Upload Filter&lt;/filter-name&gt;
        &lt;filter-class&gt;com.corejsf.UploadFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
           &lt;param-name&gt;sizeThreshold&lt;/param-name&gt;
           &lt;param-value&gt;1024&lt;/param-value&gt;
        &lt;/init-param&gt;
  &lt;/filter&gt;
  
     &lt;filter-mapping&gt;
        &lt;filter-name&gt;Upload Filter&lt;/filter-name&gt;
        &lt;url-pattern&gt;/faces/upload/*&lt;/url-pattern&gt;
     &lt;/filter-mapping&gt; 
  
      &lt;context-param&gt;
        &lt;param-name&gt;javax.faces.PROJECT_STAGE&lt;/param-name&gt;
        &lt;param-value&gt;Development&lt;/param-value&gt;
     &lt;/context-param&gt;
     &lt;context-param&gt;
        &lt;param-name&gt;facelets.LIBRARIES&lt;/param-name&gt;
        &lt;param-value&gt;/WEB-INF/corejsf.taglib.xml&lt;/param-value&gt;
     &lt;/context-param&gt;   
  </code></pre>
  
  <p><strong>6.On my WebContent folder I created a subfolder called upload(Destination of the uploaded files)</strong></p>
  
  <p><img src="https://i.stack.imgur.com/U5paD.png" alt="enter image description here"></p>
  
  <p><strong>7.Inside a jsf page I use the tag for upload and submit and also use a managed bean method to create the file names:</strong></p>
  
  <pre><code> ....
  
  &lt;corejsf:upload target="upload/#{placeAddController.prepareUniqueIdentifier}" /&gt;
  
   ....
  
  &lt;h:commandButton value="Dalje" style=" font-weight: bold;  font-size:150%; action="/submittedImage" /&gt;  
  </code></pre>
  
  <p>And the java managedbean:</p>
  
  <pre><code>@ManagedBean
  @RequestScoped
  public class PlaceAddControler {
  …
  public String prepareUniqueIdentifier() {
          return UUID.randomUUID().toString()+"png";
      }   
  </code></pre>
  
  <p>The error i see is when navigating to the page where the new tag is added is this:</p>
  
  <pre><code>javax.faces.view.facelets.FaceletException: Error Parsing /oglas.xhtml: Error Traced[line: 183] The prefix "corejsf" for element "corejsf:upload" is not bound.
      at com.sun.faces.facelets.compiler.SAXCompiler.doCompile(SAXCompiler.java:387)
      at com.sun.faces.facelets.compiler.SAXCompiler.doMetadataCompile(SAXCompiler.java:370)
      at com.sun.faces.facelets.compiler.Compiler.metadataCompile(Compiler.java:123)
      at com.sun.faces.facelets.impl.DefaultFaceletFactory.createMetadataFacelet(DefaultFaceletFactory.java:353)
      at com.sun.faces.facelets.impl.DefaultFaceletFactory.getMetadataFacelet(DefaultFaceletFactory.java:231)
      at com.sun.faces.facelets.impl.DefaultFaceletFactory.getMetadataFacelet(DefaultFaceletFactory.java:164)
      at com.sun.faces.application.view.ViewMetadataImpl.createMetadataView(ViewMetadataImpl.java:102)
      at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:239)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
      at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
      at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
      at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
      at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
      at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
      at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
      at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
      at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
      at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
      at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
      at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
      at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
      at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
      at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
      at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
      at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
      at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
      at java.lang.Thread.run(Thread.java:662)
  </code></pre>
  
  <p>-What i am missing?</p>
  
  <p>-What else do i need to do to transfer a file from the client to the serverfile system with an unique fileName, inside the upload folder. </p>
  
  <p>My final goal is not to add this images into the database, just leave them in the file system.</p>
  
  <p>I hope someone can help me.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I added the xmlns, to my page and that fixed the exception:</p>
  
  <blockquote>
    <p>xmlns:corejsf="http://corejsf.com"</p>
  </blockquote>
  
  <p>But why when i click on the button, the file is not uploaded???</p>