Documentation

Documentation versions (currently viewingVaadin 23)
New Acceleration Kits: Observability Kit, SSO Kit, and Swing Kit. Read the blog post.

Dynamic Content

Generating content dynamically based on the application state.

To generate content dynamically based on data provided by the current application state, there are two options:

  • You can use a StreamResource, which handles URLs automatically.

  • You can build a custom URL using String type parameters. In this case, you need one more servlet, which handles the URL.

The first option is preferable, since it doesn’t require an additional servlet and allows you to use data of any type from the application state.

Using Custom Servlet and Request Parameters

You can create a custom servlet which handles "image" as a relative URL:

@WebServlet(urlPatterns = "/image", name = "DynamicContentServlet")
public class DynamicContentServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("image/svg+xml");
        String name = req.getParameter("name");
        if (name == null) {
            name = "";
        }
        String svg = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
                + "<svg xmlns='http://www.w3.org/2000/svg' "
                + "xmlns:xlink='http://www.w3.org/1999/xlink'>"
                + "<rect x='10' y='10' height='100' width='100' "
                + "style=' fill: #90C3D4'/><text x='30' y='30' fill='red'>"
                + name + "</text>" + "</svg>";
        resp.getWriter().write(svg);
    }
}

The following code should be used in the application (which has its own servlet). It generates the resource URL on the fly, based on the current application state. The property value of the input component is used here as a state:

Input name = new Input();

Element image = new Element("object");
image.setAttribute("type", "image/svg+xml");
image.getStyle().set("display", "block");

NativeButton button = new NativeButton("Generate Image");
button.addClickListener(event -> {
    String url = "image?name=" + name.getValue();
    image.setAttribute("data", url);
});

UI.getCurrent().getElement().appendChild(name.getElement(), image,
    button.getElement());

Using StreamResource

Use StreamResource to generate dynamic content within the same servlet. In this case, the application generates the URL transparently for you and registers an internal handler for this URL. The code below shows how to implement the same functionality as above, using StreamResource.

Input name = new Input();

Element image = new Element("object");
image.setAttribute("type", "image/svg+xml");
image.getStyle().set("display", "block");

NativeButton button = new NativeButton("Generate Image");
button.addClickListener(event -> {
    StreamResource resource = new StreamResource("image.svg",
            () -> getImageInputStream(name));
    image.setAttribute("data", resource);
});

UI.getCurrent().getElement().appendChild(name.getElement(), image,
    button.getElement());

The data attribute value is set to the StreamResource, which is automatically converted into a URL. A StreamResource uses a dynamic data provider to produce the data. The file name given to a StreamResource is used as a part of the URL and also becomes the filename, if the user chooses to download the resource. And here is an example of how to create a data provider:

private InputStream getImageInputStream(Input name) {
    String value = name.getValue();
    if (value == null) {
        value = "";
    }
    String svg = "<?xml version='1.0' encoding='UTF-8' standalone='no'?>"
        + "<svg xmlns='http://www.w3.org/2000/svg' "
        + "xmlns:xlink='http://www.w3.org/1999/xlink'>"
        + "<rect x='10' y='10' height='100' width='100' "
        + "style=' fill: #90C3D4'/><text x='30' y='30' fill='red'>"
        + value + "</text>" + "</svg>";
    return new ByteArrayInputStream(svg.getBytes(StandardCharsets.UTF_8));
}

DF78C6F1-4DFC-4F65-A0D4-29CCB2CFEDD5