Merge branch 'master' of
https://gitbox.apache.org/repos/asf/juneau-petstore.git
Conflicts:
Dockerfile
diff --git a/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/PetStore.java b/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/PetStore.java
index 5db76c5..76d184f 100644
--- a/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/PetStore.java
+++ b/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/PetStore.java
@@ -12,7 +12,7 @@
// ***************************************************************************************************************************
package org.apache.juneau.petstore;
-import static org.apache.juneau.http.HttpMethodName.*;
+import static org.apache.juneau.http.HttpMethod.*;
import java.util.*;
diff --git a/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/dto/Pet.java b/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/dto/Pet.java
index 40c1222..c7fb76b 100644
--- a/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/dto/Pet.java
+++ b/juneau-petstore-api/src/main/java/org/apache/juneau/petstore/dto/Pet.java
@@ -71,7 +71,7 @@
this.name = x.getName();
this.price = x.getPrice();
this.species = x.getSpecies();
- this.tags = x.getTags() == null ? null : Arrays.asList(x.getTags());
+ this.tags = new ArrayList<>(Arrays.asList(x.getTags()));
return this;
}
@@ -86,7 +86,7 @@
this.name = x.getName();
this.price = x.getPrice();
this.species = x.getSpecies();
- this.tags = x.getTags() == null ? null : Arrays.asList(x.getTags());
+ this.tags = x.getTags() == null ? null : new ArrayList<>(Arrays.asList(x.getTags()));
this.status = x.getStatus();
return this;
}
@@ -180,7 +180,7 @@
* @return This object (for method chaining).
*/
public Pet tags(String...value) {
- this.tags = Arrays.asList(value);
+ this.tags = new ArrayList<>(Arrays.asList(value));
return this;
}
diff --git a/juneau-petstore-client/src/main/java/org/apache/juneau/petstore/Main.java b/juneau-petstore-client/src/main/java/org/apache/juneau/petstore/Main.java
index 47b1fce..7560b14 100644
--- a/juneau-petstore-client/src/main/java/org/apache/juneau/petstore/Main.java
+++ b/juneau-petstore-client/src/main/java/org/apache/juneau/petstore/Main.java
@@ -17,16 +17,11 @@
import java.io.*;
import java.util.*;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.juneau.json.*;
import org.apache.juneau.marshall.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.petstore.dto.*;
-import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.client2.*;
/**
* Example code showing how to connect to the PetStore application using a remote proxy.
@@ -39,36 +34,22 @@
private static final JsonParser JSON_PARSER = JsonParser.create().ignoreUnknownBeanProperties().build();
- @SuppressWarnings("deprecation")
- public static void main(String[] args) {
+ public static void main(String[] args) throws ParseException, IOException {
- // TODO - This is broken until we can update to Juneau 8.1.3 which has a fix for handling how Spring Security
- // processes Basic Auth requests.
+ RestClient restClient = RestClient.create().simpleJson().basicAuth("localhost", 5000, "admin", "password").build();
- // Set up BASIC auth.
- // User/passwords are hardcoded in SpringSecurityConfig.
- Credentials up = new UsernamePasswordCredentials("admin", "password");
- CredentialsProvider p = new BasicCredentialsProvider();
- p.setCredentials(AuthScope.ANY, up);
+ // Instantiate our proxy.
+ PetStore petStore = restClient.getRemote(PetStore.class, "http://localhost:5000");
- // Create a RestClient with JSON serialization support.
- try (RestClient rc = RestClient.create(SimpleJsonSerializer.class, JsonParser.class).defaultCredentialsProvider(p).build()) {
+ // Print out the pets in the store.
+ Collection<Pet> pets = petStore.getPets();
- // Instantiate our proxy.
- PetStore petStore = rc.getRemote(PetStore.class, "http://localhost:5000");
+ // Pretty-print them to SYSOUT.
+ SimpleJson.DEFAULT_READABLE.println(pets);
- // Print out the pets in the store.
- Collection<Pet> pets = petStore.getPets();
+ // Initialize the application through REST calls.
+ init(new PrintWriter(System.out), petStore);
- // Pretty-print them to SYSOUT.
- SimpleJson.DEFAULT_READABLE.println(pets);
-
- // Initialize the application through REST calls.
- init(new PrintWriter(System.out), petStore);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
}
/**
diff --git a/juneau-petstore-server/pom.xml b/juneau-petstore-server/pom.xml
index b9f2320..f90efeb 100644
--- a/juneau-petstore-server/pom.xml
+++ b/juneau-petstore-server/pom.xml
@@ -41,7 +41,7 @@
<maven.javadoc.skip>true</maven.javadoc.skip>
- <juneau.version>8.1.2</juneau.version>
+ <juneau.version>8.2.0</juneau.version>
<javax.inject.version>1</javax.inject.version>
<servlet.version>3.1.0</servlet.version>
<hibernate.version>5.0.9.Final</hibernate.version>
@@ -122,7 +122,7 @@
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-mock</artifactId>
- <version>8.1.2</version>
+ <version>${juneau.version}</version>
<scope>test</scope>
</dependency>
diff --git a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/App.java b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/App.java
index 5afbec2..a124a63 100644
--- a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/App.java
+++ b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/App.java
@@ -12,10 +12,14 @@
// ***************************************************************************************************************************
package org.apache.juneau.petstore;
+import java.io.*;
+
+import org.apache.juneau.petstore.service.*;
import org.apache.juneau.rest.springboot.JuneauRestInitializer;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.*;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
@@ -28,12 +32,18 @@
public class App {
public static void main(String[] args) {
- new App().start(args);
- }
+ new App().start(args);
+ }
- protected void start(String[] args) {
- new SpringApplicationBuilder(App.class)
- .initializers(new JuneauRestInitializer(App.class)) // Needed for Juneau resources as injectible Spring beans.
- .run(args);
- }
+ protected void start(String[] args) {
+ ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class)
+ .initializers(new JuneauRestInitializer(App.class)) // Needed for Juneau resources as injectible Spring beans.
+ .run(args);
+
+ try {
+ ctx.getBean(PetStoreService.class).initDirect(new PrintWriter(System.out));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java
index 0d2dbcc..84bd414 100644
--- a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java
+++ b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/PetStoreResource.java
@@ -13,7 +13,7 @@
package org.apache.juneau.petstore.rest;
import static org.apache.juneau.dto.swagger.ui.SwaggerUI.*;
-import static org.apache.juneau.http.HttpMethodName.*;
+import static org.apache.juneau.http.HttpMethod.*;
import static org.apache.juneau.http.response.Ok.*;
import java.util.*;
diff --git a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/RootResources.java b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/RootResources.java
index c836f13..a2b5127 100644
--- a/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/RootResources.java
+++ b/juneau-petstore-server/src/main/java/org/apache/juneau/petstore/rest/RootResources.java
@@ -16,7 +16,6 @@
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.widget.*;
-import org.apache.juneau.serializer.annotation.*;
/**
* Sample REST resource showing how to implement a "router" resource page.
diff --git a/juneau-petstore-server/src/main/resources/htdocs/images/asf.png b/juneau-petstore-server/src/main/resources/htdocs/images/asf.png
new file mode 100644
index 0000000..ce28113
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/images/asf.png
Binary files differ
diff --git a/juneau-petstore-server/src/main/resources/htdocs/images/juneau.png b/juneau-petstore-server/src/main/resources/htdocs/images/juneau.png
new file mode 100644
index 0000000..42a1656
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/images/juneau.png
Binary files differ
diff --git a/juneau-petstore-server/src/main/resources/htdocs/styles/SwaggerUI.css b/juneau-petstore-server/src/main/resources/htdocs/styles/SwaggerUI.css
new file mode 100644
index 0000000..b55ffc6
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/styles/SwaggerUI.css
@@ -0,0 +1,342 @@
+/*
+ ***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************
+*/
+
+.swagger-ui {
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Header key-value pairs
+ ----------------------------------------------------------------------------------------------------------*/
+
+.swagger-ui table.header {
+ margin-bottom: 15px;
+ width: 95%;
+ border: none;
+}
+
+.swagger-ui table.header * {
+ vertical-align: middle;
+}
+
+.swagger-ui table.header th {
+ font-weight: bold;
+ padding: 5px 10px;
+ text-align: left;
+ white-space: nowrap;
+ border: none;
+ border-radius: 3px;
+}
+
+.swagger-ui table.header td {
+ padding: 5px 10px;
+ text-align: left;
+ vertical-align: middle;
+ border: none;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Method buttons (e.g GET/PUT/... buttons)
+ ----------------------------------------------------------------------------------------------------------*/
+.method-button {
+ display: inline-block;
+ font-weight: bold;
+ min-width: 60px;
+ padding: 6px 15px;
+ text-align: center;
+ border-radius: 3px;
+ text-shadow: 0 1px 0 rgba(0,0,0,.1);
+ color: #fff;
+}
+.get .method-button { background: rgb(97,175,254); }
+.put .method-button { background: rgb(252,161,48); }
+.post .method-button { background: rgb(73,204,144); }
+.delete .method-button { background: rgb(249,62,62); }
+.options .method-button { background: rgb(153,102,255); }
+.deprecated .method-button { background: rgb(170,170,170); }
+.model .method-button { background: rgb(150,150,150); min-width: 120px;}
+.other .method-button { background: rgb(230,230,0); }
+
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Tag block -
+ - Encapsulates one or more op-blocks.
+ ----------------------------------------------------------------------------------------------------------*/
+
+.tag-block {
+ min-width: 800px;
+}
+
+.tag-block-summary {
+ margin: 10px 0px;
+ padding: 5px 0px;
+ align-items: center;
+ cursor: pointer;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+ user-select: none;
+ transition: all .2s;
+}
+.tag-block-summary:hover {
+ background-color: rgba(59,65,81,.1);
+}
+
+.tag-block-summary .name {
+ font-size: 18px;
+ padding: 0px 20px;
+}
+.tag-block-summary .description {
+ font-size: 14px;
+ padding: 0px 20px;
+}
+.tag-block-summary .extdocs {
+ float: right;
+ font-size: 14px;
+ padding: 0px 20px;
+}
+
+.tag-block-open .tag-block-contents { display: block; }
+.tag-block-closed .tag-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block
+ - Encapsulates a single http-method + http-path
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block {
+ margin-bottom: 10px;
+ align-items: center;
+ border-radius: 4px;
+}
+
+.op-block.get { background: rgba(97,175,254,.1); border: 1px solid rgb(97,175,254); }
+.op-block.put { background: rgba(252,161,48,.1); border: 1px solid rgb(252,161,48); }
+.op-block.post { background: rgba(73,204,144,.1); border: 1px solid rgb(73,204,144); }
+.op-block.options { background: rgba(153,102,255,.1); border: 1px solid rgb(153,102,255); }
+.op-block.delete { background: rgba(249,62,62,.1); border: 1px solid rgb(249,62,62); }
+.op-block.deprecated { background: rgba(170,170,170,.1); border: 1px solid rgb(170,170,170); }
+.op-block.model { background: rgba(0,0,0,.05); border: 1px solid rgb(170,170,170); }
+.op-block.other { background: rgba(230,230,0,0.1); border: 1px solid rgb(230,230,0); }
+
+.op-block-summary {
+ padding: 5px;
+ cursor: pointer;
+ user-select: none;
+}
+
+.op-block-summary .path {
+ font-size: 14px;
+ word-break: break-all;
+ font-family: monospace;
+ font-weight: bold;
+ padding:10px;
+}
+
+.op-block.deprecated .op-block-summary .path { color: #8f9199; text-decoration: line-through;}
+.op-block.deprecated .op-block-summary .description { color: #8f9199 }
+
+.op-block-summary .summary {
+ font-size: 14px;
+ padding: 10px;
+}
+
+.op-block-description {
+ font-size: 14px;
+ padding: 10px;
+}
+
+
+.op-block-open .op-block-contents { display: block; }
+.op-block-closed .op-block-contents { display: none; }
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Op block section header -
+ - 'Parameters' and 'Responses' subsections in an op-block
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block-section-header {
+ padding: 8px 15px;
+ background: hsla(0,0%,100%,.3);
+ box-shadow: 1px 2px 3px rgba(0,0,0,.3);
+ margin: 10px;
+ border-radius: 4px;
+}
+
+.op-block-section-header .title {
+ font-size: 14px;
+ margin: 0px;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameters and Responses sections
+ ----------------------------------------------------------------------------------------------------------*/
+
+table.parameters, table.responses {
+ border-collapse: collapse;
+ margin: 20px;
+ width: 95%;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+th.parameter-key, th.response-key {
+ font-size: 12px;
+ font-weight: bold;
+ text-align: left;
+ border: none;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+ background-color: inherit;
+}
+
+td.parameter-key, td.response-key {
+ font-size: 12px;
+ padding: 10px;
+ text-align: left;
+ border: none;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+ background-color: inherit;
+}
+
+td.parameter-value, td.response-value {
+ padding: 10px;
+ text-align: left;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Parameter name
+ ----------------------------------------------------------------------------------------------------------*/
+
+.parameter-key .in {
+ font-size: 12px;
+ font-family: monospace;
+ font-weight: bold;
+ font-style: italic;
+ color: gray;
+}
+
+.parameter-key .name {
+ font-size: 14px;
+}
+
+.parameter-key .name.required {
+ font-weight: bold;
+}
+
+.parameter-key .requiredlabel {
+ font-size: 10px;
+ color: rgba(255,0,0,.6);
+ font-weight: bold;
+}
+
+.parameter-key .type {
+ font-size: 12px;
+ padding: 5px 0;
+ font-family: monospace;
+ font-weight: bold;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Examples
+ ----------------------------------------------------------------------------------------------------------*/
+
+.op-block-contents .example-select {
+ margin: 10px 0 5px 0;
+ border-width: 1px;
+ font-weight:bold;
+ padding: 5px 40px 5px 10px;
+ border: 1px solid #41444e;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px 0 rgba(0,0,0,.25);
+ background: hsla(0,0%,100%,.3);
+}
+
+.op-block-contents .example-select:disabled {
+ color: rgba(0,0,0,.50);
+ border: 1px solid rgba(0,0,0,.50);
+}
+
+.op-block-contents .example {
+ margin: 0;
+ padding: 5px 20px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ hyphens: auto;
+ border-radius: 4px;
+ background: #41444e;
+ overflow-wrap: break-word;
+ font-family: monospace;
+ font-weight: 400;
+ color: limegreen;
+ display: none;
+ max-width: 800px;
+ max-height: 800px;
+ text-overflow: auto;
+ overflow: auto;
+}
+
+.op-block-contents .example.active {
+ display:block;
+}
+
+.op-block-contents .model {
+ display: none;
+}
+
+.op-block-contents .model.active {
+ display:block;
+}
+
+/*-----------------------------------------------------------------------------------------------------------
+ - Headers
+ ----------------------------------------------------------------------------------------------------------*/
+
+.section {
+ font-weight: bold;
+ padding: 5px 0;
+ text-align: left;
+}
+
+.headers .name {
+ padding: 5px 0;
+ font-family: monospace;
+ font-weight: bold;
+}
+
+div.headers {
+ margin: 20px 0px;
+}
+
+.headers .type {
+ padding: 5px 0;
+ font-family: monospace;
+ font-weight: bold;
+}
+
+.section-name {
+ display: inline-block;
+ vertical-align: top;
+ margin-right: 20px;
+ font-weight: bold;
+ padding: 5px 0;
+ text-align: left;
+}
+
+.section-table {
+/* display: inline-block;*/
+}
+
+.responses .section-table td {
+ padding: 5px 20px 5px 0px;
+ text-align: left;
+ border-bottom: 1px solid rgba(59,65,81,.2);
+}
diff --git a/juneau-petstore-server/src/main/resources/htdocs/themes/dark.css b/juneau-petstore-server/src/main/resources/htdocs/themes/dark.css
new file mode 100644
index 0000000..0a34995
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/themes/dark.css
@@ -0,0 +1,285 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************/
+
+/** Dark look-and-feel */
+
+/**********************************************************************************************************************/
+/** Body **/
+/**********************************************************************************************************************/
+
+body {
+ background-color: #212121 ;
+ margin: 0px;
+ font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
+ color: #EEE;
+ height: 100%;
+}
+
+body {
+ font-size: 14px;
+}
+
+body textarea, body pre {
+ -moz-tab-size: 3;
+ -o-tab-size: 3;
+ -webkit-tab-size: 3;
+ tab-size: 3;
+}
+
+/**********************************************************************************************************************/
+/** Header **/
+/**********************************************************************************************************************/
+
+header {
+ background-color: #373a3c;
+}
+
+header * {
+ font-size: 14px;
+ color: #B3B3B3;
+ margin: 0px;
+ text-decoration: none;
+ font-weight: normal;
+}
+
+header h1 {
+ padding: 10px 20px;
+ font-size: 16px;
+ border-bottom: 2px solid #000000;
+ color: white;
+}
+
+header h2 {
+ padding: 10px 20px;
+ font-size: 14px;
+ border-bottom: 2px solid #000000;
+}
+
+/**********************************************************************************************************************/
+/** Nav **/
+/**********************************************************************************************************************/
+
+nav {
+ margin: 10px 20px 10px 20px;
+ color: #94A3AB;
+}
+
+nav>ol {
+ list-style-type: none;
+ margin: 0px 10px;
+ padding: 0px;
+}
+
+nav>ol>li {
+ display: inline;
+}
+
+nav li:not(:first-child):before {
+ content: " - ";
+}
+
+nav a {
+ font-size: 10pt;
+ color: #94A3AB;
+ text-decoration: none;
+ margin: 0px 15px;
+ text-transform: uppercase;
+ cursor: pointer;
+}
+
+nav a:active, nav a:hover {
+ color: white;
+ text-decoration: underline;
+}
+
+/**********************************************************************************************************************/
+/** Content **/
+/**********************************************************************************************************************/
+
+section {
+ display: table;
+ width: 100%;
+}
+
+article {
+ display: table-cell;
+}
+
+article * {
+ font-size: 9pt;
+ color: #EEE;
+}
+
+article textarea, article input, article button {
+ color: #111;
+}
+
+article textarea, article input {
+ background-color: #EEE;
+}
+
+article div.data {
+ padding: 10px;
+ background-color: #373a3c;
+ border-radius: 4px;
+ margin: 20px;
+ display: inline-block;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ font-family: sans-serif;
+}
+
+article table {
+ border: none;
+ width: 100%;
+}
+
+article th {
+ padding: 4px 8px;
+ font-weight: normal;
+ text-align: center;
+ background-color: #0275d8;
+}
+
+article td {
+ vertical-align: top;
+ border-bottom: 1px solid #000000;
+ border-right: 1px solid #000000;
+ padding: 2px 5px;
+}
+
+article td:last-child {
+ width: 100%;
+}
+
+article ul {
+ margin: 0px;
+ padding-left: 20px;
+}
+
+article a {
+ color: #3d8bb5;
+ text-decoration: none;
+}
+
+article a:hover {
+ text-decoration: underline;
+}
+
+article iframe {
+ background-color: #F6F7F9;
+ border: 1px solid gray;
+ padding: 0px;
+ overflow: hidden;
+ width: 100%;
+ min-height: 400px;
+}
+
+aside {
+ display: table-cell;
+ vertical-align: top;
+ padding: 20px 20px;
+}
+
+/**********************************************************************************************************************/
+/** Footer **/
+/**********************************************************************************************************************/
+
+footer {
+ padding: 10px;
+ width: 100%;
+ bottom: 0;
+ position: fixed;
+ background-color: #373a3c;
+ border-top: 2px solid #000000;
+}
+
+/**********************************************************************************************************************/
+/** Popup windows **/
+/**********************************************************************************************************************/
+
+.popup-content {
+ display: none;
+ position: absolute;
+ background-color: #DDD;
+ white-space: nowrap;
+ padding: 5px;
+ box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
+ z-index: 1;
+ margin-top: 10px;
+ border-radius: 4px;
+}
+
+.popup-content * {
+ color: black;
+ font-size: 11px;
+}
+
+.popup-content a:hover {
+ color: #94A3AB;
+}
+
+.popup-show {
+ display:block;
+}
+
+/**********************************************************************************************************************/
+/** Tooltips **/
+/**********************************************************************************************************************/
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip .tooltiptext {
+ visibility: hidden;
+ background-color: #FEF9E7;
+ color: black;
+ padding: 5px;
+ border-radius: 6px;
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ margin-left: 30px;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ opacity: 0;
+ transition: opacity 0.5s;
+ font-weight: normal;
+}
+
+.tooltip .tooltiptext * {
+ color: black;
+}
+
+.tooltip:hover .tooltiptext {
+ visibility: visible;
+ opacity: 1;
+}
+
+.tooltiptext {
+ white-space: nowrap;
+ float: left;
+ border: 1px solid black;
+}
+
+/**********************************************************************************************************************/
+/** Other classes **/
+/**********************************************************************************************************************/
+
+.table {display:table;}
+.row {display:table-row;}
+.cell {display:table-cell;}
+.monospace {font-family:monospace;}
+.link { color: #94A3AB; text-decoration: none; cursor: pointer;}
+.link:hover { text-decoration: underline; }
diff --git a/juneau-petstore-server/src/main/resources/htdocs/themes/devops.css b/juneau-petstore-server/src/main/resources/htdocs/themes/devops.css
new file mode 100644
index 0000000..d757a92
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/themes/devops.css
@@ -0,0 +1,275 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************/
+
+/** DevOps look-and-feel */
+
+/**********************************************************************************************************************/
+/** Body **/
+/**********************************************************************************************************************/
+
+body {
+ background-color: #3B4B54;
+ margin: 0px;
+ font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
+ color: #B3B3B3;
+ height: 100%;
+}
+
+body {
+ font-size: 14px;
+}
+
+body textarea, body pre {
+ -moz-tab-size: 3;
+ -o-tab-size: 3;
+ -webkit-tab-size: 3;
+ tab-size: 3;
+}
+
+/**********************************************************************************************************************/
+/** Header **/
+/**********************************************************************************************************************/
+
+header {
+ background-color: #26343F;
+}
+
+header * {
+ font-size: 14px;
+ color: #B3B3B3;
+ margin: 0px;
+ text-decoration: none;
+ font-weight: normal;
+}
+
+header h1 {
+ padding: 10px 20px;
+ font-size: 16px;
+ border-bottom: 2px solid #34534B;
+ color: white;
+}
+
+header h2 {
+ padding: 10px 20px;
+ font-size: 14px;
+ border-bottom: 2px solid #34534B;
+}
+
+/**********************************************************************************************************************/
+/** Nav **/
+/**********************************************************************************************************************/
+
+nav {
+ margin: 10px 20px 10px 20px;
+ color: #94A3AB;
+}
+
+nav>ol {
+ list-style-type: none;
+ margin: 0px 10px;
+ padding: 0px;
+}
+
+nav>ol>li {
+ display: inline;
+}
+
+nav li:not(:first-child):before {
+ content: " - ";
+}
+
+nav a {
+ font-size: 10pt;
+ color: #94A3AB;
+ text-decoration: none;
+ margin: 0px 15px;
+ text-transform: uppercase;
+ cursor: pointer;
+}
+
+nav a:active, nav a:hover {
+ color: white;
+ text-decoration: underline;
+}
+
+/**********************************************************************************************************************/
+/** Content **/
+/**********************************************************************************************************************/
+
+section {
+ display: table;
+ width: 100%;
+}
+
+article {
+ display: table-cell;
+}
+
+article * {
+ font-size: 9pt;
+ color: #26343F;
+}
+
+article div.data {
+ padding: 10px;
+ background-color: white;
+ border-radius: 4px;
+ margin: 20px;
+ display: inline-block;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ font-family: sans-serif;
+ color: #26343F;
+}
+
+article table {
+ border: none;
+ width: 100%;
+}
+
+article th {
+ border-top: 1px solid #D9DCDE;
+ padding: 4px 8px;
+ font-weight: bold;
+ text-align: center;
+ background-color: #F4F6F9;
+}
+
+article td {
+ vertical-align: top;
+ border-bottom: 1px solid #d9dcde;
+ border-right: 1px solid #d9dcde;
+ padding: 2px 5px;
+}
+
+article td:last-child {
+ width: 100%;
+}
+
+article ul {
+ margin: 0px;
+ padding-left: 20px;
+}
+
+article a {
+ color: #116998;
+ text-decoration: none;
+}
+
+article a:hover {
+ text-decoration: underline;
+}
+
+article iframe {
+ background-color: #F6F7F9;
+ border: 1px solid gray;
+ padding: 0px;
+ overflow: hidden;
+ width: 100%;
+ min-height: 400px;
+}
+
+aside {
+ display: table-cell;
+ vertical-align: top;
+ padding: 20px 20px;
+}
+
+/**********************************************************************************************************************/
+/** Footer **/
+/**********************************************************************************************************************/
+
+footer {
+ padding: 10px;
+ width: 100%;
+ bottom: 0;
+ position: fixed;
+ background-color: #26343F;
+}
+
+/**********************************************************************************************************************/
+/** Popup windows **/
+/**********************************************************************************************************************/
+
+.popup-content {
+ display: none;
+ position: absolute;
+ background-color: #f4f6f9;
+ white-space: nowrap;
+ padding: 5px;
+ box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
+ z-index: 1;
+ margin-top: 10px;
+ border-radius: 4px;
+}
+
+.popup-content * {
+ color: black;
+ font-size: 11px;
+}
+
+.popup-content a:hover {
+ color: #94A3AB;
+}
+
+.popup-show {
+ display:block;
+}
+
+/**********************************************************************************************************************/
+/** Tooltips **/
+/**********************************************************************************************************************/
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip .tooltiptext {
+ visibility: hidden;
+ background-color: #FEF9E7;
+ color: black;
+ padding: 5px;
+ border-radius: 6px;
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ margin-left: 30px;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ opacity: 0;
+ transition: opacity 0.5s;
+ font-weight: normal;
+}
+
+.tooltip:hover .tooltiptext {
+ visibility: visible;
+ opacity: 1;
+}
+
+.tooltiptext {
+ white-space: nowrap;
+ float: left;
+ border: 1px solid black;
+}
+
+/**********************************************************************************************************************/
+/** Other classes **/
+/**********************************************************************************************************************/
+
+.table {display:table;}
+.row {display:table-row;}
+.cell {display:table-cell;}
+.monospace {font-family:monospace;}
+.link { color: #94A3AB; text-decoration: none; cursor: pointer;}
+.link:hover { text-decoration: underline; }
+
diff --git a/juneau-petstore-server/src/main/resources/htdocs/themes/light.css b/juneau-petstore-server/src/main/resources/htdocs/themes/light.css
new file mode 100644
index 0000000..3875da3
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/themes/light.css
@@ -0,0 +1,272 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************/
+
+/** Light look-and-feel */
+
+/**********************************************************************************************************************/
+/** Body **/
+/**********************************************************************************************************************/
+
+body {
+ margin: 0px;
+ font-size: 10px;
+ font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
+ color: #2c4557;
+ height: 100%;
+}
+
+body * {
+ font-size: 14px;
+}
+
+body textarea, body pre {
+ -moz-tab-size: 3;
+ -o-tab-size: 3;
+ -webkit-tab-size: 3;
+ tab-size: 3;
+}
+
+/**********************************************************************************************************************/
+/** Header **/
+/**********************************************************************************************************************/
+
+header {
+ background-color: #e8ebef;
+ padding: 10px 20px;
+ box-shadow: 5px 5px 2px #999999;
+ text-shadow: rgba(1,1,1,.2) 2px 4px 5px, rgba(125,32,191,.05) 0 -10px 30px;
+ white-space: nowrap;
+}
+
+header * {
+ color: #af2222;;
+ font-weight: lighter;
+}
+
+header h1 {
+ font-size: 18px;
+ margin: 0px;
+ padding: 2px;
+}
+
+header h2 {
+ font-size: 14px;
+ margin: 0px;
+ padding: 2px;
+}
+
+/**********************************************************************************************************************/
+/** Nav **/
+/**********************************************************************************************************************/
+
+nav {
+ margin: 10px;
+ padding: 5px;
+ box-shadow: 5px 5px 2px #999999;
+ background-color: #eef3f7;
+}
+
+nav * {
+ font-size: 12px;
+ font-weight: lighter;
+}
+
+nav>ol {
+ list-style-type: none;
+ margin: 0px 10px;
+ padding: 0px;
+}
+
+nav>ol>li {
+ display: inline;
+}
+
+nav li:not(:first-child):before {
+ content: " - ";
+}
+
+nav a {
+ font-size: 10pt;
+ color: #2c4557;
+ text-decoration: none;
+ margin: 0px 10px;
+ text-transform: uppercase;
+ cursor: pointer;
+}
+
+nav a:active, nav a:hover {
+ text-decoration: none;
+ color: #94a3ab;
+}
+
+/**********************************************************************************************************************/
+/** Content **/
+/**********************************************************************************************************************/
+
+section {
+ display: table;
+ width: 100%;
+}
+
+article {
+ display: table-cell;
+ padding: 20px 40px;
+}
+
+article * {
+ font-size: 9pt;
+}
+
+article div.data {
+ padding: 0px;
+ margin: 0px;
+ display: inline-block;
+ font-family: sans-serif;
+}
+
+article table {
+ border: none;
+ width: 100%;
+}
+
+article td {
+ vertical-align: top;
+ border-bottom: 1px solid #d9dcde;
+ border-right: 1px solid #d9dcde;
+ padding: 2px 5px;
+}
+
+article td:last-child {
+ width: 100%;
+}
+
+article th {
+ padding: 4px 8px;
+ text-align: center;
+ background-color: #eef3f7;
+ box-shadow: 1px 1px 2px #999999;
+}
+
+article ul {
+ margin: 0px;
+ padding-left: 20px;
+}
+
+article a {
+ color: #416e8e;
+ text-decoration: none;
+}
+
+article iframe {
+ background-color: #F6F7F9;
+ border: 1px solid gray;
+ padding: 0px;
+ overflow: hidden;
+ width: 100%;
+ min-height: 400px;
+}
+
+aside {
+ display: table-cell;
+ vertical-align: top;
+ padding: 20px 20px;
+}
+
+/**********************************************************************************************************************/
+/** Footer **/
+/**********************************************************************************************************************/
+
+footer {
+ padding: 10px;
+ width: 100%;
+ bottom: 0;
+ position: fixed;
+ background-color: #e8ebef;
+}
+
+/**********************************************************************************************************************/
+/** Popup windows **/
+/**********************************************************************************************************************/
+
+.popup-content {
+ display: none;
+ position: absolute;
+ background-color: #eef3f7;
+ white-space: nowrap;
+ padding: 5px;
+ box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
+ z-index: 1;
+ margin-top: 10px;
+ border-radius: 4px;
+}
+
+.popup-content * {
+ color: #2c4557;
+ font-size: 10pt;
+}
+
+.popup-content a:hover {
+ color: #94A3AB;
+}
+
+.popup-show {
+ display: block;
+}
+
+/**********************************************************************************************************************/
+/** Tooltips **/
+/**********************************************************************************************************************/
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip .tooltiptext {
+ visibility: hidden;
+ background-color: #FEF9E7;
+ color: black;
+ padding: 5px;
+ border-radius: 6px;
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ margin-left: 30px;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ opacity: 0;
+ transition: opacity 0.5s;
+ font-weight: normal;
+}
+
+.tooltip:hover .tooltiptext {
+ visibility: visible;
+ opacity: 1;
+}
+
+.tooltiptext {
+ white-space: nowrap;
+ float: left;
+ border: 1px solid black;
+}
+
+/**********************************************************************************************************************/
+/** Other classes **/
+/**********************************************************************************************************************/
+
+.table {display:table;}
+.row {display:table-row;}
+.cell {display:table-cell;}
+.monospace {font-family:monospace;}
+.link { color: #94A3AB; text-decoration: none; cursor: pointer;}
+.link:hover { text-decoration: underline; }
diff --git a/juneau-petstore-server/src/main/resources/htdocs/themes/original.css b/juneau-petstore-server/src/main/resources/htdocs/themes/original.css
new file mode 100644
index 0000000..722feb3
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/htdocs/themes/original.css
@@ -0,0 +1,236 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations under the License. *
+ ***************************************************************************************************************************/
+
+/** Original look-and-feel */
+
+/**********************************************************************************************************************/
+/** Body **/
+/**********************************************************************************************************************/
+
+body {
+ background-image: linear-gradient(top, #CDDDDF 0, #EAEDED 20px, #FFFFFF 70px);
+ background-image: -webkit-linear-gradient(top, #CDDDDF 0, #EAEDED 20px, #FFFFFF 70px);
+ background-attachment: fixed;
+ font-family: Sans-Serif;
+ color: #2c4557;
+ height: 100%;
+ margin: 0px;
+}
+
+body * {
+ font-size: 12px;
+}
+
+body textarea, body pre {
+ -moz-tab-size: 3;
+ -o-tab-size: 3;
+ -webkit-tab-size: 3;
+ tab-size: 3;
+}
+
+/**********************************************************************************************************************/
+/** Header **/
+/**********************************************************************************************************************/
+
+header {
+ padding: 10px 20px;
+}
+
+header h1 {
+ font-size: 16px;
+ margin-bottom: 10px;
+ margin-right: 40px;
+ padding: 5px 30px;
+ border-radius: 15px;
+ text-decoration: none;
+ font-weight: normal;
+ background: linear-gradient(to bottom, #F5F5F5, #DEE3E9) repeat scroll 0% 0% transparent;
+ background: -webkit-gradient(linear, left top, left bottom, from(#F5F5F5), to(#DEE3E9));
+}
+
+header h2 {
+ font-weight: normal;
+ margin-left: 20px;
+}
+
+/**********************************************************************************************************************/
+/** Nav **/
+/**********************************************************************************************************************/
+
+nav {
+ margin: 0px 25px;
+}
+
+nav>ol {
+ list-style-type: none;
+ margin: 0px 10px;
+ padding: 0px;
+}
+
+nav>ol>li {
+ display: inline;
+}
+
+nav li:not(:first-child):before {
+ content: " - ";
+}
+
+nav a {
+ text-decoration: underline;
+ cursor: pointer;
+ color: -webkit-link;
+}
+
+/**********************************************************************************************************************/
+/** Content **/
+/**********************************************************************************************************************/
+
+section {
+ display: table;
+ width: 100%;
+}
+
+article {
+ display: table-cell;
+ padding: 20px 40px;
+}
+
+aside {
+ display: table-cell;
+ vertical-align: top;
+ padding: 20px 20px;
+}
+
+article div.data {
+ padding: 0px;
+ margin: 0px;
+ display: inline-block;
+ font-family: sans-serif;
+}
+
+article table {
+ border:1px solid #CCCC99;
+ border-collapse: collapse;
+ margin: 5px 0px;
+ width: 100%;
+}
+
+article th {
+ border-top: 1px solid #CCCC99;
+ padding: 3px 5px;
+ color: #666666;
+ text-align: center;
+ background-image: linear-gradient(top, #FBF9E4 0%, #F3F2C2 100%);
+ background-image: -webkit-linear-gradient(top, #FBF9E4 0%, #F3F2C2 100%);
+}
+
+article td {
+ border: 1px solid #E9EACB;
+ padding: 2px 5px;
+ color: #005C87;
+ vertical-align: top;
+}
+
+article td:last-child {
+ width: 100%;
+}
+
+article ul {
+ margin: 0px;
+ padding-left: 20px;
+}
+
+/**********************************************************************************************************************/
+/** Footer **/
+/**********************************************************************************************************************/
+
+footer {
+ display: none;
+}
+
+/**********************************************************************************************************************/
+/** Popup windows **/
+/**********************************************************************************************************************/
+
+.popup-content {
+ display: none;
+ position: absolute;
+ background-color: #eef3f7;
+ white-space: nowrap;
+ padding: 5px;
+ box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
+ z-index: 1;
+ margin-top: 10px;
+ border-radius: 4px;
+}
+
+.popup-content * {
+ font-size: 9pt;
+}
+
+.popup-content a:hover {
+ color: #94A3AB;
+}
+
+.popup-show {
+ display: block;
+}
+
+/**********************************************************************************************************************/
+/** Tooltips **/
+/**********************************************************************************************************************/
+
+.tooltip {
+ position: relative;
+ display: inline-block;
+}
+
+.tooltip .tooltiptext {
+ visibility: hidden;
+ background-color: #FEF9E7;
+ color: black;
+ padding: 5px;
+ border-radius: 6px;
+ position: absolute;
+ z-index: 1;
+ top: 0;
+ left: 0;
+ margin-left: 30px;
+ box-shadow: 2px 3px 3px 0px rgba(0, 0, 0, 0.5);
+ opacity: 0;
+ transition: opacity 0.5s;
+ font-weight: normal;
+}
+
+.tooltip:hover .tooltiptext {
+ visibility: visible;
+ opacity: 1;
+}
+
+.tooltiptext {
+ white-space: nowrap;
+ float: left;
+ border: 1px solid black;
+}
+
+/**********************************************************************************************************************/
+/** Other classes **/
+/**********************************************************************************************************************/
+
+.table {display:table;}
+.row {display:table-row;}
+.cell {display:table-cell;}
+.monospace {font-family:monospace;}
+.link { color: #94A3AB; text-decoration: none; cursor: pointer;}
+.link:hover { text-decoration: underline; }
+
diff --git a/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Orders.json b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Orders.json
new file mode 100644
index 0000000..b306aa8
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Orders.json
@@ -0,0 +1,18 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+
+[
+ {id:101,petId:101,shipDate:'2018-01-01',status:'PLACED'},
+ {id:102,petId:102,shipDate:'2018-01-01',status:'APPROVED'},
+ {id:103,petId:103,shipDate:'2018-01-01',status:'DELIVERED'}
+]
diff --git a/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Pets.json b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Pets.json
new file mode 100644
index 0000000..c0aa31f
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Pets.json
@@ -0,0 +1,24 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+
+[
+ {species:'CAT', name:'Mr. Frisky', price:39.99, tags:['friendly'], status:'AVAILABLE'},
+ {species:'DOG', name:'Kibbles', price:99.99, tags:['loyal'], status:'AVAILABLE'},
+ {species:'RABBIT', name:'Hoppy', price:49.99, tags:['friendly','smells nice'], status:'AVAILABLE'},
+ {species:'RABBIT', name:'Hoppy 2', price:49.99, status:'AVAILABLE'},
+ {species:'RABBIT', name:'Hoppy 3', price:49.99, status:'AVAILABLE'},
+ {species:'RABBIT', name:'Hoppy 4', price:49.99, status:'AVAILABLE'},
+ {species:'FISH', name:'Gorton', price:1.99, status:'PENDING'},
+ {species:'MOUSE', name:'Hackwrench', price:4.99, status:'SOLD'},
+ {species:'SNAKE', name:'Just Snake', price:9.99, status:'SOLD'}
+]
\ No newline at end of file
diff --git a/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Users.json b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Users.json
new file mode 100644
index 0000000..7f02a3c
--- /dev/null
+++ b/juneau-petstore-server/src/main/resources/org/apache/juneau/petstore/service/init/Users.json
@@ -0,0 +1,18 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
+// * with the License. You may obtain a copy of the License at *
+// * *
+// * http://www.apache.org/licenses/LICENSE-2.0 *
+// * *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
+// * specific language governing permissions and limitations under the License. *
+// ***************************************************************************************************************************
+
+[
+ {username:'mwatson',firstName:'Marie',lastName:'Watson',email:'marie.watson@fakemail.com',password:'123456',phone:'444-555-7777',userStatus:'ACTIVE'},
+ {username:'dvaughn',firstName:'Daniel',lastName:'Vaughn',email:'daniel.vaughn@test.com',password:'123456',phone:'666-777-3333',userStatus:'ACTIVE'},
+ {username:'bfuller',firstName:'Brenda',lastName:'Fuller',email:'brenda.fuller@example.com',password:'123456',phone:'777-888-3333',userStatus:'INACTIVE'}
+]
diff --git a/juneau-petstore-server/src/test/java/org/apache/juneau/petstore/test/MockTest.java b/juneau-petstore-server/src/test/java/org/apache/juneau/petstore/test/MockTest.java
index 0416b2a..29a3244 100644
--- a/juneau-petstore-server/src/test/java/org/apache/juneau/petstore/test/MockTest.java
+++ b/juneau-petstore-server/src/test/java/org/apache/juneau/petstore/test/MockTest.java
@@ -1,11 +1,10 @@
package org.apache.juneau.petstore.test;
-import java.io.IOException;
-import javax.servlet.ServletException;
import org.apache.juneau.petstore.App;
-import org.apache.juneau.petstore.repository.UserRepository;
+import org.apache.juneau.petstore.dto.*;
import org.apache.juneau.petstore.rest.PetStoreResource;
-import org.apache.juneau.rest.mock2.MockRest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -22,112 +21,99 @@
@Autowired
PetStoreResource petStoreResource;
- MockRest petStoreRest;
- UserRepository userRepository;
+
+ private RestClient petStoreRest;
@Before
public void setup() {
-
- petStoreRest = MockRest.create(petStoreResource).simpleJson().build();
-
+ // Wrap our resource in a MockRest object for testing.
+ petStoreRest = MockRestClient.create(petStoreResource).simpleJson().build();
}
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
// Pets
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- private String createTestPet() throws AssertionError, ServletException, IOException {
+ // -----------------------------------------------------------------------------------------------------------------
- String petId = petStoreRest
- .post("/pet", "{name:'Sunshine',tags:['nice'], price:100.0,species:'BIRD'}")
- .execute()
- .assertStatus(200)
- .getBodyAsString();
+ private int createTestPet() throws Exception {
+
+ int petId = petStoreRest
+ .post("/pet", new CreatePet().name("Sunshine").price(100f).species(Species.BIRD).tags("nice"))
+ .run()
+ .assertStatus().code().is(200)
+ .getBody().as(int.class);
return petId;
}
- private void deleteTestPets() throws AssertionError, ServletException, IOException {
-
+ private void deleteTestPets() throws Exception {
petStoreRest
- .delete("/pets")
- .execute()
- .assertStatus(200);
-
+ .delete("/pets")
+ .complete() // Use complete() because we're not consuming response.
+ .assertStatus().code().is(200);
}
// Delete pet by Id
-
@Test
public void testDeletePet() throws Exception {
- String petId = createTestPet();
+ int petId = createTestPet();
petStoreRest
- .delete("/pet/" + petId)
- .execute()
- .assertStatus(200);
-
+ .delete("/pet/" + petId)
+ .complete()
+ .assertStatus().code().is(200);
}
// Getting all pets
-
@Test
public void testGettingPets() throws Exception {
- String petId = createTestPet();
-
+ int petId = createTestPet();
petStoreRest
- .get("/pet")
- .execute()
- .assertStatus(200)
- .assertBody(
- "[{id:" + petId + ",species:'BIRD',name:'Sunshine',tags:['nice'],price:100.0,status:'AVAILABLE'}]");
+ .get("/pet")
+ .run()
+ .assertStatus().code().is(200)
+ .assertBody().is("[{id:" + petId + ",species:'BIRD',name:'Sunshine',price:100.0,status:'AVAILABLE'}]");
+
deleteTestPets();
}
// Posting pet
-
@Test
public void testPostPet() throws Exception {
petStoreRest
- .post("/pet", "{name:'Sunshine',tags:['nice'], price:100.0,species:'BIRD'}")
- .execute()
- .assertStatus(200);
+ .post("/pet", new CreatePet().name("Sunshine").price(100f).species(Species.BIRD).tags("nice"))
+ .complete()
+ .assertStatus().code().is(200);
deleteTestPets();
}
// Find pet by Id
-
@Test
public void testfindPet() throws Exception {
- String petId = createTestPet();
-
+ int petId = createTestPet();
petStoreRest
- .get("/pet/" + petId)
- .execute()
- .assertStatus(200)
- .assertBody(
- "{id:" + petId + ",species:'BIRD',name:'Sunshine',tags:['nice'],price:100.0,status:'AVAILABLE'}");
+ .get("/pet/" + petId)
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("{id:" + petId + ",species:'BIRD',name:'Sunshine',tags:['nice'],price:100.0,status:'AVAILABLE'}");
deleteTestPets();
}
// Find pet by status
-
@Test
- public void testfindPetByStatus() throws Exception {
+ public void testFindPetByStatus() throws Exception {
- String petId = createTestPet();
-
+ int petId = createTestPet();
petStoreRest
- .get("/pet/findByStatus?status=AVAILABLE")
- .execute()
- .assertStatus(200)
- .assertBody(
- "[{id:" + petId + ",species:'BIRD',name:'Sunshine',tags:['nice'],price:100.0,status:'AVAILABLE'}]");
+ .get("/pet/findByStatus?status=AVAILABLE")
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("[{id:" + petId + ",species:'BIRD',name:'Sunshine',tags:['nice'],price:100.0,status:'AVAILABLE'}]");
deleteTestPets();
}
@@ -137,205 +123,207 @@
@Test
public void testUpdatePet() throws Exception {
- String petId = createTestPet();
-
+ int petId = createTestPet();
petStoreRest
- .put("/pet/" + petId,
- "{id: " + petId
- + ",name:'Daisy1',price:1000.0,species:'BIRD'tags:['nice'], status:'AVAILABLE' }")
- .execute()
- .assertStatus(200);
+ .put(
+ "/pet/" + petId,
+ new UpdatePet().id(petId).name("Daisy1").price(1000f).species(Species.BIRD).status(PetStatus.AVAILABLE).tags("nice")
+ )
+ .complete()
+ .assertCode().is(200);
deleteTestPets();
-
}
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
// Users
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
- private void deleteTestUsers() throws AssertionError, ServletException, IOException {
-
+ private void deleteTestUsers() throws Exception {
petStoreRest
- .delete("/users/")
- .execute()
- .assertStatus(200);
-
+ .delete("/users/")
+ .complete()
+ .assertCode().is(200);
}
- private String createTestUser(String username) throws AssertionError, ServletException, IOException {
-
+ private String createTestUser(String username) throws Exception {
petStoreRest
- .post("/user", "{username:" + username + ",firstName: 'Tom',lastName: 'Simon', userStatus: 'ACTIVE'}")
- .execute()
- .assertStatus(200);
+ .post(
+ "/user",
+ new User().username(username).firstName("Tom").lastName("Simon").userStatus(UserStatus.ACTIVE)
+ )
+ .complete()
+ .assertCode().is(200);
return username;
}
// Create user
-
@Test
public void testCreateUser() throws Exception {
-
petStoreRest
- .post("/user", "{username:'catlover',firstName: 'Tom',lastName: 'Simon', userStatus: 'ACTIVE'}")
- .execute()
- .assertStatus(200);
+ .post(
+ "/user",
+ new User().username("catlover").firstName("Tom").lastName("Simon").userStatus(UserStatus.ACTIVE)
+ )
+ .complete()
+ .assertCode().is(200);
deleteTestUsers();
}
// Delete user
-
@Test
public void testDeleteUser() throws Exception {
petStoreRest
- .delete("/user/" + "catlover1")
- .execute()
- .assertStatus(200);
+ .delete("/user/" + "catlover1")
+ .complete()
+ .assertCode().is(200);
}
// Create list of users
-
@Test
public void testCreateUsers() throws Exception {
petStoreRest
- .post("/user/createWithArray",
- "[{username:'billy',firstName: 'Billy',lastName: 'Bob', userStatus: 'ACTIVE'},"
- + "{username:'peter',firstName: 'Peter',lastName: 'Adams', userStatus: 'ACTIVE'}]")
- .execute()
- .assertStatus(200);
+ .post(
+ "/user/createWithArray",
+ new User[] {
+ new User().username("billy").firstName("Billy").lastName("Bob").userStatus(UserStatus.ACTIVE),
+ new User().username("peter").firstName("Peter").lastName("Adams").userStatus(UserStatus.ACTIVE)
+ }
+ )
+ .complete()
+ .assertCode().is(200);
deleteTestUsers();
}
// Getting all users
-
@Test
public void testGettingUsers() throws Exception {
createTestUser("doglover");
petStoreRest
- .get("/user")
- .execute()
- .assertStatus(200)
- .assertBody("[{username:'doglover',firstName:'Tom',lastName:'Simon',userStatus:'ACTIVE'}]");
+ .get("/user")
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("[{username:'doglover',firstName:'Tom',lastName:'Simon',userStatus:'ACTIVE'}]");
deleteTestUsers();
}
// Get user by user name
-
@Test
public void testFindUserByName() throws Exception {
createTestUser("garfield");
petStoreRest
- .get("/user/garfield")
- .execute()
- .assertStatus(200)
- .assertBody("{username:'garfield',firstName:'Tom',lastName:'Simon',userStatus:'ACTIVE'}");
+ .get("/user/garfield")
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("{username:'garfield',firstName:'Tom',lastName:'Simon',userStatus:'ACTIVE'}");
deleteTestUsers();
}
// Updating user
-
@Test
public void testUpdateUser() throws Exception {
createTestUser("snoopy");
petStoreRest
- .put("/user/snoopy", "{username:'snoopy',phone: '34562345'}")
- .execute()
- .assertStatus(200);
+ .put(
+ "/user/snoopy",
+ new User().username("snoopy").phone("34562345")
+ )
+ .complete()
+ .assertCode().is(200);
deleteTestUsers();
}
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ // -----------------------------------------------------------------------------------------------------------------
// Orders
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- private void deleteTestOrders() throws AssertionError, ServletException, IOException {
+ // -----------------------------------------------------------------------------------------------------------------
+ private void deleteTestOrders() throws Exception {
petStoreRest
- .delete("/orders")
- .execute()
- .assertStatus(200);
-
+ .delete("/orders")
+ .complete()
+ .assertCode().is(200);
}
- private String createTestOrder() throws AssertionError, ServletException, IOException {
+ private int createTestOrder() throws Exception {
- String petId = createTestPet();
- String orderId = petStoreRest
- .post("/store/order", "{petId:" + petId + " + ,username: 'catlover'}")
- .execute()
- .assertStatus(200)
- .getBodyAsString();
+ int petId = createTestPet();
+ int orderId = petStoreRest
+ .post(
+ "/store/order",
+ new CreateOrder().petId(petId).username("catlover")
+ )
+ .run()
+ .assertCode().is(200)
+ .getBody().as(int.class);
return orderId;
}
// Posting order
-
@Test
public void testPostOrder() throws Exception {
petStoreRest
- .post("/store/order", "{petId:'1',username: 'snoopy'}")
- .execute()
- .assertStatus(200);
+ .post(
+ "/store/order",
+ new CreateOrder().petId(1).username("snoopy")
+ )
+ .complete()
+ .assertCode().is(200);
deleteTestOrders();
}
// Getting all orders
-
@Test
public void testGettingOrders() throws Exception {
- String orderId = createTestOrder();
+ int orderId = createTestOrder();
petStoreRest
- .get("/store/order")
- .execute()
- .assertStatus(200)
- .assertBody("[{id:" + orderId + ",petId:0,status:'PLACED'}]");
+ .get("/store/order")
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("[{id:" + orderId + ",petId:0,status:'PLACED'}]");
deleteTestOrders();
}
// Find order by Id
-
@Test
public void testfindOrder() throws Exception {
- String orderId = createTestOrder();
+ int orderId = createTestOrder();
petStoreRest
- .get("/store/order/" + orderId)
- .execute()
- .assertStatus(200)
- .assertBody("{id:" + orderId + ",petId:0,status:'PLACED'}");
+ .get("/store/order/" + orderId)
+ .run()
+ .assertCode().is(200)
+ .assertBody().is("{id:" + orderId + ",petId:0,status:'PLACED'}");
deleteTestOrders();
}
// Delete order by Id
-
@Test
public void testDeleteOrder() throws Exception {
- String orderId = createTestOrder();
+ int orderId = createTestOrder();
petStoreRest
- .delete("/store/order/" + orderId)
- .execute()
- .assertStatus(200);
-
+ .delete("/store/order/" + orderId)
+ .complete()
+ .assertCode().is(200);
}
}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 32a0465..bb1c4d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,7 +38,7 @@
<junit.version>4.11</junit.version>
<servlet.version>3.1.0</servlet.version>
<httpclient.version>4.5.6</httpclient.version>
- <juneau.version>8.1.2</juneau.version>
+ <juneau.version>8.2.0</juneau.version>
<derby.version>10.10.2.0</derby.version>
<hibernate.version>5.0.9.Final</hibernate.version>
<javax.inject.version>1</javax.inject.version>