Piranha micro で Hello World


はじめに

前回は、Piranha Embedded を使った Hello World であった。

blog1.mammb.com

今回は、Piranha micro を使った Hello World。

Piranha micro は、単一のWebアプリケーション(warファイル)をそのまま実行できる。 Piranha Embedded と異なり、HTTPサーバを含み、分離されたクラスローダを介したWebアプリケーションを実行できる。

デフォルトでは、以下の最低限の機能を提供する(extension として各種コンポーネントを追加することができる)。

  • Jakarta Servlet(JSP, EL式含む)
  • Jakarta Security(Jakarta Authentication, Jakarta Authorization 含む)

具体的には以下の extension が登録される。

public class StandardExtension implements WebApplicationExtension {

    @Override
    public void extend(WebApplicationExtensionContext context) {
        context.add(AsyncExtension.class);                          // Async
        context.add(LocaleEncodingExtension.class);                 // locale-encoding
        context.add(LoggingExtension.class);                        // ServletContext.log
        context.add(MimeTypeExtension.class);                       // mime-type
        context.add(PolicyExtension.class);                         // JavaPolicy
        context.add(TempDirExtension.class);                        // TEMPDIR
        context.add(WelcomeFileExtension.class);                    // welcome-file
        context.add(ServletSecurityManagerExtension.class);         // SecurityManager
        context.add(ApacheMultiPartExtension.class);                // Servlet Part API support
        context.add(WaspJspManagerExtension.class);                 // addJspFile
        context.add(HerringExtension.class);                        // JNDI
        context.add(AnnotationScanExtension.class);                 // Annotation scanning
        context.add(WebXmlExtension.class);                         // web.xml
        context.add(ServletAnnotationsExtension.class);             // Servlet annotations
        context.add(WaspExtension.class);                           // WaSP
        context.add(ServletContainerInitializerExtension.class);    // ServletContainerInitializer
        context.add(ServletSecurityExtension.class);                // Security implementation
    }
}


コマンドライン実行

現在の piranha-micro のヘルプは以下。

$ java -jar piranha-micro-22.8.0.jar --help

  --extension-class <className>    - Set the extension to use
  --help                           - Show this help
  --http-port <integer>            - Set the HTTP port (use -1 to disable)
  --https-port <integer>           - Set the HTTPS port (disabled by default)
  --jpms                           - Enable Java Platform Module System
  --ssl-keystore-file <file>       - Set the SSL keystore file (applies to the
                                     whole JVM)
  --ssl-keystore-password <string> - Set the SSL keystore password (applies to
                                     the whole JVM
  --verbose                        - Shows the runtime parameters
  --war-file <file>                - The WAR file to deploy
  --webapp-dir <directory>         - The directory to use for the web
                                     application (auto creates when it does not
                                     exist, if omitted runtime will use the
                                     filename portion of --war-file)
  --write-pid                      - Write out a PID file

ということで、以下のように war を実行できる。

$ java -jar piranha-micro-22.8.0.jar --war-file app.war

はずだが、現時点の piranha-micro は動かない


HelloServlet.java

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

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

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

        response.setContentType("text/html; charset=UTF-8");
        response.setContentType("text/html");
        try (PrintWriter out = response.getWriter()) {
            out.println("""
            <!DOCTYPE html>
            <html>
                <head>
                    <title>Hello World!</title>
                </head>
                <body>
                    <h1>Hello World!</h1>
                </body>
            </html>
            """);
        }
    }
}


build.gradle.kts

JavaExec タスクを作成。

plugins {
    war
}

repositories {
    mavenCentral()
}

tasks.withType<JavaCompile> {
    options.encoding = Charsets.UTF_8.name()
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

dependencies {
    compileOnly("jakarta.platform:jakarta.jakartaee-api:9.1.0")
    runtimeOnly("cloud.piranha:piranha-micro:22.8.0")
    runtimeOnly("org.osgi:org.osgi.core:6.0.0")
}

tasks.register<JavaExec>("run") {
    dependsOn(tasks.build)
    classpath = sourceSets.main.get().runtimeClasspath
    mainClass.set("cloud.piranha.micro.MicroPiranhaMain")
    args = listOf(
        "--war-file", layout.projectDirectory.file("build/libs/app.war").toString(),
        "--verbose")
}

org.osgi.core の依存が必要。


実行

$ ./gradlew clean run


PIRANHA MICRO

Arguments
=========

Extension class       : cloud.piranha.extension.standard.StandardExtension
Exit on stop          : true
HTTP port             : 8080
HTTPS port            : -1
JPMS enabled          : false
PID                   : null
SSL keystore file     : null
SSK keystore password : ****
WAR filename          : /.../build/libs/app.war
Web application dir   : null

cloud.piranha.micro.MicroPiranha run
info: Started Piranha
cloud.piranha.micro.MicroPiranha run
info: It took 894 milliseconds

http://localhost:8080/app/helloServlet で以下となる。


MicroPiranhaBuilder からの実行

Application プラグインなどからMicroPiranhaBuilder を使ってwarを実行することもできる。

plugins {
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("cloud.piranha:piranha-micro:22.8.0")
}

application {
    mainClass.set("piranha.example.micro.App")
}
public class App {
    public static void main(String[] args) {
        MicroPiranha piranha = new MicroPiranhaBuilder()
                .extensionClass(StandardExtension.class)
                .warFile("../war/build/libs/app.war")
                .httpPort(8080)
                .verbose(true)
                .build();
        piranha.start();
   }
}