Embedded servlet containers abstraction
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Paweł Płazieński 52ba9f4248 Bump version to snapshot 2.0.1 7 months ago
webable-api Bump version to snapshot 2.0.1 7 months ago
webable-handler Bump version to snapshot 2.0.1 7 months ago
webable-jetty Bump version to snapshot 2.0.1 7 months ago
webable-tomcat Bump version to snapshot 2.0.1 7 months ago
webable-undertow Bump version to snapshot 2.0.1 7 months ago
.gitignore Add gitignore 3 years ago
LICENSE.md Add license 3 years ago
README.md Add readme 2 years ago
pom.xml Bump version to snapshot 2.0.1 7 months ago

README.md

Webable

Abstraction over embedding servlet containers.

Introduction

Webable offers easy programmatic creation of embedded servlet containers, such as Tomcat or Jetty, with unified, builder-like API.

Webable also offers optional “handler” configuration, which is its own API on top of servlets/filters, which allows easier and more functional approach to HTTP request handling.

Supported containers:

Including as dependency

Add dependencies in your pom.xml:

<dependency>
    <groupId>org.perfectable</groupId>
    <artifactId>webable-api</artifactId>
    <version>${webable.version}</version>
</dependency>
<dependency>
    <groupId>org.perfectable</groupId>
    <artifactId>webable-tomcat</artifactId>
    <version>${webable.version}</version>
    <scope>runtime</scope>
</dependency>

Replace webable-tomcat with webable-jetty or webable-undertow if you need other container.

Note: you need to have actual container library in runtime scope only.

If you want to use functional request handlers, add also:

<dependency>
    <groupId>org.perfectable</groupId>
    <artifactId>webable-handler</artifactId>
    <version>${webable.version}</version>
</dependency>

Use example

Plain servlet-based webapplication:

WebApplication.begin()
    .withPort(8000)
    .withContextParameter("applicationUrl", "http://example.org/")
    .withForcedSessionCreation()
    .withHttpSessionListener(InjectContextListener.INSTANCE)
    .withWebsocketEndpoint(ServerEndpointConfig.Builder.create(WebsocketEndpoint.class, "/ws").build())
    .withFilter(BasicAuthenticationFilter.create(userNameResolver))
        .named("basicAuth")
        .mappedTo("/*")
        .endFilter()
    .withServlet(EntryServlet.class)
        .initialParameter("performer", userName)
        .mappedTo("/")
        .loadedInitially()
        .endServlet()
    .serveBlocking();

Functional request-handlers:

ResourceResolver scriptsResolver = path ->
    StreamResourceLoader.classpathFromPath(path).as(MediaType.JAVASCRIPT_UTF_8);
RequestHandler rootHandler = request -> HttpResponse.status(HttpStatus.FOUND)
        .withHeader("Location", "/").withPlainTextContent("Hello " + request.completePath())
WebApplication.begin()
    .withPort("10.0.0.1", 80)
    .extend(HandlerServerConfigurationExtension.INSTANCE.adjustType())
    .withGlobalChannel(BasicAuthenticationRequestChannel.of(authenticator))
    .withResources("/scripts/*", scriptsResolver)
    .withResponse("", HttpResponse.OK.withResourceContent(MediaType.XHTML_UTF_8, "index.html"))
    .withRootHandler(rootHandler)
    .serveBlocking();