Coder Social home page Coder Social logo

bootique-jetty's Introduction

build test deploy Maven Central

Bootique is a minimally opinionated java launcher and integration technology. It is intended for building container-less runnable Java applications. With Bootique you can create REST services, webapps, jobs, DB migration tasks, etc. and run them as if they were simple commands. No JavaEE container required! Among other things Bootique is an ideal platform for Java microservices, as it allows you to create a fully-functional app with minimal setup.

Each Bootique app is a collection of modules interacting with each other via dependency injection. This GitHub project provides Bootique core. Bootique team also develops a number of important modules. A full list is available here.

Quick Links

Support

You have two options:

  • Open an issue on GitHub with a label of "help wanted" or "question" (or "bug" if you think you found a bug).
  • Post a question on the Bootique forum.

TL;DR

For the impatient, here is how to get started with Bootique:

  • Declare the official module collection:
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.bootique.bom</groupId>
            <artifactId>bootique-bom</artifactId>
            <version>3.0-M4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency> 
    </dependencies>
</dependencyManagement>
  • Include the modules that you need:
<dependencies>
    <dependency>
        <groupId>io.bootique.jersey</groupId>
        <artifactId>bootique-jersey</artifactId>
    </dependency>
    <dependency>
        <groupId>io.bootique.logback</groupId>
        <artifactId>bootique-logback</artifactId>
    </dependency>
</dependencies>
  • Write your app:
package com.foo;

import io.bootique.Bootique;

public class Application {
    public static void main(String[] args) {
        Bootique
            .app(args)
            .autoLoadModules()
            .exec()
            .exit();
    }
}

It has main() method, so you can run it!

For a more detailed tutorial proceed to this link.

Upgrading

See the "maven-central" badge above for the current production version of bootique-bom. When upgrading, don't forget to check upgrade notes specific to your version.

bootique-jetty's People

Contributors

aarrsseni avatar andrus avatar aperaverzeu avatar const1993 avatar elena-bondareva avatar irus avatar komzpa avatar kravchenkoas avatar lukaszbachman avatar pavelnikanovich avatar shad862 avatar stariy95 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bootique-jetty's Issues

Support for mapping thread pools to connectors

Now that multiple connectors are supported, we should allow explicit mapping of thread pools and assignment of those to connectors. E.g. it is useful to attach a separate small thread pool to admin connector to inspect the app state when the main thread pool is deadlocked, etc.

Support for request metrics

Integrate bootique-metrics. Let's organize jetty source tree as 2 submodules - the main one bootique-jetty with no instrumentation, and bootique-jetty-instrumented that overrides the main one with metrics code. This way the users won't be forced to import metrics under all circumstances.

Support for multiple connectors

Jetty should be able to start more than one connector. I guess we deprecate "jetty.connector" config property in favor of "jetty.connectors" array and start as many connectors as the user wants.

A test module to write Bootique apps with jetty for unit tests

I'd like to have a Bootique app embeddable in unit tests that includes a web server, and can be easily customized and started on background. I already wrote a few of those across the modules. Would be nice to have a centralized version. So will create a new module here called "bootique-jetty-test" that will provide such an app for Bootique or user apps to test with Jersey,

Support for context init parameters

While we already support init parameters for servlets and filters, let's also add support for ServletContext params:

jetty:
  params:
      a: b
      c: d

Simplify MappedServlet/MappedFilter with parameterization

Currently to bind an injectable MappedServlet/MappedFilter, we require a custom annotation to distinguish one mapped object from another:

@Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @BindingAnnotation
    public @interface MetricsMappedServlet {}

@MetricsMappedServlet
@Provides
MappedServlet mappedMetricsServlet(MetricRegistry registry) {
    MetricsServlet servlet = new MetricsServlet(registry);
    return new MappedServlet(servlet, Collections.singleton("/metrics"), "metrics");
}

public void configure(Binder binder) {
    JettyModule
        .contributeMappedServlets(binder)
        .addBinding()
        .to(Key.get(MappedServlet.class, MetricsMappedServlet.class));
}

This works, but is quite annoying. Instead we may turn MappedServlet/MappedFilter into objects parameterized by the servlet/filter type, and use TypeLiteral to do the binding.

add default Bootique favicon.ico

When the app defines no favicon, we should probably serve one with Bootique logo. This sounds "opinionated", but modules are opinionated. Also simply placing favicon.ico in a webapp docroot should result in a custom one served.

