001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.microservice.tomcat;
018
019import org.apache.juneau.commons.inject.*;
020import org.apache.juneau.microservice.*;
021
022import jakarta.servlet.*;
023
024/**
025 * Zero-config convenience launcher for an embedded-Tomcat-backed Juneau microservice.
026 *
027 * <p>
028 * Wraps the {@link Microservice} + {@link TomcatConfiguration} bootstrap in a single static call so
029 * a consumer can stand up a Tomcat microservice with one Maven dependency and one line of code:
030 *
031 * <p class='bjava'>
032 *    <jc>// Boot Tomcat + Juneau on the default port (8000) with the interactive console enabled.</jc>
033 *    <jk>public static void</jk> main(String[] args) <jk>throws</jk> Exception {
034 *       TomcatMicroservice.<jsm>run</jsm>(args, <jk>new</jk> RootResources());
035 *    }
036 * </p>
037 *
038 * <p>
039 * Bundled defaults (all overridable):
040 * <ul>
041 *    <li>Port <c>8000</c> (surfaced as <c>Tomcat/port</c> in a consumer-supplied <c>juneau.cfg</c>).
042 *    <li>Interactive console enabled (use {@link #run(String[], Servlet, boolean)} with
043 *       {@code startConsole=false} to suppress).
044 *    <li>An auto-created, auto-deleted temp Catalina base directory &mdash; a consumer-supplied
045 *       {@code @Bean TomcatSettings} with {@link TomcatSettings.Builder#baseDir(String)} wins via the
046 *       existing {@link TomcatServerComponent} resolution chain.
047 * </ul>
048 *
049 * <p>
050 * The supplied root servlet is registered as a {@code @Bean Servlet} in an external bean store and
051 * auto-mounted by {@link TomcatServerComponent TomcatServerComponent}
052 * at the path declared by its {@link org.apache.juneau.rest.server.Rest @Rest} annotation.  Consumers
053 * who want full control over the bean store / configuration classes / listener wiring should call
054 * {@link Microservice#create()} directly &mdash; this facade is a thin convenience over that builder.
055 *
056 * @since 10.0.0
057 */
058@SuppressWarnings({
059   "java:S112", // throws Exception intentional - mirrors Microservice.start() lifecycle contract.
060   "resource" // beanStore lifetime is managed by the returned Microservice; not an independent resource.
061})
062public final class TomcatMicroservice {
063
064   private TomcatMicroservice() {}
065
066   /**
067    * Boots a Tomcat microservice with the supplied root servlet and the bundled defaults,
068    * with the interactive console enabled.
069    *
070    * <p>
071    * Equivalent to calling {@link #run(String[], Servlet, boolean) run(args, rootServlet, true)}.
072    *
073    * @param args         The {@code main(String[])} arguments.  Forwarded to {@link org.apache.juneau.microservice.Microservice.Builder#args(String...) Microservice.Builder#args(String...)}.
074    * @param rootServlet  The root REST servlet (typically annotated with
075    *                     {@link org.apache.juneau.rest.server.Rest @Rest}).
076    * @return The started {@link Microservice} instance.  Callers typically chain {@link Microservice#join()}.
077    * @throws Exception Error occurred during bootstrap.
078    */
079   public static Microservice run(String[] args, Servlet rootServlet) throws Exception {
080      return run(args, rootServlet, true);
081   }
082
083   /**
084    * Boots a Tomcat microservice with the supplied root servlet and the bundled defaults.
085    *
086    * <p>
087    * Constructs the {@link Microservice}, registers the supplied servlet as a {@code @Bean Servlet} so
088    * {@link TomcatServerComponent TomcatServerComponent} auto-mounts
089    * it, applies {@link TomcatConfiguration} so embedded Tomcat itself is wired, and starts the lifecycle.  The
090    * returned microservice has not yet been {@link Microservice#join() joined}; callers wanting the
091    * standard "start and block forever" loop should chain {@code .join()}.
092    *
093    * @param args          The {@code main(String[])} arguments.  Forwarded to {@link org.apache.juneau.microservice.Microservice.Builder#args(String...) Microservice.Builder#args(String...)}.
094    * @param rootServlet   The root REST servlet (typically annotated with
095    *                      {@link org.apache.juneau.rest.server.Rest @Rest}).
096    * @param startConsole  If <jk>true</jk>, also starts the interactive console thread via
097    *                      {@link Microservice#startConsole()}.
098    * @return The started {@link Microservice} instance.
099    * @throws Exception Error occurred during bootstrap.
100    */
101   public static Microservice run(String[] args, Servlet rootServlet, boolean startConsole) throws Exception {
102      var beanStore = new BasicBeanStore();
103      beanStore.addBean(Servlet.class, rootServlet);
104      return run(args, beanStore, startConsole, TomcatConfiguration.class);
105   }
106
107   /**
108    * Power-user form: boots a Tomcat microservice with a caller-supplied bean store and configuration
109    * class list.
110    *
111    * <p>
112    * Equivalent to writing the {@link Microservice} builder chain by hand, but with the boilerplate
113    * collapsed.  Use this when the simpler {@link #run(String[], Servlet)} overloads are too
114    * restrictive &mdash; e.g. multiple {@code @Bean Servlet} contributions, custom
115    * {@code MicroserviceListener}s, or a parent bean store.
116    *
117    * @param args            The {@code main(String[])} arguments.  Forwarded to {@link org.apache.juneau.microservice.Microservice.Builder#args(String...) Microservice.Builder#args(String...)}.
118    * @param beanStore       The bean store to use for dependency injection.  Pre-populated bean entries
119    *                        ({@code @Bean Servlet}, {@code MicroserviceListener}, etc.) are picked up by
120    *                        {@link TomcatConfiguration} and the microservice runtime.
121    * @param startConsole    If <jk>true</jk>, also starts the interactive console thread.
122    * @param configurations  The {@code @Configuration}-annotated classes to register.  Always includes
123    *                        {@link TomcatConfiguration}; pass an empty list to use only that.
124    * @return The started {@link Microservice} instance.
125    * @throws Exception Error occurred during bootstrap.
126    */
127   public static Microservice run(String[] args, WritableBeanStore beanStore, boolean startConsole, Class<?>... configurations) throws Exception {
128      var ms = Microservice
129         .create()
130         .args(args)
131         .beanStore(beanStore)
132         .configurations(configurations)
133         .build()
134         .start();
135      if (startConsole)
136         ms.startConsole();
137      return ms;
138   }
139}