0

I am doing a project for school. Subject of project is tshirt design. I am using jsf and primefaces. But I don't know well jsf and primefaces. I wanted save a base64 from html as image in jsf project. But when I had tried to following functions, NullPointerException. This function is called in a Servlet. A base64 is grabbed by this Servlet.

public static void save(String dataURL){

line85: ExternalContext external = FacesContext.getCurrentInstance().getExternalContext();
    ServletContext servletContext = (ServletContext) external.getContext();
    String filename = servletContext.getRealPath("cloud.png");
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] decodedBytes;
    try {

        decodedBytes = decoder.decodeBuffer(dataURL.split("data:image/(png|jpg);base64,")[1]);
        BufferedImage imag=ImageIO.read(new ByteArrayInputStream(decodedBytes));
        ImageIO.write(imag, "png", new File(filename));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}




    23.Ara.2012 17:48:20 org.apache.catalina.core.StandardWrapperValve invoke
     SEVERE: Servlet.service() for servlet [org.soft.tshirt.servlets.DesignServlet] in context              with path [/Tshirt] threw exception
    java.lang.NullPointerException
at org.soft.tshirt.beans.ImageBean.save(ImageBean.java:85)
at org.soft.tshirt.servlets.DesignServlet.processRequest(DesignServlet.java:102)
at org.soft.tshirt.servlets.DesignServlet.doPost(DesignServlet.java:76)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at       
   org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
tufan
  • 77
  • 2
  • 10

1 Answers1

1

The current instance of the FacesContext is only available in the HTTP request thread which is been served through the FacesServlet who is the one responsible for creating the FacesContext. In other words, only when the request URL matches the URL pattern of the FacesServlet. In other words, only JSF pages, JSF managed beans (and thus not backing beans which you instantiate yourself like as is happening here!) and all other JSF artifacts like event/phase listeners, UI components, etc have the current instance of the FacesContext available to them.

In an arbitrary homegrown HTTP servlet, the FacesContext isn't available at all, for the simple reason that the FacesServlet is not been invoked beforehand. So the getCurrentInstance() method on it would return null. You know, trying to access/invoke any fields/method on null will cause NullPointerException. See also its javadoc.

In order to achieve the sole goal of obtaining the ServletContext, just invoke the inherited GenericServlet#getServletContext() method inside the servlet.

protected void doPost(...) {
    String filename = getServletContext().getRealPath("cloud.png");
    // ...
}

Pass that information instead to the method responsible for creating the file. You might want to extract that code into a different class which is reused between your servlet and backing bean.


Unrelated to the concrete problem, writing files to the expanded WAR folder is really a bad practice for the reasons mentioned in among others this answer: Uploaded image only available after refreshing the page.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you. I am trying that you said now. Also, Called function in Servlet as ImageBean.save(dataURL). ImageBean is a ManagedBean. save function is defined ImageBean. – tufan Dec 23 '12 at 14:17
  • It's in this context not a managed bean at all. You're not using the one which is instantiated by JSF and placed in EL `#{}` scope. The backing bean class is just been "abused" as an utility class. Did you understand in any way how and when the `FacesContext` is available? – BalusC Dec 23 '12 at 14:18
  • I tried to save base 64 directly in servlet getServletContext().getRealPath("cloud.png"), but again nullpointerexception. Servlet grabs base64 from html5 with jquery.post() so I can't design image in xhtml (jsf). – tufan Dec 23 '12 at 14:24
  • What exactly is now `null` (by the way, do you understand what `NullPointerException` actually means? you seem to nowhere in your comment identify what object exactly is `null` while you're trying to access it) – BalusC Dec 23 '12 at 14:25
  • error:`servlet calisti 23.Ara.2012 19:33:10 org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [org.soft.tshirt.servlets.DesignServlet] in context with path [/Tshirt] threw exception java.lang.NullPointerException at javax.servlet.GenericServlet.getServletContext(GenericServlet.java:125) at org.soft.tshirt.servlets.DesignServlet.processRequest(DesignServlet.java:114) at org.soft.tshirt.servlets.DesignServlet.doPost(DesignServlet.java:84) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at .... ` – tufan Dec 23 '12 at 14:35
  • code: `doPost( System.out.println("servlet calisti"); line114: String filename = getServletContext().getRealPath("cloud.png"); System.out.println("servlet1"); BASE64Decoder decoder = new BASE64Decoder(); System.out.println("servlet2"); byte[] decodedBytes; try { System.out.println("servlet3"); decodedBytes = decoder.decodeBuffer(dataURL.split("data:image/(png|jpg);base64,")[1]); BufferedImage imag=ImageIO.read(new ByteArrayInputStream(decodedBytes)); ImageIO.write(imag, "png", new File(filename));... }` – tufan Dec 23 '12 at 14:35
  • This suggests that you've incorrectly overridden the `init(ServletConfig config)` method without delegating to `super.init(config)`. See also among others this answer: http://stackoverflow.com/questions/3036855/java-servlet-getinitparameter-not-work-in-service/3037238#3037238 It's recommended to not use the `init(ServletConfig config)` at all, but only the argumentless `init()`. – BalusC Dec 23 '12 at 14:37
  • Thank you. I tried. Error is disappeared. But I don't find cloud.png – tufan Dec 23 '12 at 14:43
  • Please read the "Unrelated" part of my answer. Refresh your IDE project's folder structure. Or, better, don't write the file to there at all. – BalusC Dec 23 '12 at 14:49
  • I searched cloud.png in windows project folder but I don't find. – tufan Dec 23 '12 at 15:01
  • Print/debug the value of `filename` (it returns an absolute disk file system path) and look in there by Windows Explorer. Do you by the way **understand** the problem why you should not be writing anything to the deploy folder at all? You seem to not have carefully read the link mentioned in the "Unrelated" part of my answer. – BalusC Dec 23 '12 at 15:03
  • Thank you. I found it under deploy folder. My English is not well. I am learning English. So I can't understand well that some sentences. – tufan Dec 23 '12 at 15:11