Support for servlet spec annotations

If we can start supporting servlet and filter annotations, we can cut down on servlet registration bolierplate and allow for contributing servlets and filters directly without the need to manually wrap them in MappedServlet/MappedFilter:

Multibinder<Servlet> mb = JettyModule.contributeServlets(Binder b);
Multibinder<MappedServlet> mb = JettyModule.contributeMappedServlets(Binder b);

Multibinder<Filter> mb = JettyModule.contributeFilters(Binder b);
Multibinder<MappedFilter> mb = JettyModule.contributeMappedFilters(Binder b);

ServerCommand: Jetty daemon interruption should be reported as successful completion

Noticed this in the JettyTestFactory after we implemented this issue in Bootique, and started seeing command execution statuses.

stopping Jetty...
[pool-2-thread-1] INFO org.eclipse.jetty.server.ServerConnector - Stopped ServerConnector@4969f352{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[pool-2-thread-1] INFO org.eclipse.jetty.server.handler.ContextHandler - Stopped o.e.j.s.ServletContextHandler@7794b655{/,null,UNAVAILABLE}
Error executing runtime
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Thread.join(Thread.java:1245)
    at java.lang.Thread.join(Thread.java:1319)
    at com.nhl.bootique.jetty.command.ServerCommand.run(ServerCommand.java:43)
    at com.nhl.bootique.run.DefaultRunner.run(DefaultRunner.java:20)
    at com.nhl.bootique.test.BQTestRuntime.run(BQTestRuntime.java:62)
    at com.nhl.bootique.test.BQDaemonTestRuntime.lambda$start$0(BQDaemonTestRuntime.java:48)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

I guess we should either support Jetty shutdown via a port or return success when Jetty is stopped via "runtime.shutdown()" call. After all this is an orderly shutdown event.

Support for static resources

This task turns Jetty into a webserver that can serve static files from the filesystem or from the app jar. Static resources can be coming either from classpath, external url or filesystem. Supported configuration:

jetty:
  # If true, Jetty will install a "default" servlet that serves static resources.
  # this is "false" by default
  staticResources: true

  # sets a base location for resources of the Jetty context.
  # can be a path, a URL or a special "classpath:/" URL. 
  # it can be reused or overridden by DefaultServlet configuration below.
  # for security reasons this has to be set explicitly. There's no default.
  staticResourceBase: <path_or_url>

If "staticResources" is true, Bootique would add Jetty DefaultServlet to the web server. It supports a bunch of other parameters that can be passed as this:

jetty:
  servlets:
    default:
      params:
        resourceBase: a/b/c
        ....

Suppress Jetty INFO loggers by default

Bootique-jetty prints enough information about Jetty startup, so let's suppress logging by Jetty classes at the INFO level by default (can of course be turned back on by the user).

Support for gzip compression

Would be nice to have gzip compression enabled by default for all responses in a container. This can be built using Jetty Gzip Handler which seems to do all the content negotiation as well actual (de)compression.

New API for contributing Servlets

Using servlet path as a key in a DI map was a hack. Need to get rid of it, replacing with a more reliable mechanism. Will introduce a new class MappedServlet and a new JettyBinder to bind it:

// binding a MappedServlet present in DI, annotated with a given annotation:
JettyBinder.contributeTo(binder).servlet(MyAnnotation.class);

// binding explicitly
JettyBinder.contributeTo(binder).servlet(myServlet, "/*");

Configurable request and response header size

Currently max size of request and response headers (the former also affects max size of GET URL) is currently hardcoded in HttpConnectorFactory to be 8K. Would be nice to be able to change that via YAML, as certain services can take lots of URL parameters.

Print full base URL on startup

Jetty startup output looks like this:

o.e.j.s.h.ContextHandler - Started o.e.j.s.ServletContextHandler@69ad94cc{/mycontext,null,AVAILABLE}
o.e.j.s.ServerConnector - Started ServerConnector@7158437e{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}

It is not easy to figure out the base URL of the app. So let's actually make the ServerCommand print more user-friendly information. E.g.:

c.n.b.j.c.ServerCommand - Started Jetty in 1024 ms. Base URL: http://172.22.8.136:8080/mycontext

Support for binding YAML parameters to servlets and filters as init parameters

Per #12 developers can supply init parameters to servlets and filters by passing them to the MappedServlet and MappedFilter. This is not very convenient. Would be cool to connect this to YAML. E.g.:

jetty:
   servlets:
      s1:
        params:
           a: b
           c: d
   filters:
      f1:
        params:
          f: g

This will still require explicitly naming servlets and filters, which will hopefully be easy to achieve after #16 is available.

more flexible mapping of static folders

Sometimes we want '/' to be handled by a dynamic resource (e.g. REST endpoint), and then to designate certain subfolders to be served as static resources. Current version of mapping a default servlet is insufficient for this purpose. Instead we are going to do the following:

  • Remove support for staticResources property in YAML
  • Add explicit API for registering either a "standard" default servlet, or a default servlet working off of subdirs:
JettyModule.contributeDefaultServlet(binder);
JettyModule.contributeStaticServlet(binder, "static", "/f1/*", "/f2/*");

Upgrade Notes:

This is a breaking change. If you used 'staticResources' , you will need to remove this key from YAML and instead call one of the "contribute*" methods above explicitly.

Timing async requests

Current TimingFilter (implemented per #28) under-report response times for async servlets. Need to deal with async requests somehow.

Creating customer ServerFactory class

So I've created a custom ServerFactory class that overrides "createHandler" to provide a ServletContextHandler that has SESSIONS as the options. So then I bound it like:

binder.bind(ServerFactory.class).to(SHServerFactory.class);

in a module that precedes loading the JettyModule. But I get an exception:

Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:

1) A binding to com.nhl.bootique.jetty.server.ServerFactory was already configured at com.smarthealth.shmisc.wicket.SHWebApplication$1.configure(SHWebApplication.java:52).
  at com.nhl.bootique.jetty.JettyModule.createServerFactory(JettyModule.java:132)

1 error
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466)
    at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
    at com.google.inject.Guice.createInjector(Guice.java:96)
    at com.google.inject.Guice.createInjector(Guice.java:73)
    at com.nhl.bootique.Bootique.createInjector(Bootique.java:340)
    at com.nhl.bootique.Bootique.runtime(Bootique.java:264)
    at com.nhl.bootique.Bootique.run(Bootique.java:280)
    at com.smarthealth.shmisc.wicket.SHWebApplication.main(SHWebApplication.java:56)
    at com.smarthealth.WicketApplication.main(WicketApplication.java:23)

