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.