This is an automated email from the ASF dual-hosted git repository. jamesbognar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/juneau.git
commit 251e90ae2537c508f4197d0bb11309cc410f55ab Author: JamesBognar <[email protected]> AuthorDate: Fri Jun 24 08:18:22 2022 -0400 Javadocs --- juneau-doc/src/main/javadoc/doc-files/9a.png | Bin 0 -> 221670 bytes juneau-doc/src/main/javadoc/doc-files/9b.png | Bin 0 -> 146792 bytes juneau-doc/src/main/javadoc/doc-files/9c.png | Bin 0 -> 226731 bytes juneau-doc/src/main/javadoc/doc-files/9d.png | Bin 0 -> 234305 bytes juneau-doc/src/main/javadoc/doc-files/9e.png | Bin 0 -> 110349 bytes juneau-doc/src/main/javadoc/doc-files/9f.png | Bin 0 -> 185344 bytes juneau-doc/src/main/javadoc/doc-files/9g.png | Bin 0 -> 140337 bytes juneau-doc/src/main/javadoc/doc-files/9h.png | Bin 0 -> 116711 bytes juneau-doc/src/main/javadoc/doc-files/PetStore.png | Bin 0 -> 838280 bytes .../src/main/javadoc/doc-files/PetStore_pets.png | Bin 0 -> 233639 bytes .../src/main/javadoc/doc-files/RootResources.png | Bin 0 -> 184725 bytes juneau-doc/src/main/javadoc/overview.html | 685 ++++++++++++++++++++- juneau-doc/src/main/javadoc/resources/docs.txt | 6 +- .../src/main/javadoc/resources/fragments/toc.html | 8 +- 14 files changed, 681 insertions(+), 18 deletions(-) diff --git a/juneau-doc/src/main/javadoc/doc-files/9a.png b/juneau-doc/src/main/javadoc/doc-files/9a.png new file mode 100644 index 000000000..33a1791d8 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9a.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9b.png b/juneau-doc/src/main/javadoc/doc-files/9b.png new file mode 100644 index 000000000..85720f204 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9b.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9c.png b/juneau-doc/src/main/javadoc/doc-files/9c.png new file mode 100644 index 000000000..23a3e7ff9 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9c.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9d.png b/juneau-doc/src/main/javadoc/doc-files/9d.png new file mode 100644 index 000000000..f183863a5 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9d.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9e.png b/juneau-doc/src/main/javadoc/doc-files/9e.png new file mode 100644 index 000000000..286a78ffe Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9e.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9f.png b/juneau-doc/src/main/javadoc/doc-files/9f.png new file mode 100644 index 000000000..dd0013c9e Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9f.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9g.png b/juneau-doc/src/main/javadoc/doc-files/9g.png new file mode 100644 index 000000000..a5c0b6c14 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9g.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/9h.png b/juneau-doc/src/main/javadoc/doc-files/9h.png new file mode 100644 index 000000000..084e7ce49 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/9h.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/PetStore.png b/juneau-doc/src/main/javadoc/doc-files/PetStore.png new file mode 100644 index 000000000..78b98c896 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/PetStore.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/PetStore_pets.png b/juneau-doc/src/main/javadoc/doc-files/PetStore_pets.png new file mode 100644 index 000000000..e5e5c722f Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/PetStore_pets.png differ diff --git a/juneau-doc/src/main/javadoc/doc-files/RootResources.png b/juneau-doc/src/main/javadoc/doc-files/RootResources.png new file mode 100644 index 000000000..a4e5d96e4 Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/RootResources.png differ diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html index 2589f4e86..8d5f16651 100644 --- a/juneau-doc/src/main/javadoc/overview.html +++ b/juneau-doc/src/main/javadoc/overview.html @@ -73,25 +73,25 @@ <tr class='dark bb'> <td rowspan="4" style='text-align:center;font-weight:bold;padding:20px;'>Juneau Core</td> <td class='code'><a class='doclink' href='#juneau-marshall'>juneau-marshall</a></td> - <td> + <td style='padding:10px'> A universal toolkit for marshalling POJOs to a wide variety of content types using a common framework with no external library dependencies. </td> </tr> <tr class='dark bb'> <td class='code'><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td> - <td> + <td style='padding:10px'> Extended marshalling support for RDF languages. </td> </tr> <tr class='dark bb'> <td class='code'><a class='doclink' href='#juneau-dto'>juneau-dto</a></td> - <td> + <td style='padding:10px'> A variety of predefined DTOs for serializing and parsing languages such as HTML5, Swagger and ATOM. </td> </tr> <tr class='dark bb'> <td class='code'><a class='doclink' href='#juneau-config'>juneau-config</a></td> - <td> + <td style='padding:10px'> A sophisticated configuration file API. </td> </tr> @@ -99,32 +99,32 @@ <tr class='light bb'> <td rowspan="5" style='text-align:center;font-weight:bold;padding:20px;'>Juneau REST</td> <td class='code'><a class='doclink' href='#juneau-rest-server'>juneau-rest-server</a></td> - <td> + <td style='padding:10px'> A universal REST server API for creating Swagger-based self-documenting REST interfaces using POJOs, simply deployed as one or more top-level servlets in any Servlet 3.1.0+ container. </td> </tr> <tr class='light bb'> <td class='code'><a class='doclink' href='#juneau-rest-server-springboot'>juneau-rest-server-springboot</a></td> - <td> + <td style='padding:10px'> Spring boot integration support. </td> </tr> <tr class='light bb'> <td class='code'><a class='doclink' href='#juneau-rest-server-jaxrs'>juneau-rest-server-jaxrs</a></td> - <td> + <td style='padding:10px'> JAX/RS integration support. </td> </tr> <tr class='light bb'> <td class='code'><a class='doclink' href='#juneau-rest-client'>juneau-rest-client</a></td> - <td> + <td style='padding:10px'> A universal REST client API for interacting with Juneau or 3rd-party REST interfaces using POJOs and proxy interfaces. </td> </tr> <tr class='light bb'> <td class='code'><a class='doclink' href='#juneau-rest-mock'>juneau-rest-mock</a></td> - <td> + <td style='padding:10px'> Mocking APIs for server-less end-to-end testing of REST server and client APIs. </td> </tr> @@ -132,25 +132,25 @@ <tr class='dark bb'> <td rowspan="4" style='text-align:center;font-weight:bold;padding:20px;'>Examples</td> <td class='code'>juneau-examples-core</td> - <td> + <td style='padding:10px'> Juneau Core API examples. </td> </tr> <tr class='dark bb'> <td class='code'>juneau-examples-rest</td> - <td> + <td style='padding:10px'> Juneau REST API examples. </td> </tr> <tr class='dark bb'> <td class='code'>juneau-examples-rest-jetty</td> - <td> + <td style='padding:10px'> Juneau REST API examples using Jetty deployment. </td> </tr> <tr class='dark bb'> <td class='code'>juneau-examples-rest-springboot</td> - <td> + <td style='padding:10px'> Juneau REST API examples using Spring Boot deployment. </td> </tr> @@ -505,7 +505,13 @@ <li><p><a class='doclink' href='#my-springboot-microservice.msm.Running'>Running in Eclipse</a><span class='update'>created: 8.0.0</span></p> <li><p><a class='doclink' href='#my-springboot-microservice.msm.Building'>Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></p> </ol> - <li><p class='toc2'><a class='doclink' href='#juneau-petstore'>juneau-pestore</a><span class='update'>created: 8.2.0, <b><red>todo</red></b></span></p> + <li><p class='toc2'><a class='doclink' href='#juneau-petstore'>juneau-petstore</a><span class='update'>created: 8.2.0, updated: 9.0.0</span></p> + <ol> + <li><p><a class='doclink' href='#juneau-petstore.jp.RunningTheApp'>Running the Pet Store App</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-api'>juneau-petstore-api</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-client'>juneau-petstore-client</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-server'>juneau-petstore-server</a><span class='update'>created: 9.0.0</span></p> + </ol> <li><p class='toc2'><a class='doclink' href='#Glossaries'>Glossaries</a><span class='update'>created: 8.1.3</span></p> <ol> <li><p><a class='doclink' href='#Glossaries.g.LanguageSupport'>Language Support</a><span class='update'>created: 8.1.3</span></p> @@ -27638,13 +27644,660 @@ <!-- ==================================================================================================== --> -<h2 class='topic' onclick='toggle(this)'><a href='#juneau-petstore' id='juneau-petstore'>16 - juneau-pestore</a><span class='update'>created: 8.2.0, <b><red>todo</red></b></span></h2> +<h2 class='topic' onclick='toggle(this)'><a href='#juneau-petstore' id='juneau-petstore'>16 - juneau-petstore</a><span class='update'>created: 8.2.0, updated: 9.0.0</span></h2> <div class='topic'><!-- START: 16 - juneau-petstore --> <div class='topic'> <p> - TODO + The <c>PetStore</c> application is an functional application meant to demonstrate using Juneau with Spring Boot + to create an end-to-end client/server REST API. + </p> + <p> + What makes Juneau unique is the ability to create Java interfaces that behave just like RPC, but using REST + as the underlying protocol. And the technology it not tied to any platform so it can be used in any environment + by simply pulling in Maven dependencies. The server-side need only provide the ability to host a servlet. + </p> + <p> + Visit the <a class='doclink' href='https://github.com/apache/juneau-petstore'>GitHub project</a> hosting the application. + </p> + <p> + The project is broken down into the following subprojects: + </p> + <ul class='spaced-list'> + <li><c>juneau-petstore-api</c> - Contains the Java interface and DTOs for the petstore application. + <li><c>juneau-petstore-server</c> - Contains the server-side Java implementation of the petstore Java interface as a REST resource. + <li><c>juneau-petstore-client</c> - Contains the client-side Java proxy of the petstore Java interface. + </ul> +</div> + +<!-- ==================================================================================================== --> + +<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.RunningTheApp' id='juneau-petstore.jp.RunningTheApp'>16.1 - Running the Pet Store App</a><span class='update'>created: 9.0.0</span></h3> +<div class='topic'><!-- START: 16.1 - juneau-petstore.jp.RunningTheApp --> +<div class='topic'> + <p> + The Pet Store app is a Spring Boot application that can be started up by running the <c>App</c> class. + This starts the application on port 5000. It can also be started in a docker container using the following + instructions: + </p> + <ul class='spaced-list'> + <li> + Install <a class='doclink' href='https://docs.docker.com/install/'>docker</a> on your machine. + </li> + <li> + <p> + Clone the Petstore project on your machine. + </p> + <p class='bcode w800'> + git clone https://github.com/apache/juneau-petstore.git + </p> + </li> + <li> + <p> + Open terminal inside the project directory and run the below command to start the app. + </p> + <p class='bcode w800'> + docker build . -t petstore && docker run -p 5000:5000 petstore + </p> + </li> + </ul> +</div> +</div><!-- END: 16.1 - juneau-petstore.jp.RunningTheApp --> + +<!-- ==================================================================================================== --> + +<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-api' id='juneau-petstore.jp.juneau-petstore-api'>16.2 - juneau-petstore-api</a><span class='update'>created: 9.0.0</span></h3> +<div class='topic'><!-- START: 16.2 - juneau-petstore.jp.juneau-petstore-api --> +<div class='topic'> + <p> + The <c>juneau-petstore-api</c> module contains the Java interface of our application and the DTOs that go along + with it. These classes are meant to be shared between the server and client side code. + </p> + + <p> + The <c>PetStore</c> class is our primary class for defining our application. It's a standard Java interface with + annotations used to describe how the methods map to REST calls. + </p> + <h5 class='figure'>PetStore.java</h5> + <p class='bcode w800'> + <ja>@Remote</ja>(path=<js>"/petstore"</js>) + <jk>public interface</jk> PetStore { + + <jc>//------------------------------------------------------------------------------------------------------------------ + // Pets + //------------------------------------------------------------------------------------------------------------------</jc> + + <jd>/** + * Returns all pets in the database. + * + * @return All pets in the database. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + */</jd> + <ja>@RemoteGet</ja>(<js>"/pet"</js>) + <jk>public</jk> Collection<Pet> getPets() <jk>throws</jk> NotAcceptable; + + <jd>/** + * Returns a pet from the database. + * + * @param petId The ID of the pet to retrieve. + * @return The pet. + * @throws IdNotFound Pet was not found. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + */</jd> + <ja>@RemoteGet</ja>(<js>"/pet/{petId}"</js>) + <jk>public</jk> Pet getPet( + <ja>@Path</ja>( + name=<js>"petId"</js>, + schema=<ja>@Schema</ja>(description=<js>"ID of pet to return"</js>) + ) + <jk>long</jk> <jv>petId</jv> + ) <jk>throws</jk> IdNotFound, NotAcceptable; + + <jd>/** + * Adds a pet to the database. + * + * @param pet The pet data to add to the database. + * @return {@link Ok} if successful. + * @throws IdConflict ID already in use. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + * @throws UnsupportedMediaType Unsupported <c>Content-Type</c> header specified. + */</jd> + <ja>@RemotePost</ja>(<js>"/pet"</js>) + <jk>public long</jk> createPet( + <ja>@Content</ja>( + schema=<ja>@Schema</ja>(description=<js>"Pet object to add to the store"</js>) + ) + CreatePet <jv>pet</jv> + ) <jk>throws</jk> IdConflict, NotAcceptable, UnsupportedMediaType; + + <jd>/** + * Updates a pet in the database. + * + * @param pet The pet data to add to the database. + * @return {@link Ok} if successful. + * @throws IdNotFound ID not found. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + * @throws UnsupportedMediaType Unsupported <c>Content-Type</c> header specified. + */</jd> + <ja>@RemotePut</ja>(<js>"/pet/{petId}"</js>) + <jk>public</jk> Ok updatePet( + <ja>@Content</ja>( + schema=<ja>@Schema</ja>(description=<js>"Pet object that needs to be added to the store"</js>) + ) + UpdatePet <jv>pet</jv> + ) <jk>throws</jk> IdNotFound, NotAcceptable, UnsupportedMediaType; + + <jd>/** + * Find all pets with the matching statuses. + * + * @param status The statuses to match against. + * @return The pets that match the specified statuses. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + */</jd> + <ja>@RemoteGet</ja>(<js>"/pet/findByStatus"</js>) + <jk>public</jk> Collection<Pet> findPetsByStatus( + <ja>@Query</ja>( + name=<js>"status"</js>, + schema=<ja>@Schema</ja>( + description=<js>"Status values that need to be considered for filter."</js>, + required=<jk>true</jk>, + type=<js>"array"</js>, + collectionFormat=<js>"csv"</js>, + items=<ja>@Items</ja>( + type=<js>"string"</js>, + _enum=<js>"AVAILABLE,PENDING,SOLD"</js>, + _default=<js>"AVAILABLE"</js> + ) + ) + ) + PetStatus[] <jv>status</jv> + ) <jk>throws</jk> NotAcceptable; + + <jd>/** + * Deletes the specified pet. + * + * @param apiKey Security key. + * @param petId ID of pet to delete. + * @return {@link Ok} if successful. + * @throws IdNotFound Pet not found. + * @throws NotAcceptable Unsupported <c>Accept</c> header specified. + */</jd> + <ja>@RemoteDelete</ja>(<js>"/pet/{petId}"</js>) + <jk>public</jk> Ok deletePet( + <ja>@Header</ja>( + name=<js>"api_key"</js>, + schema=<ja>@Schema</ja>( + description=<js>"Security API key"</js>, + required=<jk>true</jk> + ) + ) + String <jv>apiKey</jv>, + <ja>@Path</ja>( + name=<js>"petId"</js>, + schema=<ja>@Schema(description=<js>"Pet id to delete"</js>) + ) + <jk>long</jk> <jv>petId</jv> + ) <jk>throws</jk> IdNotFound, NotAcceptable; + + <jd>/** + * Deletes all pets in the database. + * + * @return {@link Ok} if successful. + */</jd> + <ja>@RemoteDelete</ja>(<js>"/pet"</js>) + <jk>public</jk> Ok deleteAllPets(); + + <jc>//------------------------------------------------------------------------------------------------------------------ + // Orders + //------------------------------------------------------------------------------------------------------------------</jc> + + ... + } + </p> + + <p> + <ja>@Remote</ja> and <ja>@RemoteX</ja> are client-side annotations used to map the method calls to REST + and will be describe in the client code section. + </p> + <p> + <ja>@Path</ja> and <ja>@Body</ja> are used by both the client and server side code to map to REST artifacts on both + sides. + </p> + <p> + Both sets of annotations are provided by pulling in the Juneau dependency below: + + <h5 class='figure'>Maven Dependency</h5> + <p class='bcode w500'> + <xt><dependency></xt> + <xt><groupId></xt>org.apache.juneau<xt></groupId></xt> + <xt><artifactId></xt>juneau-marshall<xt></artifactId></xt> + <xt><version></xt>9.x.x<xt></version></xt> + <xt></dependency></xt> + </p> + <p> + The <c>Pet</c> class is a DTO that gets serialized over the REST connection. It is also annotated with JPA annotations + so that they can easily be stored in a JPA datastore on the server side. + </p> + <h5 class='figure'>Pet.java</h5> + <p class='bcode w800'> + <ja>@Bean</ja>(typeName=<js>"Pet"</js>, properties=<js>"id,species,name,tags,price,status"</js>) + <ja>@Entity</ja>(name=<js>"PetstorePet"</js>) + <jk>public class</jk> Pet { + + <ja>@Column @Id @GeneratedValue</ja> + <ja>@Schema</ja>(description=<js>"Unique identifier for this pet."</js>) + <ja>@Html</ja>(link=<js>"servlet:/pet/{id}"</js>) + <jk>private long</jk> <jf>id</jf>; + + <ja>@Column</ja>(length=50) + <ja>@Schema</ja>(description=<js>"Pet name."</js>, minLength=3, maxLength=50) + <jk>private</jk> String <jf>name</jf>; + + <ja>@Column</ja> + <ja>@Schema</ja>(description=<js>"Price of pet."</js>, maximum=<js>"999.99"</js>) + <ja>@Html</ja>(render=PriceRender.<jk>class</jk>) + <jk>private float</jk> <jf>price</jf>; + + ... + } + </p> + <p> + The annotations here are a combination of Juneau annotations for controlling marshalling (<ja>@Bean</ja>, <ja>@Html</ja>) + and documentation/validation (<ja>@Schema</ja>), and JPA annoations for database persistence (<ja>@Entity</ja>, <ja>@Column</ja>). + </p> + <div class='info'> + Most applications may choose to have separate classes for DTOs and JPA beans since you typically are not going to want + to expose server-side details to client-side code. In these examples however they were combined into the same classes for brevity. + </div> +</div> +</div><!-- END: 16.2 - juneau-petstore.jp.juneau-petstore-api --> + +<!-- ==================================================================================================== --> + +<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-client' id='juneau-petstore.jp.juneau-petstore-client'>16.3 - juneau-petstore-client</a><span class='update'>created: 9.0.0</span></h3> +<div class='topic'><!-- START: 16.3 - juneau-petstore.jp.juneau-petstore-client --> +<div class='topic'> + <p> + The <c>juneau-petstore-client</c> module contains a single <c>Main</c> class used to instantiate the proxy against + our remote REST interface using the Java interface described above. + </p> + + <h5 class='figure'>Main.java</h5> + <p class='bcode w800'> + <jk>public class</jk> Main { + + <jk>public static void</jk> main(String[] <jv>args</jv>) { + + <jc>// Create a RestClient with JSON serialization support.</jc> + RestClient <jv>restClient</jv> = RestClient.<jsm>create</jsm>().simpleJson().build(); + + <jc>// Instantiate our proxy.</jc> + PetStore <jv>petStore</jv> = <jv>restClient</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:5000"</js>); + + <jc>// Print out the pets in the store.</jc> + Collection<Pet> <jv>pets</jv> = <jv>petStore</jv>.getPets(); + + <jc>// Pretty-print them to STDOUT.</jc> + SimpleJson.<jsf>DEFAULT_READABLE</jsf>.println(<jv>pets</jv>); + } + } + </p> + <p> + Notice how little code is necessary to construct a remote proxy. + </p> +</div> +</div><!-- END: 16.3 - juneau-petstore.jp.juneau-petstore-client --> + +<!-- ==================================================================================================== --> + +<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-server' id='juneau-petstore.jp.juneau-petstore-server'>16.4 - juneau-petstore-server</a><span class='update'>created: 9.0.0</span></h3> +<div class='topic'><!-- START: 16.4 - juneau-petstore.jp.juneau-petstore-server --> +<div class='topic'> + <p> + The <c>juneau-petstore-server</c> 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: </p> + + <h5 class='figure'>App.java</h5> + <p class='bcode w800'> + <ja>@SpringBootApplication</ja> + <ja>@EnableJpaRepositories</ja>(basePackages=<js>"org.apache.juneau.petstore"</js>) + <ja>@EnableCaching</ja> + <ja>@Controller</ja> + <jk>public class</jk> App { + + <jc>//----------------------------------------------------------------------------------------------------------------- + // App + //-----------------------------------------------------------------------------------------------------------------</jc> + + <jk>public static void</jk> main(String[] <jv>args</jv>) { + <jk>try</jk> { + <jk>new</jk> SpringApplicationBuilder(App.<jk>class</jk>).run(<jv>args</jv>); + } <jk>catch</jk> (Exception <jv>e</jv>) { + <jv>e</jv>.printStackTrace(); + } + } + + <jc>//----------------------------------------------------------------------------------------------------------------- + // Beans + //-----------------------------------------------------------------------------------------------------------------</jc> + + <ja>@Bean</ja> + <jk>public</jk> PetStoreService petStoreService() { + <jk>return new</jk> PetStoreService(); + } + + <ja>@Bean</ja> + <jk>public</jk> RootResources rootResources() { + <jk>return new</jk> RootResources(); + } + + <ja>@Bean</ja> + <jk>public</jk> PetStoreResource petStoreResource() { + <jk>return new</jk> PetStoreResource(); + } + + <ja>@Bean</ja> + <jk>public</jk> ServletRegistrationBean<Servlet> getRootServlet(RootResources rootResources) { + <jk>return new</jk> ServletRegistrationBean<>(rootResources, "/*"); + } + } + </p> + <p> + Notice how cleanly Juneau servlets fit into Spring Boot. No special initializers are required + to integrate Juneau with Spring Boot. + </p> + + <p> + The <c>RootResources</c> 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...<c>PetStoreResource</c>: + </p> + + <h5 class='figure'>RootResources.java</h5> + <p class='bcode w800'> + <ja>@Rest</ja>( + path=<js>"/*"</js>, + title=<js>"Root resources"</js>, + description=<js>"Example of a router resource page."</js>, + children={ + PetStoreResource.<jk>class</jk> + } + ) + <ja>@HtmlDocConfig</ja>( + widgets={ + ContentTypeMenuItem.<jk>class</jk> + }, + navlinks={ + <js>"options: ?method=OPTIONS"</js>, + <js>"$W{ContentTypeMenuItem}"</js>, + <js>"source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java"</js> + }, + aside={ + <js>"<div style='max-width:400px' class='text'>"</js>, + <js>" <p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>"</js>, + <js>" <p>Resources can be nested arbitrarily deep through router pages.</p>"</js>, + <js>" <p>Note the <span class='link'>options</span> link provided that lets you see the generated swagger doc for this page.</p>"</js>, + <js>" <p>Also note the <span class='link'>sources</span> link on these pages to view the source code for the page.</p>"</js>, + <js>" <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>"</js>, + <js>" <p>Other features (such as this aside) are added through annotations.</p>"</js>, + <js>"</div>"</js> + } + ) + <jk>public class</jk> RootResources <jk>extends</jk> BasicSpringRestServletGroup <jk>implements</jk> BasicUniversalConfig { + <jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; + } + </p> + <p> + By extending from <c>BasicSpringRestServletGroup</c>, the root servlet hooks into the injection framework of Spring + to resolve spring beans such as the child resource <c>PetStoreResource</c>. + </p> + <p> + This page renders as follows: + </p> + + <p class='bcode w800'> + http://localhost:5000 + </p> + <img class='bordered w800' src='doc-files/RootResources.png'> + + <p> + The <c>PetStoreResource</c> class is the REST implementation of our <c>PetStore</c> interface. + </p> + + <h5 class='figure'>PetStoreResource.java</h5> + <p class='bcode w800'> + <ja>@Rest</ja>( + path=<js>"/petstore"</js>, + title=<js>"Petstore application"</js>, + description={ + <js>"This is a sample server Petstore server based on the Petstore sample at Swagger.io."</js>, + <js>"You can find out more about Swagger at http://swagger.io."</js>, + }, + swagger=<ja>@Swagger</ja>( + version=<js>"1.0.0"</js>, + title=<js>"Swagger Petstore"</js>, + termsOfService=<js>"You are on your own."</js>, + contact=<ja>@Contact</ja>( + name=<js>"Juneau Development Team"</js>, + email=<js>"[email protected]"</js>, + url=<js>"http://juneau.apache.org"</js> + ), + license=<ja>@License</ja>( + name=<js>"Apache 2.0"</js>, + url=<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js> + ), + externalDocs=<ja>@ExternalDocs</ja>( + description=<js>"Find out more about Juneau"</js>, + url=<js>"http://juneau.apache.org"</js> + ), + tags={ + <ja>@Tag</ja>( + name=<js>"pet"</js>, + description=<js>"Everything about your Pets"</js>, + externalDocs=<ja>@ExternalDocs</ja>( + description=<js>"Find out more"</js>, + url=<js>"http://juneau.apache.org"</js> + ) + ), + <ja>@Tag</ja>( + name=<js>"store"</js>, + description=<js>"Access to Petstore orders"</js> + ), + <ja>@Tag</ja>( + name=<js>"user"</js>, + description=<js>"Operations about user"</js>, + externalDocs=<ja>@ExternalDocs</ja>( + description=<js>"Find out more about our store"</js>, + url=<js>"http://juneau.apache.org"</js> + ) + ) + } + ), + staticFiles={<js>"htdocs:/htdocs"</js>} + ) + <ja>@HtmlDocConfig</ja>( + widgets={ + ContentTypeMenuItem.<jk>class</jk>, + }, + navlinks={ + <js>"up: request:/.."</js>, + <js>"options: servlet:/?method=OPTIONS"</js>, + <js>"$W{ContentTypeMenuItem}"</js>, + <js>"source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java"</js> + }, + head={ + <js>"<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>"</js> <jc>// Add a cat icon to the page.</jc> + }, + header={ + <js>"<h1>$R{resourceTitle}</h1>"</js>, + <js>"<h2>$R{methodSummary}</h2>"</js>, + <js>"$C{PetStore/headerImage}"</js> + }, + aside={ + <js>"<div style='max-width:400px' class='text'>"</js>, + <js>" <p>This page shows a standard nested REST resource.</p>"</js>, + <js>" <p>It shows how different properties can be rendered on the same bean in different views.</p>"</js>, + <js>" <p>It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.</p>"</js>, + <js>" <p>It also shows how the Queryable converter and query widget can be used to create searchable interfaces.</p>"</js>, + <js>"</div>"</js> + }, + stylesheet=<js>"servlet:/htdocs/themes/dark.css"</js> <jc>// Use dark theme by default.</jc> + ) + <jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig, PetStore { + + <ja>@Inject</ja> + <jk>private</jk> PetStoreService <jf>store</jf>; + + <jd>/** + * Navigation page + * + * @return Navigation page contents. + */</jd> + <ja>@RestGet</ja>( + path=<js>"/"</js>, + summary=<js>"Navigation page"</js> + ) + <ja>@HtmlDocConfig</ja>( + style={ + <js>"INHERIT"</js>, <jc>// Flag for inheriting resource-level CSS.</jc> + <js>"body { "</js>, + <js>"background-image: url('petstore/htdocs/background.jpg'); "</js>, + <js>"background-color: black; "</js>, + <js>"background-size: cover; "</js>, + <js>"background-attachment: fixed; "</js>, + <js>"}"</js> + } + ) + <jk>public</jk> ResourceDescriptions getTopPage() { + <jk>return new</jk> ResourceDescriptions() + .append(<js>"pet"</js>, <js>"All pets in the store"</js>) + .append(<js>"store"</js>, <js>"Orders and inventory"</js>) + .append(<js>"user"</js>, <js>"Petstore users"</js>) + ; + } + + ... + </p> + <p> + Clicking the <c>petstore</c> link on the root page takes you to our PetStore resource: + </p> + <p class='bcode w800'> + http://localhost:5000/petstore + </p> + <img class='bordered w800' src='doc-files/PetStore.png'> + + <p> + The methods defined in our <c>PetStore</c> interface are implemented like so: + </p> + <h5 class='figure'>PetStoreResource.java</h5> + <p class='bcode w800'> + <ja>@Override</ja> <jc>/* PetStore */</jc> + <ja>@RestGet</ja>( + path=<js>"/pet"</js>, + summary=<js>"All pets in the store"</js>, + swagger=<ja>@OpSwagger</ja>( + tags=<js>"pet"</js>, + parameters={ + Queryable.<jsf>SWAGGER_PARAMS</jsf> <jc>// Documents searching.</jc> + } + ), + converters={Queryable.<jk>class</jk>} <jc>// Searching support.</jc> + ) + <ja>@Bean</ja>(on=<js>"Pet"</js>, excludeProperties=<js>"tags,photo"</js>) <jc>// In this view, don't serialize tags/photos properties.</jc> + <jk>public</jk> Collection<Pet> getPets() <jk>throws</jk> NotAcceptable { + <jk>return</jk> <jf>store</jf>.getPets(); + } + + <ja>@Override</ja> <jc>/* PetStore */</jc> + <ja>@RestGet</ja>( + path=<js>"/pet/{petId}"</js>, + summary=<js>"Find pet by ID"</js>, + description=<js>"Returns a single pet"</js>, + swagger=<ja>@OpSwagger</ja>( + tags=<js>"pet"</js> + ) + ) + <jk>public</jk> Pet getPet(<jk>long</jk> <jv>petId</jv>) <jk>throws</jk> IdNotFound, NotAcceptable { + <jk>return</jk> <jf>store</jf>.getPet(<jv>petId</jv>); + } + + <ja>@Override</ja> <jc>/* PetStore */</jc> + <ja>@RestPost</ja>( + path=<js>"/pet"</js>, + summary=<js>"Add a new pet to the store"</js>, + swagger=<ja>@OpSwagger</ja>( + tags=<js>"pet"</js> + ), + roleGuard=<js>"ROLE_ADMIN || (ROLE_USER && ROLE_WRITABLE)"</js> <jc>// Restrict access to this method.</jc> + ) + <jk>public long</jk> createPet(CreatePet <jv>pet</jv>) <jk>throws</jk> IdConflict, NotAcceptable, UnsupportedMediaType { + <jk>return</jk> <jf>store</jf>.create(<jv>pet</jv>).getId(); + } + + ... + </p> + <p> + After running the <c>Main</c> method in the client code to populate the database, the page renders as follows: + </p> + <p class='bcode w800'> + http://localhost:5000/petstore/pet + </p> + <img class='bordered w800' src='doc-files/PetStore_pets.png'> + + <p> + The <l>OPTIONS</l> menu items takes you to the auto-generated Swagger UI for the application: + </p> + <p class='bcode w900'> + http://localhost:10000/petstore/pet?method=OPTIONS + </p> + <img class='bordered w900' src='doc-files/9a.png'> + <p> + Since we've defined tags on our annotations, the pet-related operations are all grouped under the <l>pet</l> tag: + </p> + <img class='bordered w900' src='doc-files/9b.png'> + <p> + Information for all HTTP parts is automatically generated: + </p> + <img class='bordered w900' src='doc-files/9h.png'> + <p> + The schema models for POJO models is available in the <l>Responses</l> section of an operation: + </p> + <img class='bordered w900' src='doc-files/9c.png'> + <p> + Auto-generated examples are available for all supported languages: + </p> + <img class='bordered w900' src='doc-files/9d.png'> + <p> + For example, <l>application/json+simple</l>: + </p> + <img class='bordered w900' src='doc-files/9e.png'> + <p> + Examples can be derived in a number of ways. In our case, we've defined a static method on our <l>Pet</l> + class annotated with <ja>@Example</ja>: + </p> + <h5 class='figure'>Pet.java</h5> + <p class='bcode w800'> + <ja>@Example</ja> + <jk>public static</jk> Pet example() { + <jk>return new</jk> Pet() + .id(123) + .species(Species.<jsf>DOG</jsf>) + .name(<js>"Doggie"</js>) + .tags(<js>"friendly"</js>,<js>"smart"</js>) + .status(PetStatus.<jsf>AVAILABLE</jsf>); + } + </p> + <p> + Similar functionality exists for request bodies as well: + </p> + <img class='bordered w900' src='doc-files/9f.png'> + <p> + At the bottom of the page is a listing of the POJO models in the app: + </p> + <img class='bordered w900' src='doc-files/9g.png'> + </div> +</div><!-- END: 16.4 - juneau-petstore.jp.juneau-petstore-server --> </div><!-- END: 16 - juneau-petstore --> <!-- ==================================================================================================== --> diff --git a/juneau-doc/src/main/javadoc/resources/docs.txt b/juneau-doc/src/main/javadoc/resources/docs.txt index dc3e8e5ca..c472014ec 100644 --- a/juneau-doc/src/main/javadoc/resources/docs.txt +++ b/juneau-doc/src/main/javadoc/resources/docs.txt @@ -204,6 +204,10 @@ jmr.RootProperty = #juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty, Overvie jmr.Serializers = #juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers, Overview > juneau-marshall-rdf > RDF Details > RDF Serializers jmr.TypedLiterals = #juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals, Overview > juneau-marshall-rdf > RDF Details > Typed Literals jmr.UriProperties = #juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties, Overview > juneau-marshall-rdf > RDF Details > URI Properties +jp.RunningTheApp = #juneau-petstore.jp.RunningTheApp, Overview > juneau-petstore > Running the Pet Store App +jp.juneau-petstore-api = #juneau-petstore.jp.juneau-petstore-api, Overview > juneau-petstore > juneau-petstore-api +jp.juneau-petstore-client = #juneau-petstore.jp.juneau-petstore-client, Overview > juneau-petstore > juneau-petstore-client +jp.juneau-petstore-server = #juneau-petstore.jp.juneau-petstore-server, Overview > juneau-petstore > juneau-petstore-server jrc.Authentication = #juneau-rest-client.jrc.Authentication, Overview > juneau-rest-client > Authentication jrc.AuthenticationBASIC = #juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC, Overview > juneau-rest-client > Authentication > BASIC Authentication jrc.AuthenticationForm = #juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm, Overview > juneau-rest-client > Authentication > FORM-based Authentication @@ -300,7 +304,7 @@ juneau-marshall = #juneau-marshall, Overview > juneau-marshall juneau-marshall-rdf = #juneau-marshall-rdf, Overview > juneau-marshall-rdf juneau-microservice-core = #juneau-microservice-core, Overview > juneau-microservice-core juneau-microservice-jetty = #juneau-microservice-jetty, Overview > juneau-microservice-jetty -juneau-petstore = #juneau-petstore, Overview > juneau-pestore +juneau-petstore = #juneau-petstore, Overview > juneau-petstore juneau-rest-client = #juneau-rest-client, Overview > juneau-rest-client juneau-rest-mock = #juneau-rest-mock, Overview > juneau-rest-mock juneau-rest-server = #juneau-rest-server, Overview > juneau-rest-server diff --git a/juneau-doc/src/main/javadoc/resources/fragments/toc.html b/juneau-doc/src/main/javadoc/resources/fragments/toc.html index ba9584a70..0e74cf8e8 100644 --- a/juneau-doc/src/main/javadoc/resources/fragments/toc.html +++ b/juneau-doc/src/main/javadoc/resources/fragments/toc.html @@ -359,7 +359,13 @@ <li><p><a class='doclink' href='{OVERVIEW_URL}#my-springboot-microservice.msm.Running'>Running in Eclipse</a><span class='update'>created: 8.0.0</span></p> <li><p><a class='doclink' href='{OVERVIEW_URL}#my-springboot-microservice.msm.Building'>Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></p> </ol> - <li><p class='toc2'><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore'>juneau-pestore</a><span class='update'>created: 8.2.0, <b><red>todo</red></b></span></p> + <li><p class='toc2'><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore'>juneau-petstore</a><span class='update'>created: 8.2.0, updated: 9.0.0</span></p> + <ol> + <li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore.jp.RunningTheApp'>Running the Pet Store App</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore.jp.juneau-petstore-api'>juneau-petstore-api</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore.jp.juneau-petstore-client'>juneau-petstore-client</a><span class='update'>created: 9.0.0</span></p> + <li><p><a class='doclink' href='{OVERVIEW_URL}#juneau-petstore.jp.juneau-petstore-server'>juneau-petstore-server</a><span class='update'>created: 9.0.0</span></p> + </ol> <li><p class='toc2'><a class='doclink' href='{OVERVIEW_URL}#Glossaries'>Glossaries</a><span class='update'>created: 8.1.3</span></p> <ol> <li><p><a class='doclink' href='{OVERVIEW_URL}#Glossaries.g.LanguageSupport'>Language Support</a><span class='update'>created: 8.1.3</span></p>
