0

Maybe I do not understand the servlet lifecycle very well, but this is what i want: I want to display a page generated by a servlet let's say servlet: paginaAmd. On this page I want to display a list of images stored in folder on web server. The address of url of the images is something like: /img/80-80-1-1-1-1-1-1-1-1-1 where /img/* is my servlet for displaying images.

All works well if I want to display one image at a time in browser. But when I want to put all the list at once, the images are not displayed correctly. Sometimes are not displayed at all, sometimes are displayed in wrong position (the position does not alter in time), and sometimes are displayed only some images.

I suspect that somehow not all the doGet() methods are catched.

Can someone give me some advice? Here are the servlet code witch is implemented by the tutorial here: http://balusc.blogspot.fr/2007/04/imageservlet.html

@WebServlet(name = "ImgDisplay", urlPatterns = {"/img/*"})
public class ImgDisplay extends HttpServlet
{
    private SessionFactory sessionfactory = new AnnotationConfiguration().configure().buildSessionFactory();
    private Query query;
    private String mesajEroare = "";
    private HttpServletRequest _request;
    private HttpServletResponse _response;

    private int width = 0;
    private int height = 0;
    private int idImagine = 0;
    private int format = 0;
    private String titluArticol = "";
    private String numeImagine = "";
    private boolean imgValida = false;

    private int DEFAULT_BUFFER_SIZE = 1024 * 100;

    String fileUploadPath = "";


    @Override
    public void init() throws ServletException {
    }



    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        this._request = request;
        this._response = response;


        this.SetVariabile();

        if(imgValida)
        {
            String nImagine = this.GetImageFromDisk();
            this.DisplayImage(nImagine);
        }

    }








    private void SetVariabile()
    {
        String reqUrl = _request.getRequestURL().toString();

        String aUrl[] = reqUrl.split("/");
        String urlImg = aUrl[aUrl.length - 1];

        aUrl = urlImg.split("-");
        try
        {
            this.width = Integer.parseInt(aUrl[0]);
            this.height = Integer.parseInt(aUrl[1]);
            this.idImagine = Integer.parseInt(aUrl[2]);
            this.format = Integer.parseInt(aUrl[3]);
            this.numeImagine = aUrl[aUrl.length - 1];
            this.imgValida = true;
        }
        catch(Exception e)
        {
            this.imgValida = false;
        }

    }




    private String GetImageFromDisk()
    {
        String nImagine;
        //preiau imaginea
        PaginiImagini pa = new PaginiImagini();
        Session session;
        try
        {
            session = sessionfactory.openSession();
            session.beginTransaction();

            query = session.getNamedQuery("PaginiImagini.findByImagineID");
            query.setInteger("imagineID", this.idImagine);
            pa = (PaginiImagini) query.uniqueResult();
            session.getTransaction().commit();
            session.close();
        }
        catch( Exception e )
        {
            this.mesajEroare = "Nu pot citi din baza de date!";
        }

        // citesc imagine de pe disk
        ServletContext sctx = getServletContext();
        this.fileUploadPath = sctx.getInitParameter("file-upload-path");
        String pathImagine = this.fileUploadPath + "/" + Setari.pathImaginiMici;
        if(this.width > Setari.wImagineMica || this.height > Setari.hImagineMica)
        {
            pathImagine = this.fileUploadPath + "/" + Setari.pathImaginiMari;
        }

        nImagine =  pathImagine + "/" + pa.getNumeImaginePeDisc();
        return nImagine;
    }






    private void DisplayImage(String imageToRead) throws FileNotFoundException, IOException
    {
        File image = new File(imageToRead);

        String contentType = getServletContext().getMimeType(image.getName());
        _response.setContentType(contentType);
        _response.setHeader("Content-Length", String.valueOf(image.length()));
        _response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\"");
        _response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        _response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        _response.setDateHeader("Expires", 0); // Proxies.

        // Prepare streams.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try
        {
            // Open streams.
            input = new BufferedInputStream(new FileInputStream(image), DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(_response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            // Write file contents to response.
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0)
            {
                output.write(buffer, 0, length);
            }
        }
        finally
        {
            // Gently close streams.
            close(output);
            close(input);
        }

    }





    /**
     *
     * @param resource
     */
    private static void close(Closeable resource)
    {
        if (resource != null)
        {
            try
            {
                resource.close();
            }
            catch (IOException e)
            {
                // Do your thing with the exception. Print it, log it or mail
                // it.
                //e.printStackTrace();
            }
        }
    }



}
virgil66ro
  • 27
  • 1
  • 5
  • Related: [How do servlets work? Instantiation, session variables and multithreading](http://stackoverflow.com/a/3106909) – BalusC Jan 27 '13 at 20:35

1 Answers1

2

You have serious concurrency issues in your servlet. A single instance of the servlet is used to serve all the requests to this servlet. So a servlet should be stateless. But the first thing you're doing is

this._request = request;
this._response = response;

This means that if two concurrent requests are made to the servlet, you might have the first one set these two instance variables, then the second one resetting the same instance variables. The first image would thus be sent as a response to the second request, and nothing would be sent as a response to the first request. And this is only one of the strange things that could happen. You could also have exceptions and inconsistent data.

Don't store the request and response (and any other state) in instance variables. Pass them from method to method. I've not analyzed the whole code, but the only instance field that you should have in the servlet is sessionFactory field.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255