I'm not sure how to get past this.

JettyTestFactory - incorrect startup time reporting

A minor issue... When starting multiple jetty instances in the tests (but potentially outside tests as well), the logs report ever increasing start time (as if it takes much longer to start every new instance compared to the previous instance). E.g.:

[pool-26-thread-1] INFO org.eclipse.jetty.server.Server - jetty-9.3.6.v20151106
[pool-26-thread-1] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@577d78ad{/,null,AVAILABLE}
[pool-26-thread-1] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@29b0910b{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[pool-26-thread-1] INFO org.eclipse.jetty.server.Server - Started @7530ms
...
[pool-28-thread-1] INFO org.eclipse.jetty.server.Server - jetty-9.3.6.v20151106
[pool-28-thread-1] INFO org.eclipse.jetty.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@7265759d{/,null,AVAILABLE}
[pool-28-thread-1] INFO org.eclipse.jetty.server.ServerConnector - Started ServerConnector@556d2b3{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
[pool-28-thread-1] INFO org.eclipse.jetty.server.Server - Started @8077ms

This is because Jetty "uptime" timer is static and counts startup time since the first startup. Will need to our own resettable timer, one per server. See org.eclipse.jetty.util.Uptime for details. (the default timer goes to java.lang.management.RuntimeMXBean which is not appropriate for tests ... and perhaps outside tests as well).

ServerFactory - add getters

ServerFactory is already injectable, and sometimes it may be helpful to inspect its contents in the app code. Let's add public getters for all of its properties (for now excluding filters and servlets).

change 'staticResourceBase' type of FolderResourceFactory

Currently 'staticResourceBase' is a ResourceFactory. So producing sub-URLs from it requires a manual check for trailing slash. Let's change that to FolderResourceFactory so that a valid usable URL value is returned regardless of how it was configured by the user (whether config included trailing slash or not)

Upgrade Bootique to 0.12

0.12 version of Bootique includes a completely redone command API. Need to upgrade Job commands to that new API.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.