1

Hi i have tried following this very helpful tut found here:

http://balusc.blogspot.co.uk/2007/04/imageservlet.html

I am following the tutorial to try and create my image servlet which retrieves an image from a database and displays it the the user on my jsp page. As far as i am aware the code looks ok, but the console is showing me a 500 internal error and my server console indicates that my Image variable is null here:

Image image = dataManager.getPhotos(homeId);

Below is my complete code:

@WebServlet(name = "ImageServlet", urlPatterns = {"/Image"})
public class ImageServlet extends HttpServlet {

private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
private static DatabaseConnector dataManager;

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    // Get ID from request.
    String homeId = request.getParameter("id");

    // Check if ID is supplied to the request.
    if (homeId == null) {
        // Do your thing if the ID is not supplied to the request.
        // Throw an exception, or send 404, or show default/warning image, or just ignore it.
        response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
        return;
    }
    try {
        // Lookup Image by ImageId in database.
        // Do your "SELECT * FROM Image WHERE ImageID" thing.
        Image image = dataManager.getPhotos(homeId);

        // Check if image is actually retrieved from database.
        if (image == null) {
            // Do your thing if the image does not exist in database.
            // Throw an exception, or send 404, or show default/warning image, or just ignore it.
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
            return;
        }

        // Init servlet response.
        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setContentType("image/png");
        response.setHeader("Content-Length", String.valueOf(image.getLength()));
        response.setHeader("Content-Disposition", "inline; filename=\"" + image.getHomeID() + "\"");

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

        try {
            // Open streams.
            input = new BufferedInputStream(image.getContent(), 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);
        }

    } catch (IllegalArgumentException ex) {
        Logger.getLogger(ImageServlet.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SQLException ex) {
        Logger.getLogger(ImageServlet.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(ImageServlet.class.getName()).log(Level.SEVERE, null, ex);
    }
}

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();
        }
    }
}

My Database Connector below handles and retrieves the data below:

 public Image getPhotos(String homeID) throws
        IllegalArgumentException, SQLException, ClassNotFoundException {

    createConnection();

    Image img = new Image();

    ResultSet rs = null;
    PreparedStatement preparedStatement = null;

    String strQuery = "SELECT * "
            + "FROM home_photo "
            + "WHERE home_photo.home_id = ?";

    try {
        preparedStatement = conn.prepareStatement(strQuery);
        preparedStatement.setString(1, homeID);
        rs = preparedStatement.executeQuery();

        while (rs.next()) {
            img.setHomeID(rs.getInt("home_id"));
            img.setPhotoID(rs.getInt("photo_id"));
            img.setContent(rs.getBinaryStream("photo"));
            img.setDescription(rs.getString("description"));
            img.setLength(rs.getInt("length"));
            img.setContentType(rs.getString("type"));
        }

    } catch (SQLException e) {
        throw new SQLException(e);
    }

    closeConnection();
    return img;
}

Of which i cant see where it would return img and null?

Help appreciated.

user1851487
  • 547
  • 5
  • 13
  • 28

1 Answers1

2

The problem and the code suggests that it's actually the dataManager which is null. The code is written in such way that if the image would ever be null, then it would just return a 404, not a 500 with a NullPointerException.

You need to make sure that the dataManager is not null, e.g. by instantiating it in init() method, or if it's an EJB, by injecting it as @EJB.


Unrelated to the concrete problem, the DatabaseConnector being a static variable and the JDBC Connection being declared as an instance variable is also not a good sign. This code is not thread safe. Start here to learn how to write proper JDBC code: Is it safe to use a static java.sql.Connection instance in a multithreaded system? On the very same blog as you found the image servlet, you can also find a basic JDBC DAO tutorial.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Hi, thank you for the reply. i have used an int() method to instatiante the dataManager. But the code has now fired a "Stream Closed" exception in my console at the while loop in the servlet – user1851487 Jan 18 '13 at 12:17
  • 1
    That's actually a different problem for which you should have asked a new question :) But ala, you need to replace `InputStream content` by `byte[] content` and use `ResultSet#getBytes()` to obtain it. It's basically caused by `InputStream` not being available anymore after closing the connection. – BalusC Jan 18 '13 at 12:20