From 3306ea56f39184cd813cc0e6e7f14a4789cbcdf7 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 25 Mar 2015 10:41:38 +0100 Subject: [PATCH] Turned Starbucks client into test. Allows us to benefit from default logging setup. Removed obsolete Tomcat version declaration. Polished StoreInitializer to use Lambdas instead of an enum. --- rest/pom.xml | 4 - .../main/java/example/orders/LineItem.java | 8 +- .../example/orders/SimpleProjectionTests.java | 80 +++++++++++++++++++ .../java/example/stores/StoreInitializer.java | 32 +++----- .../java/example/stores/StarbucksClient.java | 38 +++++++-- 5 files changed, 127 insertions(+), 35 deletions(-) create mode 100644 rest/projections/src/test/java/example/orders/SimpleProjectionTests.java rename rest/starbucks/src/{main => test}/java/example/stores/StarbucksClient.java (64%) diff --git a/rest/pom.xml b/rest/pom.xml index 62507429..ac7c856f 100644 --- a/rest/pom.xml +++ b/rest/pom.xml @@ -21,10 +21,6 @@ security - - 8.0.15 - - org.springframework.boot diff --git a/rest/projections/src/main/java/example/orders/LineItem.java b/rest/projections/src/main/java/example/orders/LineItem.java index 9efbf9b2..771002ec 100644 --- a/rest/projections/src/main/java/example/orders/LineItem.java +++ b/rest/projections/src/main/java/example/orders/LineItem.java @@ -21,14 +21,18 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.RequiredArgsConstructor; +import lombok.ToString; /** * @author Oliver Gierke */ @Entity -@Data +@Getter +@EqualsAndHashCode(of = "id") +@ToString @RequiredArgsConstructor public class LineItem { diff --git a/rest/projections/src/test/java/example/orders/SimpleProjectionTests.java b/rest/projections/src/test/java/example/orders/SimpleProjectionTests.java new file mode 100644 index 00000000..5dd642c9 --- /dev/null +++ b/rest/projections/src/test/java/example/orders/SimpleProjectionTests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed 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 example.orders; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.projection.ProjectionFactory; +import org.springframework.data.projection.SpelAwareProxyProjectionFactory; + +/** + * Test cases showing the programatic use of a {@link ProjectionFactory}. + * + * @author Oliver Gierke + */ +public class SimpleProjectionTests { + + ProjectionFactory factory = new SpelAwareProxyProjectionFactory(); + + @Test + public void createMapBackedProjection() { + + Customer customer = factory.createProjection(Customer.class); + customer.setFirstname("Dave"); + customer.setLastname("Matthews"); + + // Verify accessors work + assertThat(customer.getFirstname(), is("Dave")); + assertThat(customer.getLastname(), is("Matthews")); + + // Verify evaluating a SpEL expression + assertThat(customer.getFullName(), is("Dave Matthews")); + } + + @Test + public void createsProxyForSourceMap() { + + Map backingMap = new HashMap<>(); + backingMap.put("firstname", "Dave"); + backingMap.put("lastname", "Matthews"); + + Customer customer = factory.createProjection(Customer.class, backingMap); + + // Verify accessors work + assertThat(customer.getFirstname(), is("Dave")); + assertThat(customer.getLastname(), is("Matthews")); + } + + interface Customer { + + String getFirstname(); + + void setFirstname(String firstname); + + String getLastname(); + + void setLastname(String lastname); + + @Value("#{target.firstname + ' ' + target.lastname}") + String getFullName(); + } +} diff --git a/rest/starbucks/src/main/java/example/stores/StoreInitializer.java b/rest/starbucks/src/main/java/example/stores/StoreInitializer.java index 4bc1770b..91ff4e5c 100644 --- a/rest/starbucks/src/main/java/example/stores/StoreInitializer.java +++ b/rest/starbucks/src/main/java/example/stores/StoreInitializer.java @@ -24,16 +24,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; -import org.springframework.batch.item.file.mapping.FieldSetMapper; import org.springframework.batch.item.file.separator.DefaultRecordSeparatorPolicy; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; -import org.springframework.batch.item.file.transform.FieldSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.stereotype.Component; -import org.springframework.validation.BindException; /** * Component initializing a hand full of Starbucks stores and persisting them through a {@link StoreRepository}. @@ -80,8 +77,16 @@ public class StoreInitializer { tokenizer.setStrict(false); DefaultLineMapper lineMapper = new DefaultLineMapper(); + lineMapper.setFieldSetMapper(fields -> { + + Point location = new Point(fields.readDouble("Longitude"), fields.readDouble("Latitude")); + Address address = new Address(fields.readString("Street Address"), fields.readString("City"), fields + .readString("Zip"), location); + + return new Store(fields.readString("Name"), address); + }); + lineMapper.setLineTokenizer(tokenizer); - lineMapper.setFieldSetMapper(StoreFieldSetMapper.INSTANCE); itemReader.setLineMapper(lineMapper); itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy()); itemReader.setLinesToSkip(1); @@ -102,23 +107,4 @@ public class StoreInitializer { return stores; } - - private static enum StoreFieldSetMapper implements FieldSetMapper { - - INSTANCE; - - /* - * (non-Javadoc) - * @see org.springframework.batch.item.file.mapping.FieldSetMapper#mapFieldSet(org.springframework.batch.item.file.transform.FieldSet) - */ - @Override - public Store mapFieldSet(FieldSet fields) throws BindException { - - Point location = new Point(fields.readDouble("Longitude"), fields.readDouble("Latitude")); - Address address = new Address(fields.readString("Street Address"), fields.readString("City"), - fields.readString("Zip"), location); - - return new Store(fields.readString("Name"), address); - } - } } diff --git a/rest/starbucks/src/main/java/example/stores/StarbucksClient.java b/rest/starbucks/src/test/java/example/stores/StarbucksClient.java similarity index 64% rename from rest/starbucks/src/main/java/example/stores/StarbucksClient.java rename to rest/starbucks/src/test/java/example/stores/StarbucksClient.java index cc20c15a..022c4e2d 100644 --- a/rest/starbucks/src/main/java/example/stores/StarbucksClient.java +++ b/rest/starbucks/src/test/java/example/stores/StarbucksClient.java @@ -20,39 +20,65 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.StreamSupport; +import lombok.extern.slf4j.Slf4j; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.PagedResources; import org.springframework.hateoas.PagedResources.PageMetadata; import org.springframework.hateoas.Resource; import org.springframework.hateoas.client.Traverson; +import org.springframework.hateoas.client.Traverson.TraversalBuilder; import org.springframework.hateoas.mvc.TypeReferences.PagedResourcesType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** + * A test case to discover the search resource and execute a predefined search with it. + * * @author Oliver Gierke */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration +@Slf4j public class StarbucksClient { - public static void main(String[] args) { + @Configuration + static class Config {} + + @Test + @Ignore + public void discoverStoreSearch() { Traverson traverson = new Traverson(URI.create("http://localhost:8080"), MediaTypes.HAL_JSON); + // Set up path traversal + TraversalBuilder builder = traverson. // + follow("stores", "search", "by-location"); + + // Log discovered + log.info(""); + log.info("Discovered link: {}", builder.asTemplatedLink()); + log.info(""); + Map parameters = new HashMap<>(); parameters.put("location", "40.740337,-73.995146"); parameters.put("distance", "0.5miles"); - PagedResources> resources = traverson. // - follow("stores", "search", "by-location").// + PagedResources> resources = builder.// withTemplateParameters(parameters).// toObject(new PagedResourcesType>() {}); PageMetadata metadata = resources.getMetadata(); - System.out.println(String.format("Got %s of %s stores: ", resources.getContent().size(), - metadata.getTotalElements())); + log.info("Got {} of {} stores: ", resources.getContent().size(), metadata.getTotalElements()); StreamSupport.stream(resources.spliterator(), false).// map(Resource::getContent).// - forEach(store -> String.format("- %s - %s", store.name, store.address)); + forEach(store -> log.info("{} - {}", store.name, store.address)); } static class Store {