{title:'juneau-petstore-server', created:'9.0.0'}

The juneau-petstore-server module contains all of the guts of the application. It's a standard Spring Boot application with Juneau integration support. For brevity, the app and configuration classes are combined into the following:

App.java

| @SpringBootApplication | @EnableJpaRepositories(basePackages="org.apache.juneau.petstore") | @EnableCaching | @Controller | public class App { | | //----------------------------------------------------------------------------------------------------------------- | // App | //----------------------------------------------------------------------------------------------------------------- | | public static void main(String[] args) { | try { | new SpringApplicationBuilder(App.class).run(args); | } catch (Exception e) { | e.printStackTrace(); | } | } | | //----------------------------------------------------------------------------------------------------------------- | // Beans | //----------------------------------------------------------------------------------------------------------------- | | @Bean | public PetStoreService petStoreService() { | return new PetStoreService(); | } | | @Bean | public RootResources rootResources() { | return new RootResources(); | } | | @Bean | public PetStoreResource petStoreResource() { | return new PetStoreResource(); | } | | @Bean | public ServletRegistrationBean getRootServlet(RootResources rootResources) { | return new ServletRegistrationBean<>(rootResources, "/*"); | } | }

Notice how cleanly Juneau servlets fit into Spring Boot. No special initializers are required to integrate Juneau with Spring Boot.

The RootResources class is the top-level entry point into the REST API. It allows us to group child resources. In our case though we only have one child resource...PetStoreResource:

RootResources.java

| @Rest( | path="/*", | title="Root resources", | description="Example of a router resource page.", | children={ | PetStoreResource.class | } | ) | @HtmlDocConfig( | widgets={ | ContentTypeMenuItem.class | }, | navlinks={ | "options: ?method=OPTIONS", | "$W{ContentTypeMenuItem}", | "source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java" | }, | aside={ | "<div style='max-width:400px' class='text'>", | " <p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>", | " <p>Resources can be nested arbitrarily deep through router pages.</p>", | " <p>Note the <span class='link'>options</span> link provided that lets you see the generated swagger doc for this page.</p>", | " <p>Also note the <span class='link'>sources</span> link on these pages to view the source code for the page.</p>", | " <p>All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.</p>", | " <p>Other features (such as this aside) are added through annotations.</p>", | "</div>" | } | ) | public class RootResources extends BasicSpringRestServletGroup { | private static final long serialVersionUID = 1L; | }

By extending from BasicSpringRestServletGroup, the root servlet hooks into the injection framework of Spring to resolve spring beans such as the child resource PetStoreResource.

This page renders as follows:

| http://localhost:5000

The PetStoreResource class is the REST implementation of our PetStore interface.

PetStoreResource.java

| @Rest( | path="/petstore", | title="Petstore application", | description={ | "This is a sample server Petstore server based on the Petstore sample at Swagger.io.", | "You can find out more about Swagger at http://swagger.io.", | }, | swagger=@Swagger( | version="1.0.0", | title="Swagger Petstore", | termsOfService="You are on your own.", | contact=@Contact( | name="Juneau Development Team", | email="dev@juneau.apache.org", | url="http://juneau.apache.org" | ), | license=@License( | name="Apache 2.0", | url="http://www.apache.org/licenses/LICENSE-2.0.html" | ), | externalDocs=@ExternalDocs( | description="Find out more about Juneau", | url="http://juneau.apache.org" | ), | tags={ | @Tag( | name="pet", | description="Everything about your Pets", | externalDocs=@ExternalDocs( | description="Find out more", | url="http://juneau.apache.org" | ) | ), | @Tag( | name="store", | description="Access to Petstore orders" | ), | @Tag( | name="user", | description="Operations about user", | externalDocs=@ExternalDocs( | description="Find out more about our store", | url="http://juneau.apache.org" | ) | ) | } | ), | staticFiles={"htdocs:/htdocs"} | ) | @HtmlDocConfig( | widgets={ | ContentTypeMenuItem.class, | }, | navlinks={ | "up: request:/..", | "options: servlet:/?method=OPTIONS", | "$W{ContentTypeMenuItem}", | "source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java" | }, | head={ | "<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>" // Add a cat icon to the page. | }, | header={ | "<h1>$R{resourceTitle}</h1>", | "<h2>$R{methodSummary}</h2>", | "$C{PetStore/headerImage}" | }, | aside={ | "<div style='max-width:400px' class='text'>", | " <p>This page shows a standard nested REST resource.</p>", | " <p>It shows how different properties can be rendered on the same bean in different views.</p>", | " <p>It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.</p>", | " <p>It also shows how the Queryable converter and query widget can be used to create searchable interfaces.</p>", | "</div>" | }, | stylesheet="servlet:/htdocs/themes/dark.css" // Use dark theme by default. | ) | public class PetStoreResource extends BasicRestObject implements PetStore { | | @Autowired | private PetStoreService store; | | /** | * Navigation page | * | * @return Navigation page contents. | */ | @RestGet( | path="/", | summary="Navigation page" | ) | @HtmlDocConfig( | style={ | "INHERIT", // Flag for inheriting resource-level CSS. | "body { ", | "background-image: url('petstore/htdocs/background.jpg'); ", | "background-color: black; ", | "background-size: cover; ", | "background-attachment: fixed; ", | "}" | } | ) | public ResourceDescriptions getTopPage() { | return new ResourceDescriptions() | .append("pet", "All pets in the store") | .append("store", "Orders and inventory") | .append("user", "Petstore users") | ; | } | | ...

Clicking the petstore link on the root page takes you to our PetStore resource:

| http://localhost:5000/petstore

The methods defined in our PetStore interface are implemented like so:

PetStoreResource.java

| @Override /* PetStore */ | @RestGet( | path="/pet", | summary="All pets in the store", | swagger=@OpSwagger( | tags="pet", | parameters={ | Queryable.SWAGGER_PARAMS // Documents searching. | } | ), | converters={Queryable.class} // Searching support. | ) | @Bean(on="Pet", excludeProperties="tags,photo") // In this view, don't serialize tags/photos properties. | public Collection<Pet> getPets() throws NotAcceptable { | return store.getPets(); | } | | @Override /* PetStore */ | @RestGet( | path="/pet/{petId}", | summary="Find pet by ID", | description="Returns a single pet", | swagger=@OpSwagger( | tags="pet" | ) | ) | public Pet getPet(long petId) throws IdNotFound, NotAcceptable { | return store.getPet(petId); | } | | @Override /* PetStore */ | @RestPost( | path="/pet", | summary="Add a new pet to the store", | swagger=@OpSwagger( | tags="pet" | ), | roleGuard="ROLE_ADMIN || (ROLE_USER && ROLE_WRITABLE)" // Restrict access to this method. | ) | public long createPet(CreatePet pet) throws IdConflict, NotAcceptable, UnsupportedMediaType { | return store.create(pet).getId(); | } | | ...

After running the Main method in the client code to populate the database, the page renders as follows:

| http://localhost:5000/petstore/pet

The OPTIONS menu items takes you to the auto-generated Swagger UI for the application:

| http://localhost:10000/petstore/pet?method=OPTIONS

Since we've defined tags on our annotations, the pet-related operations are all grouped under the pet tag:

Information for all HTTP parts is automatically generated:

The schema models for POJO models is available in the Responses section of an operation:

Auto-generated examples are available for all supported languages:

For example, application/json5:

Examples can be derived in a number of ways. In our case, we've defined a static method on our Pet class annotated with @Example:

Pet.java

| @Example | public static Pet example() { | return new Pet() | .id(123) | .species(Species.DOG) | .name("Doggie") | .tags("friendly","smart") | .status(PetStatus.AVAILABLE); | }

Similar functionality exists for request bodies as well:

At the bottom of the page is a listing of the POJO models in the app: