Running a Web Application as an Azure Function

In our previous blog entry we demonstrated you can run a JSP as an Azure function. Can we go even further and run a Web Application as an Azure Function? Yes, we can!

Below is the quick recipe to get this to work!

The code below is the 'Hello World' Servlet


public class HelloWorldServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        PrintWriter writer = response.getWriter();
        writer.println("Hello World");
        writer.flush();
    }
}
        

The code below is the Azure Function dispatching to the Web Application

            
public class WebappFunction {

    /**
     * Stores the single instance of Piranha Embedded.
     */
    private static EmbeddedPiranha EMBEDDED_PIRANHA;

    /**
     * Run the function.
     *
     * @param request the request.
     * @param path the path.
     * @param context the execution context.
     * @return the response.
     */
    @FunctionName("webapp")
    public HttpResponseMessage run(
            @HttpTrigger(
                    name = "request",
                    methods = {HttpMethod.GET, HttpMethod.POST},
                    route = "{path}",
                    authLevel = AuthorizationLevel.ANONYMOUS
            ) HttpRequestMessage<Optional<String>> request,
            @BindingName("path") String path,
            final ExecutionContext context) {

        /**
         * Build the Embedded request.
         */
        EmbeddedRequest embeddedRequest = new EmbeddedRequestBuilder()
                .method(request.getHttpMethod().name())
                .servletPath(path.equals("") ? "" : "/" + path)
                .build();

        /**
         * Build the Embedded response.
         */
        EmbeddedResponse embeddedResponse = new EmbeddedResponseBuilder()
                .build();

        /**
         * Build up the Piranha Embedded runtime and dispatch the request and
         * response to it and then capture the response.
         */
        String body = null;

        try {
            if (EMBEDDED_PIRANHA == null) {
                EMBEDDED_PIRANHA = new EmbeddedPiranha();
                WebApplication webApplication = EMBEDDED_PIRANHA.getWebApplication();
                webApplication.setClassLoader(
                    new DefaultWebApplicationClassLoader(new File("webapp")));
                webApplication.addResource(new DefaultDirectoryResource("webapp"));
                webApplication.addInitializer(WebXmlInitializer.class.getName());
                webApplication.addServlet("DefaultServlet", DefaultServlet.class.getName());
                webApplication.addServletMapping("DefaultServlet", "/*");
                webApplication.initialize();
                webApplication.start();
            }
            EMBEDDED_PIRANHA.service(embeddedRequest, embeddedResponse);
        } catch (IOException | ServletException e) {
            body = e.getMessage();
        }

        if (body == null) {
            body = embeddedResponse.getResponseAsString();
        }

        /**
         * Return the function response.
         */
        return request.createResponseBuilder(HttpStatus.OK).
                header("Content-Type", "text/html").
                body(body).
                build();
    }
}
        

As you can see this was all very easy to accomplish thanks to Piranha Embedded. Go over to the Piranha Cloud project to see more. If there is interest in a proper extension please file an issue there.

A zip file that contains everything you need is available here

Posted February 16th, 2020

Up