You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/04/16 23:06:59 UTC
[juneau] branch master updated: PetStore improvements.
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
The following commit(s) were added to refs/heads/master by this push:
new 7a91424 PetStore improvements.
7a91424 is described below
commit 7a91424e2c611c46d32b5ead6df94c5b0d4dd3bd
Author: JamesBognar <ja...@apache.org>
AuthorDate: Mon Apr 16 19:06:58 2018 -0400
PetStore improvements.
---
.../main/java/org/apache/juneau/utils/IdMap.java | 8 +
.../juneau/examples/rest/PetStoreResource.java | 246 ---------------------
.../apache/juneau/examples/rest/RootResources.java | 2 +-
.../rest/petstore/{Order.java => CreateOrder.java} | 61 ++---
.../juneau/examples/rest/petstore/Order.java | 10 +-
.../juneau/examples/rest/petstore/PetStore.java | 43 +++-
.../examples/rest/petstore/PetStoreResource.java | 21 +-
7 files changed, 84 insertions(+), 307 deletions(-)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdMap.java
index a41a6a9..11a7c4e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdMap.java
@@ -95,4 +95,12 @@ public class IdMap<K,V> extends ConcurrentHashMap<K,V> {
public K nextId() {
return idGen.next();
}
+
+ /**
+ * Sets a lower bound on the specified ID.
+ * @param k The lower-bound key.
+ */
+ public void lbId(K k) {
+ idGen.lb(k);
+ }
}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
deleted file mode 100644
index ec57bd1..0000000
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java
+++ /dev/null
@@ -1,246 +0,0 @@
-// ***************************************************************************************************************************
-// * 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. *
-// ***************************************************************************************************************************
-package org.apache.juneau.examples.rest;
-
-import static org.apache.juneau.dto.html5.HtmlBuilder.*;
-import static org.apache.juneau.http.HttpMethodName.*;
-import static org.apache.juneau.rest.annotation.HookEvent.*;
-
-import java.util.*;
-import java.util.Map;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.dto.html5.*;
-import org.apache.juneau.html.*;
-import org.apache.juneau.html.annotation.Html;
-import org.apache.juneau.json.*;
-import org.apache.juneau.microservice.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.annotation.Body;
-import org.apache.juneau.rest.converters.*;
-import org.apache.juneau.rest.helper.*;
-import org.apache.juneau.rest.widget.*;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.transforms.*;
-
-/**
- * Sample REST resource that renders summary and detail views of the same bean.
- */
-@RestResource(
- title="Pet Store",
- description="An example of a typical REST resource where beans are rendered in summary and details views.",
- path="/petstore",
- htmldoc=@HtmlDoc(
- widgets={
- ContentTypeMenuItem.class,
- ThemeMenuItem.class,
- PetStoreResource.AddPet.class
- },
- navlinks={
- "up: request:/..",
- "options: servlet:/?method=OPTIONS",
- "$W{ContentTypeMenuItem}",
- "$W{ThemeMenuItem}",
- "source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java",
- "$W{AddPet}"
- },
- aside={
- "<div style='max-width:400px' class='text'>",
- " <p>This page shows a standard REST resource that renders bean summaries and details.</p>",
- " <p>It shows how different properties can be rendered on the same bean in different views.</p>",
- " <p>It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.</p>",
- " <p>It also shows how the Queryable converter and query widget can be used to create searchable interfaces.</p>",
- "</div>"
- },
- head={
- "<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>"
- }
- ),
- staticFiles={"htdocs:htdocs"}
-)
-public class PetStoreResource extends BasicRestServletJena {
- private static final long serialVersionUID = 1L;
-
- // Our database.
- private Map<Integer,Pet> petDB;
-
- /**
- * Initializes the pet store database.
- *
- * @param builder The resource config.
- * @throws Exception
- */
- @RestHook(INIT)
- public void initDatabase(RestContextBuilder builder) throws Exception {
- // Load our database from a local JSON file.
- petDB = JsonParser.DEFAULT.parse(getClass().getResourceAsStream("PetStore.json"), LinkedHashMap.class, Integer.class, Pet.class);
- }
-
- // Exclude the 'breed' and 'getsAlongWith' properties from the beans.
- @RestMethod(
- name=GET,
- path="/",
- summary="The complete list of pets in the store",
- bpx="Pet: breed,getsAlongWith",
-
- // Add our converter for POJO query support.
- converters=Queryable.class,
-
- // Add our menu items in the nav links.
- htmldoc=@HtmlDoc(
-
- widgets={
- QueryMenuItem.class,
- ContentTypeMenuItem.class,
- ThemeMenuItem.class
- },
-
- navlinks={
- "INHERIT", // Inherit links from class.
- "[2]:$W{QueryMenuItem}" // Insert QUERY link in position 2.
- }
- )
- )
- public Collection<Pet> getPets() {
- return petDB.values();
- }
-
- // Shows all bean properties.
- @RestMethod(name=GET, path="/{id}", summary="Pet details")
- public Pet getPet(@Path("id") Integer id) {
- return petDB.get(id);
- }
-
- @RestMethod(name=POST, path="/")
- public Redirect addPet(@Body Pet pet) throws Exception {
- this.petDB.put(pet.id, pet);
- return new Redirect("servlet:/");
- }
-
- // Our bean class.
- public static class Pet {
-
- @Html(link="servlet:/{id}") // Creates a hyperlink in HTML view.
- @NameProperty // Links the parent key to this bean.
- public int id;
-
- public String name;
- public Kind kind;
- public String breed;
- public List<Kind> getsAlongWith;
-
- @BeanProperty(format="$%.2f") // Renders price in dollars.
- public float price;
-
- @Swap(DateSwap.ISO8601D.class) // Renders dates in ISO8601 format.
- public Date birthDate;
-
- public int getAge() {
- Calendar c = new GregorianCalendar();
- c.setTime(birthDate);
- return new GregorianCalendar().get(Calendar.YEAR) - c.get(Calendar.YEAR);
- }
- }
-
- @Html(render=KindRender.class) // Render as an icon in HTML.
- public static enum Kind {
- CAT, DOG, BIRD, FISH, MOUSE, RABBIT, SNAKE
- }
-
- public static class KindRender extends HtmlRender<Kind> {
- @Override
- public Object getContent(SerializerSession session, Kind value) {
- return new Img().src("servlet:/htdocs/"+value.toString().toLowerCase()+".png");
- }
- @Override
- public String getStyle(SerializerSession session, Kind value) {
- return "background-color:#FDF2E9";
- }
- }
-
- /**
- * Renders the "ADD" menu item.
- */
- public class AddPet extends MenuItemWidget {
-
- @Override
- public String getLabel(RestRequest req) throws Exception {
- return "add";
- }
-
- @Override
- public Object getContent(RestRequest req) throws Exception {
- return div(
- form().id("form").action("servlet:/").method(POST).children(
- table(
- tr(
- th("ID:"),
- td(input().name("id").type("number").value(getNextAvailableId())),
- td(new Tooltip("(?)", "A unique identifer for the pet.", br(), "Must not conflict with existing IDs"))
- ),
- tr(
- th("Name:"),
- td(input().name("name").type("text")),
- td(new Tooltip("(?)", "The name of the pet.", br(), "e.g. 'Fluffy'"))
- ),
- tr(
- th("Kind:"),
- td(
- select().name("kind").children(
- option("CAT"), option("DOG"), option("BIRD"), option("FISH"), option("MOUSE"), option("RABBIT"), option("SNAKE")
- )
- ),
- td(new Tooltip("(?)", "The kind of animal."))
- ),
- tr(
- th("Breed:"),
- td(input().name("breed").type("text")),
- td(new Tooltip("(?)", "The breed of animal.", br(), "Can be any arbitrary text"))
- ),
- tr(
- th("Gets along with:"),
- td(input().name("getsAlongWith").type("text")),
- td(new Tooltip("(?)", "A comma-delimited list of other animal types that this animal gets along with."))
- ),
- tr(
- th("Price:"),
- td(input().name("price").type("number").placeholder("1.0").step("0.01").min(1).max(100)),
- td(new Tooltip("(?)", "The price to charge for this pet."))
- ),
- tr(
- th("Birthdate:"),
- td(input().name("birthDate").type("date")),
- td(new Tooltip("(?)", "The pets birthday."))
- ),
- tr(
- td().colspan(2).style("text-align:right").children(
- button("reset", "Reset"),
- button("button","Cancel").onclick("window.location.href='/'"),
- button("submit", "Submit")
- )
- )
- ).style("white-space:nowrap")
- )
- );
- }
- }
-
- final int getNextAvailableId() {
- int i = 100;
- for (Integer k : petDB.keySet())
- i = Math.max(i, k);
- return i+1;
- }
-}
-
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
index fc35343..bbdeafe 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
@@ -15,6 +15,7 @@ package org.apache.juneau.examples.rest;
import static org.apache.juneau.serializer.WriterSerializer.*;
import org.apache.juneau.examples.rest.addressbook.*;
+import org.apache.juneau.examples.rest.petstore.*;
import org.apache.juneau.microservice.*;
import org.apache.juneau.microservice.resources.*;
import org.apache.juneau.rest.annotation.*;
@@ -58,7 +59,6 @@ import org.apache.juneau.rest.widget.*;
children={
HelloWorldResource.class,
PetStoreResource.class,
- org.apache.juneau.examples.rest.petstore.PetStoreResource.class,
SystemPropertiesResource.class,
MethodExampleResource.class,
RequestEchoResource.class,
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreateOrder.java
similarity index 69%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreateOrder.java
index 43139e0..5bc4bca 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreateOrder.java
@@ -13,60 +13,35 @@
package org.apache.juneau.examples.rest.petstore;
import org.apache.juneau.annotation.*;
-import org.apache.juneau.html.annotation.*;
-@Bean(fluentSetters=true, properties="id,petId,quantity,shipDate,status")
-@Example("{id:123,petId:456,quantity:100,shipDate:'2012-12-21',status:'APPROVED'}")
-public class Order {
- private long id, petId;
- private int quantity;
- private String shipDate;
- private OrderStatus status;
-
- public long getId() {
- return id;
+/**
+ * Bean for creating {@link Order} objects.
+ */
+public class CreateOrder {
+ private final long petId;
+ private final int quantity;
+ private final String shipDate;
+
+ @BeanConstructor(properties="petId,quantity,shipDate")
+ public CreateOrder(long petId, int quantity, String shipDate) {
+ this.petId = petId;
+ this.quantity = quantity;
+ this.shipDate = shipDate;
}
- @Html(link="servlet:/store/order/{id}")
- public Order id(long id) {
- this.id = id;
- return this;
+ public static CreateOrder example() {
+ return new CreateOrder(123, 10, "2012-12-21");
}
-
- @Html(link="servlet:/pet/{id}")
+
public long getPetId() {
return petId;
}
-
- public Order petId(long petId) {
- this.petId = petId;
- return this;
- }
-
+
public int getQuantity() {
return quantity;
}
-
- public Order quantity(int quantity) {
- this.quantity = quantity;
- return this;
- }
-
+
public String getShipDate() {
return shipDate;
}
-
- public Order shipDate(String shipDate) {
- this.shipDate = shipDate;
- return this;
- }
-
- public OrderStatus getStatus() {
- return status;
- }
-
- public Order status(OrderStatus status) {
- this.status = status;
- return this;
- }
}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
index 43139e0..9886fc1 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
@@ -12,15 +12,18 @@
// ***************************************************************************************************************************
package org.apache.juneau.examples.rest.petstore;
+import java.util.*;
+
import org.apache.juneau.annotation.*;
import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.transforms.*;
@Bean(fluentSetters=true, properties="id,petId,quantity,shipDate,status")
@Example("{id:123,petId:456,quantity:100,shipDate:'2012-12-21',status:'APPROVED'}")
public class Order {
private long id, petId;
private int quantity;
- private String shipDate;
+ private Date shipDate;
private OrderStatus status;
public long getId() {
@@ -52,11 +55,12 @@ public class Order {
return this;
}
- public String getShipDate() {
+ @Swap(DateSwap.ISO8601D.class)
+ public Date getShipDate() {
return shipDate;
}
- public Order shipDate(String shipDate) {
+ public Order shipDate(Date shipDate) {
this.shipDate = shipDate;
return this;
}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
index c7bae5f..7c786f2 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
@@ -17,6 +17,7 @@ import java.util.*;
import java.util.concurrent.*;
import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.transform.*;
import org.apache.juneau.utils.*;
@@ -143,6 +144,8 @@ public class PetStore {
public Pet add(Pet value) throws IdConflict {
if (value.getId() == 0)
value.id(petDb.nextId());
+ else
+ petDb.lbId(value.getId());
Pet old = petDb.putIfAbsent(value.getId(), value);
if (old != null)
throw new IdConflict(value.getId(), Pet.class);
@@ -184,6 +187,39 @@ public class PetStore {
return value;
}
+ public Pet create(CreatePet c) {
+ Pet p = new Pet();
+ p.name(c.getName());
+ p.price(c.getPrice());
+ p.species(getSpecies(c.getName()));
+ p.tags(getTags(c.getTags()));
+ p.status(c.getStatus());
+ return add(p);
+ }
+
+ public Order create(CreateOrder c) {
+ Order o = new Order();
+ o.petId(c.getPetId());
+ o.quantity(c.getQuantity());
+ o.shipDate(StringUtils.parseISO8601Date(c.getShipDate()));
+ o.status(OrderStatus.PLACED);
+ return add(o);
+ }
+
+ private List<Tag> getTags(List<String> tags) {
+ List<Tag> l = new ArrayList<>();
+ for (String t : tags)
+ l.add(getOrCreateTag(t));
+ return l;
+ }
+
+ private Tag getOrCreateTag(String name) {
+ for (Tag t : tagDb.values())
+ if (t.getName().equals(name))
+ return t;
+ return add(new Tag().name(name));
+ }
+
public Pet update(Pet value) throws IdNotFound {
Pet old = petDb.replace(value.getId(), value);
if (old == null)
@@ -191,13 +227,6 @@ public class PetStore {
return value;
}
- public Species update(Species value) throws IdNotFound {
- Species old = speciesDb.replace(value.getId(), value);
- if (old == null)
- throw new IdNotFound(value.getId(), Species.class);
- return value;
- }
-
public Order update(Order value) throws IdNotFound {
Order old = orderDb.replace(value.getId(), value);
if (old == null)
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
index 1e130fe..dd490d6 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
@@ -31,8 +31,8 @@ import org.apache.juneau.rest.converters.*;
* Sample resource that shows how to generate ATOM feeds.
*/
@RestResource(
- path="/petstore2",
- title="Swagger Petstore",
+ path="/petstore",
+ title="Petstore application",
description=
"This is a sample server Petstore server based on the Petstore sample at Swagger.io."
+ "<br>You can find out more about Swagger at <a class='link' href='http://swagger.io'>http://swagger.io</a>.",
@@ -55,6 +55,14 @@ import org.apache.juneau.rest.converters.*;
"<h1>$R{resourceTitle}</h1>",
"<h2>$R{methodSummary}</h2>",
"$C{PetStore/headerImage}"
+ },
+ aside={
+ "<div style='max-width:400px' class='text'>",
+ " <p>This page shows a standard nested REST resource.</p>",
+ " <p>It shows how different properties can be rendered on the same bean in different views.</p>",
+ " <p>It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.</p>",
+ " <p>It also shows how the Queryable converter and query widget can be used to create searchable interfaces.</p>",
+ "</div>"
}
),
properties= {
@@ -107,7 +115,6 @@ public class PetStoreResource extends BasicRestServletJena {
QueryMenuItem.class,
AddPetMenuItem.class
},
-
navlinks={
"INHERIT", // Inherit links from class.
"[2]:$W{QueryMenuItem}", // Insert QUERY link in position 2.
@@ -147,10 +154,10 @@ public class PetStoreResource extends BasicRestServletJena {
}
)
public Ok addPet(
- @Body(description="Pet object that needs to be added to the store") Pet pet
+ @Body(description="Pet object that needs to be added to the store") CreatePet pet
) throws IdConflict, NotAcceptable, UnsupportedMediaType {
- store.add(pet);
+ store.create(pet);
return OK;
}
@@ -331,10 +338,10 @@ public class PetStoreResource extends BasicRestServletJena {
}
)
public Order placeOrder(
- @Body(description="Order placed for purchasing the pet", example="{petId:456,quantity:100}") Order order
+ @Body(description="Order placed for purchasing the pet", example="{petId:456,quantity:100}") CreateOrder order
) throws IdConflict, NotAcceptable, UnsupportedMediaType {
- return store.add(order);
+ return store.create(order);
}
@RestMethod(
--
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.