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.petstore.jetty;
018
019import org.apache.juneau.commons.inject.*;
020import org.apache.juneau.http.response.*;
021import org.apache.juneau.marshall.html.*;
022import org.apache.juneau.marshall.serializer.*;
023import org.apache.juneau.microservice.examples.*;
024import org.apache.juneau.petstore.console.*;
025import org.apache.juneau.petstore.console.data.*;
026import org.apache.juneau.petstore.rest.*;
027import org.apache.juneau.petstore.service.*;
028import org.apache.juneau.rest.server.*;
029import org.apache.juneau.rest.server.servlet.*;
030import org.apache.juneau.rest.server.widget.*;
031
032/**
033 * Root router resource for the Jetty deployment.
034 *
035 * <p>
036 * Mounts the deployment-agnostic {@link PetStoreResource} and {@link PetstoreConsoleResource} (the admin console at
037 * {@code /console}) from {@code juneau-petstore-core}, and the Jetty/Microservice-specific admin resources ({@link ConfigResource}, {@link LogsResource},
038 * {@link ShutdownResource}).  The admin trio is a documented Jetty-only non-parity feature — the Spring Boot
039 * deployment in {@code juneau-petstore-springboot} does not mount it.  {@link App.AppConfig#adminBoundary()} puts the
040 * trio behind its own CSRF boundary.
041 *
042 * <p>
043 * Also showcases the Config API + SVL variable resolver: the root page's header is driven by
044 * {@code $C{Petstore/appName}}, which resolves against the {@code [Petstore]} section of
045 * {@code juneau-petstore-jetty.cfg} (the same {@code $C{...}} pattern already used by the {@code source} navlink
046 * below, which resolves {@code $C{Source/gitHub}}).  Jetty-only — Spring Boot's embedded container has no
047 * {@code .cfg}/{@code Config} equivalent.
048 *
049 * <p>
050 * Registers the one seeded {@link PetStore} shared by every child resource.
051 *
052 * <h5 class='section'>Example:</h5>
053 * <p class='bjava'>
054 *    <jc>// Children declare a field and the group's bean back-fills it.</jc>
055 *    <ja>@Bean</ja>
056 *    <jk>private transient</jk> PetStore <jf>store</jf>;
057 * </p>
058 *
059 * <h5 class='section'>See Also:</h5><ul>
060 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauPetstore">juneau-petstore</a>
061 * </ul>
062 *
063 * @serial exclude
064 */
065@Rest(
066   title="Juneau Petstore (Jetty)",
067   description="Apache Juneau petstore sample application running under Jetty/Microservice.",
068   children={
069      PetstoreConsoleResource.class,
070      ConsoleAssetsRest.class,
071      PetStoreResource.class,
072      PetstoreUiResource.class,
073      ConfigResource.class,
074      LogsResource.class,
075      ShutdownResource.class
076   }
077)
078@HtmlDocConfig(
079   widgets={
080      ContentTypeMenuItem.class
081   },
082   header={
083      "<h3>$C{Petstore/appName}</h3>"
084   },
085   navlinks={
086      "api: servlet:/api",
087      "stats: servlet:/stats",
088      "$W{ContentTypeMenuItem}",
089      "source: $C{Source/gitHub}/org/apache/juneau/petstore/jetty/RootResources.java"
090   },
091   aside={
092      "<div class='text'>",
093      "\t<p>Apache Juneau petstore sample application.</p>",
094      "\t<p>This is a 'router' page that serves as a jumping-off point to the petstore CRUD resource and",
095      "\t   the microservice admin endpoints.</p>",
096      "\t<p>Click <span class='link'>API</span> for the generated swagger doc, or <span class='link'>STATS</span>",
097      "\t   for runtime statistics.</p>",
098      "</div>"
099   },
100   asideFloat="RIGHT"
101)
102@SerializerConfig(
103   // For consistency with other Juneau samples — single quotes simplify HTML/string assertions in tests.
104   quoteChar="'"
105)
106@SuppressWarnings({
107   "java:S110" // Inheritance depth acceptable for example/demo code
108})
109public class RootResources extends BasicRestServletGroup {
110
111   private static final long serialVersionUID = 1L;
112
113   /**
114    * Registers the one {@link PetStore} shared by the {@code /petstore} API and the console tree, seeded with the
115    * deterministic demo data set.
116    *
117    * <p>
118    * Child resources inherit the group's beans, so a plain {@code @Bean} method is all that is needed.
119    *
120    * <p>
121    * The store runs on the system clock unless the {@value PetstoreSeed#FIXED_NOW_ENV} environment variable is set, which pins
122    * "now" so the store page's day figures render the same on every run (the docs screenshots rely on this).  Its value
123    * is an ISO-8601 instant such as {@code 2026-10-01T12:00:00Z}, or {@code seed} for the seed data's own clock.
124    *
125    * @return The seeded {@link PetStore}.
126    */
127   @Bean
128   public PetStore petStore() {
129      var clock = PetstoreSeed.fixedNowClock();
130      if (clock == null)
131         return PetstoreSeed.create().populate(new PetStore());
132      return PetstoreSeed.create().clock(clock).populate(new PetStore(clock));
133   }
134
135   /**
136    * {@code GET /} goes to the console store page.
137    *
138    * @param req The request.
139    * @return A 303 to {@code /console/store}.
140    */
141   @RestGet(path="/")
142   public SeeOther index(RestRequest req) {
143      return new SeeOther().setLocation(req.getUriResolver().resolve("servlet:/console/store"));
144   }
145}