1

I am trying to return a image with ServletContext but I get a 500 error and the console says:

java.lang.NullPointerException: null at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2146) at org.apache.commons.io.IOUtils.copy(IOUtils.java:2102) at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2123) at org.apache.commons.io.IOUtils.copy(IOUtils.java:2078) at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:721)

Configuration:

@Configuration
public class ImageConfiguration {

    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(byteArrayHttpMessageConverter());
    }

    @Bean
    public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
        ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
        arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
        return arrayHttpMessageConverter;
    }

    private List<MediaType> getSupportedMediaTypes() {
        List<MediaType> list = new ArrayList<MediaType>();
        list.add(MediaType.IMAGE_JPEG);
        list.add(MediaType.IMAGE_PNG);
        list.add(MediaType.APPLICATION_OCTET_STREAM);
        return list;
    }
}

Service:

@Service
public class ImageService {

    @Autowired
    ServletContext servletContext;

    public byte[] getRankImage (String id) throws IOException {

        byte[] b;

            InputStream in;


        if (id.equals("0")) {
            in = servletContext.getResourceAsStream("images/level-0.png");
            return IOUtils.toByteArray(in);

restful service:

@RequestMapping(value = "/level/{id}", method = RequestMethod.GET)
    public ResponseEntity<byte[]> getImage(@PathVariable("id") String id) {
        byte[] imageBytes;

        try {
            imageBytes = imageService.getRankImage(id);
            return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(imageBytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

The images are located in resources -> images -> {image_name} when I look in the war file I confirm that they are in there. I am not sure if I am doing this wrong or I need to handle the path differently.

---------Update 1-------

I took the war file and deployed it manually in apache and this is the output: enter image description here

Mike3355
  • 11,305
  • 24
  • 96
  • 184

2 Answers2

0

In ImageService class, you autowired ServletContext instance.

Spring container will not autowire servletContext as it is not a spring bean. ServletContext is from javax.servlet package.

You can inject the instance using setter method as shown below.

@Service
public class ImageService implements ServletContextAware{

     private ServletContext context;

     public void setServletContext(ServletContext servletContext) {
        this.context = servletContext;
     }

     // use `context` object to get the image and pass to IOUtils.toByteArray method
}

By implementing ServletContextAware interface, Spring will inject it for you.

Ideally, we shouldn't be injecting ServletContext instance outside the Controller layer. Here, we are injecting in Service layer which isn't the recommended approach.

Hope this helps!

harshavmb
  • 3,404
  • 3
  • 21
  • 55
  • `java.lang.NullpointerEception: null` yes same error. The files are located in `recources -> images -> {image_name}` – Mike3355 Jun 12 '17 at 15:39
  • `if (id.equals("0")) { in = servletContext.getResourceAsStream("images/level-0.png"); return IOUtils.toByteArray(in); }` – Mike3355 Jun 12 '17 at 15:41
  • Don't think it would work with spring-boot. I think servlet context resources work with `war`. I think they work in `/src/main/webapp` rather `/src/main/resources`. Are you running it as a jar? – harshavmb Jun 12 '17 at 16:25
  • Have you verified whether the images are located in the same location inside jar? Have you exploded and checked? – harshavmb Jun 12 '17 at 16:28
  • I just updated the post. I am not seeing my images as I would typically see in a war file. The format looks off - I am using spring boots internal apache server – Mike3355 Jun 12 '17 at 16:43
  • Any reason you are using resourceloader? Since, they are images, why don't you consider loading the images from external filesystem using file api? – harshavmb Jun 12 '17 at 16:45
  • Going off this post: http://www.baeldung.com/spring-mvc-image-media-data – Mike3355 Jun 12 '17 at 17:22
  • In the above link, they are fetching from `WEB-INF/*` which is apt for MVC projects. I would suggest you to load from external filesystem rather bulging your war.. :) Good luck! – harshavmb Jun 12 '17 at 17:31
  • is byte array which is returned from getRankImage empty or not? if it is empty you will know that you do not have correct path. I think this link can help you https://stackoverflow.com/questions/36371748/spring-boot-access-static-resources-missing-scr-main-resources – mommcilo Jun 15 '17 at 10:36
0

From http://www.xyzws.com/servletfaq/how-to-use-servletcontextgetresourceasstreamjavalangstring-path/18 , the line

in = servletContext.getResourceAsStream("images/level-0.png");

should have a / before the images, and the path should be relative to the current context root (parent of WEB-INF).

mikep
  • 3,841
  • 8
  • 21