Skip to main content

Customizing via @Bean

As of 10.0, JettyMicroservice was reshaped — the legacy subclass form was retired, and a thin static-call facade was introduced to collapse the standard Microservice + JettyConfiguration bootstrap. See juneau-microservice-jetty for the new entry point.

juneau-microservice-jetty contributes a single JettyConfiguration class that wires Jetty into the standard Microservice. Customization is therefore done by contributing your own @Bean definitions rather than subclassing.

Hooking into the lifecycle​

Implement MicroserviceListener and expose it as a @Bean — every MicroserviceListener bean in the store is invoked on start() / stop() / config-change events (start in registration order, stop in reverse order).

@Configuration
public class MyApp {

@Bean
Servlet rootResources() { return new RootResources(); }

@Bean(name = "lifecycle")
MicroserviceListener lifecycle() {
return new BasicMicroserviceListener() {
@Override
public void onStart(Microservice ms) {
// custom start-up logic, e.g. warming caches, registering JMX beans, etc.
}
@Override
public void onStop(Microservice ms) {
// custom shutdown logic
}
};
}
}

public class App {
public static void main(String[] args) throws Exception {
Microservice
.create()
.args(args)
.configurations(JettyConfiguration.class, MyApp.class)
.build()
.start()
.startConsole()
.join();
}
}

Overriding Jetty defaults​

The relevant Jetty hooks are all keyed by bean type in the store; user-supplied @Beans win over the defaults that JettyConfiguration contributes.

OverrideReplace by contributing
Jetty server itself@Bean Server (skips jetty.xml entirely if its "ServletContextHandler" attribute is set).
Server factory@Bean JettyServerFactory — used when no @Bean Server is supplied.
Ports / jetty.xml content / var resolution@Bean JettySettings (use JettySettings.create().ports(...).jettyXml(...).build()).
Servlet auto-mounts@Bean Servlets annotated with @Rest — mounted at @Rest(path = "...").

Registering servlet filters​

Contribute a ServletFilterRegistration bean to mount a jakarta.servlet.Filter before the server starts. The same type works on Jetty and on Tomcat.

@Bean(name="consoleBoundary")
ServletFilterRegistration consoleBoundary() {
return ServletFilterRegistration.create(new PetstoreConsoleBoundary())
.urlPatterns("/console/*")
.dispatcherTypes(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC, DispatcherType.ERROR)
.order(ServletFilterRegistration.HIGHEST_PRECEDENCE)
.build();
}
  • URL patterns follow the Servlet specification: a prefix (/api/*), an extension (*.json), an exact path, or "" for the context root. At least one is required, and a malformed pattern is rejected when the registration is built.
  • Dispatcher types default to REQUEST only. dispatcherTypes(...) replaces the default, so list REQUEST explicitly when you want it.
  • Order. Lower order values run first. Filters with the same order run by bean name, so give each registration its own @Bean(name=...). @Order on the bean method does not affect filter order. The default is 0, which runs after the auto-mounted AuthFilterChain at ServletFilterRegistration.AUTH_ORDER (-100). A filter that must reject a request before authentication, such as a CSRF boundary, uses HIGHEST_PRECEDENCE and a narrow pattern; on /* it would also intercept authentication redirects and challenges.
  • AuthFilterChain. A bean of that type is mounted automatically. To change its dispatchers or order, register the injected bean instance in your own ServletFilterRegistration; that registration replaces the automatic one.
  • Validation. The same filter instance cannot be registered twice, and explicit name(...) values must be unique.

The addFilter(Filter, String...) overloads on the server component are unchanged and still map REQUEST only.

Accessing the Jetty server at runtime​

JettyServerComponent jetty = Microservice
.getInstance()
.getBeanStore()
.getBean(JettyServerComponent.class)
.orElseThrow();

URI uri = jetty.getURI();
int port = jetty.getPort();
Server server = jetty.getServer();