Buddhika Ariyaratne
Buddhika Ariyaratne

Reputation: 2423

JSF Dynamic Image as div Background

I generate dynamic images from a backend database using streamed content. They work fine when used with p:graphicImage.

The issue comes when such a dynamic image needs to be the background of div.

How can I use dynamic images created with stream content as a background of a div element?

JSF Controller

public StreamedContent imageByCodeInlineWithoutGet(String code) {
    FacesContext context = FacesContext.getCurrentInstance();
    if (context.getRenderResponse()) {
        return new DefaultStreamedContent();
    } else {

        String id = code;
        if (id == null) {
            return new DefaultStreamedContent();
        }
        String j = "select s from Upload s where lower(s.code)=:id";
        Map m = new HashMap();
        m.put("id", id.trim().toLowerCase());
        Upload temImg = getUploadFacade().findFirstByJpql(j, m);
        if (temImg != null) {
            byte[] imgArr = null;
            try {
                imgArr = temImg.getBaImage();
            } catch (Exception e) {
                return new DefaultStreamedContent();
            }
            if (imgArr == null) {
                return new DefaultStreamedContent();
            }
            StreamedContent str = new DefaultStreamedContent(new ByteArrayInputStream(imgArr), temImg.getFileName());
            return str;
        } else {
            return new DefaultStreamedContent();
        }
    }
}

Generating Images Dynamically

                                <p:graphicImage cache="false"  value="#{streamedContentController.imageByCodeInlineWithoutGet('header__logo')}"  >
                                </p:graphicImage>

I want to use the image as a css background like below

                        <style type="text/css">
                            background-image:#{streamedContentController.imageByCodeInlineWithoutGet('header__logo')};
                        </style>

or Passing as a parameter.

                    <div class="hero__item set-bg" data-setbg="#{streamedContentController.imageByCodeInlineWithoutGet('header__logo')}">
                        </div>
                    </div>

Is it possible with JSF or PrimeFaces or any other library ?

Upvotes: 1

Views: 474

Answers (1)

fuggerjaki61
fuggerjaki61

Reputation: 821

The easiest way of sending custom content on a GET request for a specific path is a HttpServlet.

Just starting with a kick-off example:

@WebServlet("/images/*")
public class ImageServlet extends HttpServlet {

    @EJB
    private YourEJB imageEJB; // your EJB for images

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // get the image code from the requested path
        String imageCode = request.getPathInfo().substring(1);

        // get the image type and byte array as the content

        response.setContentType(getServletContext().getMimeType(/* image type */);
        // OR
        response.setContentType(/* image mime type */);

        response.setContentLength(/* byte array length */); // just 'array.length'
        response.getOutputStream().write(/* byte array */); // just `array`
    }
}

Explanation

This registers a custom HttpServlet for the given path (/images/* this path can be changed to what you want). The servlet gets called when the client loads the image via a GET request.

Then you can get the image code from the requested path (request.getPathInfo().substring(1) gets the file path and removes the first slash).

Then you have to get the mime type of the image. This is possible by two ways:

  • get the basic file extension (jpg, png, etc.) and get the mime type for the file type from web.xml (mime-type elements)
  • directly get the mime type

Then you must have the byte array that represents the content of the image. Set the response size with contentLength.

Then finally write the byte array to the response.


Usage

The good thing is you can use it everwhere (css, js, plain html, etc.).

Just specify the /images/*code* and the image gets loaded.


See Also

Omnifaces GraphicImageBean (similar to this solution)

Upvotes: 2

Related Questions