From c2d46e36d32c7ebf5aa6ac686367b5f8d5061997 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Wed, 1 Oct 2014 12:58:02 +0100 Subject: [PATCH 1/9] upgraded to GAE 1.9.12, using Jetty over tomcat, using appengine plugin --- pom.xml | 92 +++++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/pom.xml b/pom.xml index f3eaeec..439c685 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.demo gae-demo - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT war gae @@ -14,35 +14,35 @@ org.springframework.boot spring-boot-starter-parent - 1.1.0.BUILD-SNAPSHOT + 1.1.2.BUILD-SNAPSHOT - - org.springframework.boot - spring-boot-starter-web - - + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + + + org.springframework.boot spring-boot-starter-actuator - - org.springframework.boot - spring-boot-starter-tomcat - provided - org.springframework.boot spring-boot-legacy - 1.1.0.BUILD-SNAPSHOT - - - net.kindleit - gae-runtime - ${gae.version} - pom - provided + 1.1.2.BUILD-SNAPSHOT + org.springframework.boot spring-boot-starter-test @@ -79,7 +79,7 @@ UTF-8 1.7 / - 1.8.8 + 1.9.12 ${settings.localRepository}/com/google/appengine/appengine-java-sdk/${gae.version}/appengine-java-sdk-${gae.version} test @@ -90,33 +90,29 @@ org.springframework.boot spring-boot-maven-plugin - - net.kindleit - maven-gae-plugin - 0.9.6 - - - net.kindleit - gae-runtime - ${gae.version} - pom - - - - - maven-release-plugin - - gae:deploy - - - - org.apache.tomcat.maven - tomcat6-maven-plugin - 2.0 - - / - - + + com.google.appengine + appengine-maven-plugin + ${gae.version} + + false + + -Xdebug + -agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n + + + + + + endpoints_get_discovery_doc + + + src/main/webapp/WEB-INF/web.xml + + + + + From 237fbe3ceba6b7d86f9a378a5cfc678042188746 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Wed, 1 Oct 2014 16:43:54 +0100 Subject: [PATCH 2/9] trying to use cron --- .gitignore | 1 + .idea/uiDesigner.xml | 125 ++++++++++++++++++ gae-demo.iml | 84 ++++++++++++ src/main/java/demo/Application.java | 13 +- src/main/java/demo/Item.java | 46 +++++++ src/main/java/demo/QueueItemListener.java | 7 + .../java/demo/controller/ItemController.java | 60 +++++++++ src/main/java/demo/pojo/ItemDisplay.java | 8 ++ src/main/java/demo/queue/IQueueService.java | 18 +++ .../java/demo/service/SimpleItemQueue.java | 102 ++++++++++++++ .../servlets/SelfPurgingQueueServlet.java | 53 ++++++++ src/main/webapp/WEB-INF/appengine-web.xml | 4 +- src/main/webapp/WEB-INF/cron.xml | 8 ++ src/main/webapp/WEB-INF/web.xml | 10 ++ .../demo/controller/ItemControllerTest.java | 84 ++++++++++++ src/test/java/demo/mock/CronSimulator.java | 45 +++++++ .../demo/service/SimpleItemQueueTest.java | 75 +++++++++++ 17 files changed, 730 insertions(+), 13 deletions(-) create mode 100644 .idea/uiDesigner.xml create mode 100644 gae-demo.iml create mode 100644 src/main/java/demo/Item.java create mode 100644 src/main/java/demo/QueueItemListener.java create mode 100644 src/main/java/demo/controller/ItemController.java create mode 100644 src/main/java/demo/pojo/ItemDisplay.java create mode 100644 src/main/java/demo/queue/IQueueService.java create mode 100644 src/main/java/demo/service/SimpleItemQueue.java create mode 100644 src/main/java/demo/servlets/SelfPurgingQueueServlet.java create mode 100644 src/main/webapp/WEB-INF/cron.xml create mode 100644 src/test/java/demo/controller/ItemControllerTest.java create mode 100644 src/test/java/demo/mock/CronSimulator.java create mode 100644 src/test/java/demo/service/SimpleItemQueueTest.java diff --git a/.gitignore b/.gitignore index 17cecc2..9d93787 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea .classpath .project .settings/ diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..3b00020 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gae-demo.iml b/gae-demo.iml new file mode 100644 index 0000000..26c36e3 --- /dev/null +++ b/gae-demo.iml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index 76be452..d2961ec 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -4,27 +4,18 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Configuration -@ComponentScan @EnableAutoConfiguration -@RestController +@ComponentScan public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } - @RequestMapping("/") - public String home() { - return "Hello World"; - } - - @RequestMapping("/version") - public String getVersion() { - return "1.0"; - } } diff --git a/src/main/java/demo/Item.java b/src/main/java/demo/Item.java new file mode 100644 index 0000000..47bdeb4 --- /dev/null +++ b/src/main/java/demo/Item.java @@ -0,0 +1,46 @@ +package demo; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Item { + private static final Logger log = LoggerFactory.getLogger(Item.class); + private final String id = java.util.UUID.randomUUID().toString(); + private final String value; + private long creationTimeMs = 0; + + public Item(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void startClockTicking() { + if (creationTimeMs == 0) //protect against being called twice. + { + creationTimeMs = System.currentTimeMillis(); + log.info("started clock ticking"); + } + } + + public long getCreationTimeMs() { + return creationTimeMs; + } + + + public String getId() { + return id; + } + + @Override + public String toString() { + return "Item{" + + "id='" + id + '\'' + + ", value='" + value + '\'' + + ", creationTimeMs=" + creationTimeMs + + '}'; + } +} + diff --git a/src/main/java/demo/QueueItemListener.java b/src/main/java/demo/QueueItemListener.java new file mode 100644 index 0000000..8b4e9af --- /dev/null +++ b/src/main/java/demo/QueueItemListener.java @@ -0,0 +1,7 @@ +package demo; + + +public interface QueueItemListener +{ + void onTrigger(Item item); +} diff --git a/src/main/java/demo/controller/ItemController.java b/src/main/java/demo/controller/ItemController.java new file mode 100644 index 0000000..b02ff53 --- /dev/null +++ b/src/main/java/demo/controller/ItemController.java @@ -0,0 +1,60 @@ +package demo.controller; + +import demo.Item; +import demo.pojo.ItemDisplay; +import demo.service.SimpleItemQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * Created by will on 01/10/2014. + */ + +@RestController +public class ItemController { + + private static final Logger log = LoggerFactory.getLogger(ItemController.class); + + @Autowired + SimpleItemQueue simpleItemQueue; + + @RequestMapping("/") + public String home() { + return "Hello World"; + } + + @RequestMapping("/version") + public String getVersion() { + return "1.0"; + } + + + @RequestMapping(value = "/item/add", method = RequestMethod.POST, consumes = "application/json", + produces = "application/json", + headers = {"content-type=application/json"}) + @ResponseBody + public void submitRfq(@RequestBody ItemDisplay itemDisplay) { + log.info("adding " + itemDisplay.value + " to queue"); + + Item item = new Item(itemDisplay.value); + simpleItemQueue.add(item); + } + + @RequestMapping(value = "/item/size", + method = RequestMethod.GET, + consumes = "*", + produces = "application/json", + headers = {"content-type=application/json"}) + @ResponseBody + public String getAll() { + + return String.valueOf(simpleItemQueue.size()); + + } + + +} diff --git a/src/main/java/demo/pojo/ItemDisplay.java b/src/main/java/demo/pojo/ItemDisplay.java new file mode 100644 index 0000000..160a711 --- /dev/null +++ b/src/main/java/demo/pojo/ItemDisplay.java @@ -0,0 +1,8 @@ +package demo.pojo; + +/** + * Created by will on 01/10/2014. + */ +public class ItemDisplay { + public String value; +} diff --git a/src/main/java/demo/queue/IQueueService.java b/src/main/java/demo/queue/IQueueService.java new file mode 100644 index 0000000..fb5ada3 --- /dev/null +++ b/src/main/java/demo/queue/IQueueService.java @@ -0,0 +1,18 @@ +package demo.queue; + +import demo.Item; +import demo.QueueItemListener; + + +public interface IQueueService +{ + void add(Item item); + + int size(); + + Item find(String id); + + void manuallySeekTimeouts(); + + void clear(); +} diff --git a/src/main/java/demo/service/SimpleItemQueue.java b/src/main/java/demo/service/SimpleItemQueue.java new file mode 100644 index 0000000..e85b97f --- /dev/null +++ b/src/main/java/demo/service/SimpleItemQueue.java @@ -0,0 +1,102 @@ +package demo.service; + + +import demo.Item; +import demo.QueueItemListener; +import demo.queue.IQueueService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.Iterator; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This is a queue that self purges every 30 seconds. + */ + +@Service +public class SimpleItemQueue implements IQueueService +{ + private static final Logger log = LoggerFactory.getLogger(SimpleItemQueue.class); + + static String MAX_QUEUE_LIFETIME_SECONDS = "30"; + + private final Long timeout = Long.parseLong(MAX_QUEUE_LIFETIME_SECONDS) * 1000L; + private final ConcurrentLinkedQueue fifoQueue = new ConcurrentLinkedQueue<>(); + private QueueItemListener rfqListener = new SelfPurger(); + + + public SimpleItemQueue(){} + + @Override + public void add(Item rfq) + { + rfq.startClockTicking(); + fifoQueue.add(rfq); + } + + @Override + public int size() + { + return fifoQueue.size(); + } + + + @Override + public Item find(String id) + { + Iterator iterator = fifoQueue.iterator(); + Item found = null; + while(iterator.hasNext()) + { + found = iterator.next(); + if(found.getId().equals(id)) + return found; + } + + return null; + } + + @Override + public void manuallySeekTimeouts() + { + + log.info(" seeking timeout"); + long now = System.currentTimeMillis(); + long elapsedTimeMs; + Iterator iterator = fifoQueue.iterator(); + while(iterator.hasNext()) + { + Item item = iterator.next(); + elapsedTimeMs = now - item.getCreationTimeMs(); + if(elapsedTimeMs >= timeout) + { + log.info("found a timedout id = " + item.getId()); + + rfqListener.onTrigger(item); + } + else + { + log.info("elapsedTimeMs = " + elapsedTimeMs); + } + } + + } + + @Override + public void clear() { + fifoQueue.clear(); + } + + + class SelfPurger implements QueueItemListener + { + + @Override + public void onTrigger(Item rfq) + { + fifoQueue.remove(rfq); + } + } +} diff --git a/src/main/java/demo/servlets/SelfPurgingQueueServlet.java b/src/main/java/demo/servlets/SelfPurgingQueueServlet.java new file mode 100644 index 0000000..9ee14ea --- /dev/null +++ b/src/main/java/demo/servlets/SelfPurgingQueueServlet.java @@ -0,0 +1,53 @@ +package demo.servlets; + +import demo.service.SimpleItemQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.support.SpringBeanAutowiringSupport; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class SelfPurgingQueueServlet extends HttpServlet +{ + private static final Logger log = LoggerFactory.getLogger(SelfPurgingQueueServlet.class); + + private static final long serialVersionUID = -1137258632691070463L; + + @Autowired + SimpleItemQueue simpleItemQueue; + + @Override + public void init(ServletConfig config) throws ServletException + { + super.init(config); + SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); + } + + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException + + { + log.info("== called =="); + + log.info("userAgent =" + request.getHeader("User-Agent")); + log.info("host =" + request.getHeader("Host")); + log.info("X-AppEngine-Cron =" + request.getHeader("X-AppEngine-Cron")); + log.info("X-AppEngine-QueueName =" + request.getHeader("X-AppEngine-QueueName")); + log.info("X-AppEngine-TaskName =" + request.getHeader("X-AppEngine-TaskName")); + log.info("X-AppEngine-TaskRetryCount =" + request.getHeader("X-AppEngine-TaskRetryCount")); + + boolean isCronTask = "true".equals(request.getHeader("X-AppEngine-Cron")); + //String queueName = request.getHeader("X-AppEngine-QueueName"); + + if(isCronTask) + simpleItemQueue.manuallySeekTimeouts(); + else + log.warn("someone tried to invoke cron"); + } + } \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/appengine-web.xml b/src/main/webapp/WEB-INF/appengine-web.xml index 23972a2..ab5fdb9 100644 --- a/src/main/webapp/WEB-INF/appengine-web.xml +++ b/src/main/webapp/WEB-INF/appengine-web.xml @@ -1,6 +1,6 @@ - dsyerboot - 4 + itaxibookwill + 1 true \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/cron.xml b/src/main/webapp/WEB-INF/cron.xml new file mode 100644 index 0000000..0cc46b7 --- /dev/null +++ b/src/main/webapp/WEB-INF/cron.xml @@ -0,0 +1,8 @@ + + + + /cron/item/ + polling item Queue + every 1 mins synchronized + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 6e9d6f9..b6f18a1 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -37,4 +37,14 @@ / + + itemQueueServlet + demo.servlets.SelfPurgingQueueServlet + 2 + + + itemQueueServlet + /cron/item/* + + diff --git a/src/test/java/demo/controller/ItemControllerTest.java b/src/test/java/demo/controller/ItemControllerTest.java new file mode 100644 index 0000000..a4c23f7 --- /dev/null +++ b/src/test/java/demo/controller/ItemControllerTest.java @@ -0,0 +1,84 @@ +package demo.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import demo.Application; +import demo.Item; +import demo.pojo.ItemDisplay; +import org.junit.After; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.util.Arrays; + +import static org.junit.Assert.*; + + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest("server.port=0") +public class ItemControllerTest { + + private static final org.slf4j.Logger log = LoggerFactory.getLogger(ItemControllerTest.class); + + @Value("${local.server.port}") + private int port; + + @Test + public void testVersion() throws IOException { + String body = new TestRestTemplate().getForObject("http://127.0.0.1:" + port + + "/info", String.class); + log.info("found info = " + body); + assertTrue("Wrong body: " + body, body.contains("{\"version")); + } + + @Test + @Ignore + public void testSubmitRfq() throws Exception { + + ItemDisplay two = new ItemDisplay(); + two.value = "two"; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); + + RestTemplate template = new RestTemplate(); + + ObjectMapper mapper = new ObjectMapper(); + String jsonItem = mapper.writeValueAsString(two); + + log.info("item = " + jsonItem); + HttpEntity requestEntity = new HttpEntity(jsonItem,headers); + + ResponseEntity entity = template.postForEntity("http://127.0.0.1:" + port + "/item/add", requestEntity, ItemDisplay.class); + + + String response = new TestRestTemplate().getForObject("http://127.0.0.1:" + port +"/item/size", String.class); + assertEquals("1",response); + + log.info("sleeping for 3100 ms"); + Thread.sleep(3100); + + response = new TestRestTemplate().getForObject("http://127.0.0.1:" + port +"/item/size", String.class); + assertEquals("0",response); + + } + + @After + public void end() + { + + } +} \ No newline at end of file diff --git a/src/test/java/demo/mock/CronSimulator.java b/src/test/java/demo/mock/CronSimulator.java new file mode 100644 index 0000000..2da83c8 --- /dev/null +++ b/src/test/java/demo/mock/CronSimulator.java @@ -0,0 +1,45 @@ +package demo.mock; +/* + * + * This class has a thread inside it - to simulate cron + */ + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import demo.queue.*; + +public class CronSimulator implements Runnable { + private static final Logger log = LoggerFactory.getLogger(CronSimulator.class); + private final ScheduledExecutorService cronSimulator = Executors.newScheduledThreadPool(1); + private ScheduledFuture scannerHandle; + + private final IQueueService listener; + + public CronSimulator(IQueueService listener) { + this.listener = listener; + } + + + public void start() { + log.info("start"); + scannerHandle = cronSimulator.scheduleAtFixedRate(this, 0, 3, TimeUnit.SECONDS); + } + + public void stop() { + log.info("stop"); + scannerHandle.cancel(true); + } + + @Override + public void run() { + listener.manuallySeekTimeouts(); + } + + +} diff --git a/src/test/java/demo/service/SimpleItemQueueTest.java b/src/test/java/demo/service/SimpleItemQueueTest.java new file mode 100644 index 0000000..34b20a1 --- /dev/null +++ b/src/test/java/demo/service/SimpleItemQueueTest.java @@ -0,0 +1,75 @@ +package demo.service; + + +import demo.Application; +import demo.Item; +import demo.mock.CronSimulator; +import org.junit.After; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import javax.annotation.PostConstruct; + +@ActiveProfiles("test") +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +@WebAppConfiguration +@IntegrationTest +public class SimpleItemQueueTest +{ + private static final Logger log = LoggerFactory.getLogger(SimpleItemQueueTest.class); + + @BeforeClass + public static void init() + { + SimpleItemQueue.MAX_QUEUE_LIFETIME_SECONDS = "3"; + } + + @Autowired + private SimpleItemQueue simpleItemQueue; + + private CronSimulator cronSimulator; + + @PostConstruct + public void start() + { + cronSimulator = new CronSimulator(simpleItemQueue); + } + + @After + public void end() + { + simpleItemQueue.clear(); + cronSimulator.stop(); + } + + @Test + public void testCleanExpiredTokens() throws Exception + { + cronSimulator.start(); + + Item one = new Item("one"); + + simpleItemQueue.add(one); + + Assert.assertEquals(1, simpleItemQueue.size()); + + log.info("sleeping"); + Thread.sleep(6000); + log.info("waking"); + + Assert.assertEquals(0, simpleItemQueue.size()); + + + } +} \ No newline at end of file From cdbd0457556640b5cba24d1fc4fb19ca101560b1 Mon Sep 17 00:00:00 2001 From: willedwards Date: Wed, 1 Oct 2014 21:30:53 +0100 Subject: [PATCH 3/9] removed metrics; --- src/main/java/demo/Application.java | 13 ++++++++++--- .../java/demo/service/SimpleItemQueue.java | 4 +++- src/main/webapp/WEB-INF/web.xml | 18 +++++++----------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index d2961ec..649ecbc 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -1,18 +1,25 @@ package demo; +import demo.service.SimpleItemQueue; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; @Configuration @EnableAutoConfiguration @ComponentScan public class Application { + private static final SimpleItemQueue simpleItemQueue = new SimpleItemQueue(); + + @Bean + public SimpleItemQueue buildQueue() + { + return simpleItemQueue; + } + public static void main(String[] args) { SpringApplication.run(Application.class, args); } diff --git a/src/main/java/demo/service/SimpleItemQueue.java b/src/main/java/demo/service/SimpleItemQueue.java index e85b97f..fc3c712 100644 --- a/src/main/java/demo/service/SimpleItemQueue.java +++ b/src/main/java/demo/service/SimpleItemQueue.java @@ -27,7 +27,9 @@ public class SimpleItemQueue implements IQueueService private QueueItemListener rfqListener = new SelfPurger(); - public SimpleItemQueue(){} + public SimpleItemQueue(){ + log.info("called"); + } @Override public void add(Item rfq) diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index b6f18a1..9e1c7ff 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -12,16 +12,6 @@ org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener - - metricFilter - org.springframework.web.filter.DelegatingFilterProxy - - - - metricFilter - /* - - appServlet org.springframework.web.servlet.DispatcherServlet @@ -40,11 +30,17 @@ itemQueueServlet demo.servlets.SelfPurgingQueueServlet - 2 + 4 itemQueueServlet /cron/item/* + + defaultHtmlEscape + true + + + From c7e0a2ad442df2702a5ebfa2a45b98a9bec86ade Mon Sep 17 00:00:00 2001 From: willedwards Date: Thu, 2 Oct 2014 08:11:49 +0100 Subject: [PATCH 4/9] new attempt --- pom.xml | 1 + src/main/java/demo/Application.java | 20 +++++++++++++++++-- .../servlets/SelfPurgingQueueServlet.java | 8 +++++--- src/main/resources/logback.xml | 3 +++ src/main/webapp/WEB-INF/web.xml | 10 ---------- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index 439c685..b2ac86b 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,7 @@ org.springframework.boot spring-boot-starter-actuator + org.springframework.boot spring-boot-legacy diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index 649ecbc..9ca78a5 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -1,16 +1,23 @@ package demo; import demo.service.SimpleItemQueue; +import demo.servlets.SelfPurgingQueueServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.web.WebApplicationInitializer; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; @Configuration @EnableAutoConfiguration @ComponentScan -public class Application { +public class Application implements WebApplicationInitializer +{ private static final SimpleItemQueue simpleItemQueue = new SimpleItemQueue(); @@ -23,6 +30,15 @@ public SimpleItemQueue buildQueue() public static void main(String[] args) { SpringApplication.run(Application.class, args); } - + + + @Override + public void onStartup(ServletContext servletContext) throws ServletException + { + ServletRegistration.Dynamic dispatcher = servletContext.addServlet("itemQueueServlet", new SelfPurgingQueueServlet(simpleItemQueue)); + dispatcher.setLoadOnStartup(2); + dispatcher.addMapping("/cron/item/*"); + dispatcher. + } } diff --git a/src/main/java/demo/servlets/SelfPurgingQueueServlet.java b/src/main/java/demo/servlets/SelfPurgingQueueServlet.java index 9ee14ea..e2b65f6 100644 --- a/src/main/java/demo/servlets/SelfPurgingQueueServlet.java +++ b/src/main/java/demo/servlets/SelfPurgingQueueServlet.java @@ -3,7 +3,6 @@ import demo.service.SimpleItemQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.support.SpringBeanAutowiringSupport; import javax.servlet.ServletConfig; @@ -18,9 +17,12 @@ public class SelfPurgingQueueServlet extends HttpServlet private static final Logger log = LoggerFactory.getLogger(SelfPurgingQueueServlet.class); private static final long serialVersionUID = -1137258632691070463L; + private final SimpleItemQueue simpleItemQueue; - @Autowired - SimpleItemQueue simpleItemQueue; + public SelfPurgingQueueServlet(SimpleItemQueue simpleItemQueue) + { + this.simpleItemQueue = simpleItemQueue; + } @Override public void init(ServletConfig config) throws ServletException diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 266ac62..9bcb79b 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,4 +1,7 @@ + + + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 9e1c7ff..b35ed50 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -27,16 +27,6 @@ / - - itemQueueServlet - demo.servlets.SelfPurgingQueueServlet - 4 - - - itemQueueServlet - /cron/item/* - - defaultHtmlEscape true From 9733ed6f84fbc11bcbc7c1d3cb484e4a12a2a246 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Thu, 2 Oct 2014 10:15:54 +0100 Subject: [PATCH 5/9] removed excess line --- src/main/java/demo/Application.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index 9ca78a5..8f73598 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -38,7 +38,6 @@ public void onStartup(ServletContext servletContext) throws ServletException ServletRegistration.Dynamic dispatcher = servletContext.addServlet("itemQueueServlet", new SelfPurgingQueueServlet(simpleItemQueue)); dispatcher.setLoadOnStartup(2); dispatcher.addMapping("/cron/item/*"); - dispatcher. } } From e381f23ce1ca899165539bdbc53bbe63f4b76295 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Thu, 2 Oct 2014 13:02:35 +0100 Subject: [PATCH 6/9] using controller instead of servlet --- src/main/java/demo/Application.java | 10 +--- .../java/demo/controller/CronController.java | 51 +++++++++++++++++++ src/main/webapp/WEB-INF/appengine-web.xml | 2 +- 3 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 src/main/java/demo/controller/CronController.java diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index 8f73598..e7e458e 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -16,7 +16,7 @@ @Configuration @EnableAutoConfiguration @ComponentScan -public class Application implements WebApplicationInitializer +public class Application { private static final SimpleItemQueue simpleItemQueue = new SimpleItemQueue(); @@ -32,12 +32,4 @@ public static void main(String[] args) { } - @Override - public void onStartup(ServletContext servletContext) throws ServletException - { - ServletRegistration.Dynamic dispatcher = servletContext.addServlet("itemQueueServlet", new SelfPurgingQueueServlet(simpleItemQueue)); - dispatcher.setLoadOnStartup(2); - dispatcher.addMapping("/cron/item/*"); - } - } diff --git a/src/main/java/demo/controller/CronController.java b/src/main/java/demo/controller/CronController.java new file mode 100644 index 0000000..4c486f8 --- /dev/null +++ b/src/main/java/demo/controller/CronController.java @@ -0,0 +1,51 @@ +package demo.controller; + +import demo.service.SimpleItemQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +/** + * Created by will on 01/10/2014. + */ + +@RestController +public class CronController { + + private static final Logger log = LoggerFactory.getLogger(CronController.class); + + @Autowired + SimpleItemQueue simpleItemQueue; + + + @RequestMapping(value = "/cron/item", + method = RequestMethod.GET, + consumes = "*", + headers = {"content-type=application/X-AppEngine-Cron"}) + @ResponseBody + public void purgeQueue(HttpServletRequest request) + { + + + log.info("== called =="); + + log.info("userAgent =" + request.getHeader("User-Agent")); + log.info("host =" + request.getHeader("Host")); + log.info("X-AppEngine-Cron =" + request.getHeader("X-AppEngine-Cron")); + log.info("X-AppEngine-QueueName =" + request.getHeader("X-AppEngine-QueueName")); + log.info("X-AppEngine-TaskName =" + request.getHeader("X-AppEngine-TaskName")); + log.info("X-AppEngine-TaskRetryCount =" + request.getHeader("X-AppEngine-TaskRetryCount")); + + boolean isCronTask = "true".equals(request.getHeader("X-AppEngine-Cron")); + //String queueName = request.getHeader("X-AppEngine-QueueName"); + + if(isCronTask) + simpleItemQueue.manuallySeekTimeouts(); + else + log.warn("someone tried to invoke cron"); + } + +} diff --git a/src/main/webapp/WEB-INF/appengine-web.xml b/src/main/webapp/WEB-INF/appengine-web.xml index ab5fdb9..6282d71 100644 --- a/src/main/webapp/WEB-INF/appengine-web.xml +++ b/src/main/webapp/WEB-INF/appengine-web.xml @@ -1,6 +1,6 @@ itaxibookwill - 1 + 3 true \ No newline at end of file From 68bafa85003374db352b2af04bca08dbdcba593d Mon Sep 17 00:00:00 2001 From: William Edwards Date: Thu, 2 Oct 2014 13:50:34 +0100 Subject: [PATCH 7/9] tidy up --- src/main/java/demo/Application.java | 15 ----- .../java/demo/controller/CronController.java | 18 +++--- .../servlets/SelfPurgingQueueServlet.java | 55 ------------------- src/main/resources/logback.xml | 5 +- src/main/webapp/WEB-INF/appengine-web.xml | 2 +- 5 files changed, 15 insertions(+), 80 deletions(-) delete mode 100644 src/main/java/demo/servlets/SelfPurgingQueueServlet.java diff --git a/src/main/java/demo/Application.java b/src/main/java/demo/Application.java index e7e458e..09c2ba8 100644 --- a/src/main/java/demo/Application.java +++ b/src/main/java/demo/Application.java @@ -1,17 +1,9 @@ package demo; -import demo.service.SimpleItemQueue; -import demo.servlets.SelfPurgingQueueServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.web.WebApplicationInitializer; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; @Configuration @EnableAutoConfiguration @@ -19,13 +11,6 @@ public class Application { - private static final SimpleItemQueue simpleItemQueue = new SimpleItemQueue(); - - @Bean - public SimpleItemQueue buildQueue() - { - return simpleItemQueue; - } public static void main(String[] args) { SpringApplication.run(Application.class, args); diff --git a/src/main/java/demo/controller/CronController.java b/src/main/java/demo/controller/CronController.java index 4c486f8..3a81b8a 100644 --- a/src/main/java/demo/controller/CronController.java +++ b/src/main/java/demo/controller/CronController.java @@ -4,6 +4,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; @@ -26,18 +28,18 @@ public class CronController { consumes = "*", headers = {"content-type=application/X-AppEngine-Cron"}) @ResponseBody - public void purgeQueue(HttpServletRequest request) + public ResponseEntity purgeQueue(HttpServletRequest request) { log.info("== called =="); - log.info("userAgent =" + request.getHeader("User-Agent")); - log.info("host =" + request.getHeader("Host")); - log.info("X-AppEngine-Cron =" + request.getHeader("X-AppEngine-Cron")); - log.info("X-AppEngine-QueueName =" + request.getHeader("X-AppEngine-QueueName")); - log.info("X-AppEngine-TaskName =" + request.getHeader("X-AppEngine-TaskName")); - log.info("X-AppEngine-TaskRetryCount =" + request.getHeader("X-AppEngine-TaskRetryCount")); + log.debug("userAgent =" + request.getHeader("User-Agent")); + log.debug("host =" + request.getHeader("Host")); + log.debug("X-AppEngine-Cron =" + request.getHeader("X-AppEngine-Cron")); + log.debug("X-AppEngine-QueueName =" + request.getHeader("X-AppEngine-QueueName")); + log.debug("X-AppEngine-TaskName =" + request.getHeader("X-AppEngine-TaskName")); + log.debug("X-AppEngine-TaskRetryCount =" + request.getHeader("X-AppEngine-TaskRetryCount")); boolean isCronTask = "true".equals(request.getHeader("X-AppEngine-Cron")); //String queueName = request.getHeader("X-AppEngine-QueueName"); @@ -46,6 +48,8 @@ public void purgeQueue(HttpServletRequest request) simpleItemQueue.manuallySeekTimeouts(); else log.warn("someone tried to invoke cron"); + + return new ResponseEntity(HttpStatus.OK); } } diff --git a/src/main/java/demo/servlets/SelfPurgingQueueServlet.java b/src/main/java/demo/servlets/SelfPurgingQueueServlet.java deleted file mode 100644 index e2b65f6..0000000 --- a/src/main/java/demo/servlets/SelfPurgingQueueServlet.java +++ /dev/null @@ -1,55 +0,0 @@ -package demo.servlets; - -import demo.service.SimpleItemQueue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.context.support.SpringBeanAutowiringSupport; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public class SelfPurgingQueueServlet extends HttpServlet -{ - private static final Logger log = LoggerFactory.getLogger(SelfPurgingQueueServlet.class); - - private static final long serialVersionUID = -1137258632691070463L; - private final SimpleItemQueue simpleItemQueue; - - public SelfPurgingQueueServlet(SimpleItemQueue simpleItemQueue) - { - this.simpleItemQueue = simpleItemQueue; - } - - @Override - public void init(ServletConfig config) throws ServletException - { - super.init(config); - SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext()); - } - - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException - - { - log.info("== called =="); - - log.info("userAgent =" + request.getHeader("User-Agent")); - log.info("host =" + request.getHeader("Host")); - log.info("X-AppEngine-Cron =" + request.getHeader("X-AppEngine-Cron")); - log.info("X-AppEngine-QueueName =" + request.getHeader("X-AppEngine-QueueName")); - log.info("X-AppEngine-TaskName =" + request.getHeader("X-AppEngine-TaskName")); - log.info("X-AppEngine-TaskRetryCount =" + request.getHeader("X-AppEngine-TaskRetryCount")); - - boolean isCronTask = "true".equals(request.getHeader("X-AppEngine-Cron")); - //String queueName = request.getHeader("X-AppEngine-QueueName"); - - if(isCronTask) - simpleItemQueue.manuallySeekTimeouts(); - else - log.warn("someone tried to invoke cron"); - } - } \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 9bcb79b..a8afa73 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,7 +1,8 @@ - - + + + diff --git a/src/main/webapp/WEB-INF/appengine-web.xml b/src/main/webapp/WEB-INF/appengine-web.xml index 6282d71..8219f6e 100644 --- a/src/main/webapp/WEB-INF/appengine-web.xml +++ b/src/main/webapp/WEB-INF/appengine-web.xml @@ -1,6 +1,6 @@ - itaxibookwill + your_unique_app_here 3 true \ No newline at end of file From 6befebd19f48a125f6543f0ff5201456b5ccae64 Mon Sep 17 00:00:00 2001 From: William Edwards Date: Thu, 2 Oct 2014 13:53:18 +0100 Subject: [PATCH 8/9] updated README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d863697..9ba29c5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ $ git clone https://github.com/scratches/spring-boot-legacy $ (cd spring-boot-legacy; mvn install) $ git clone https://github.com/scratches/spring-boot-sample-gae $ cd spring-boot-sample-gae -$ mvn gae:deploy +$ mvn appengine:update ``` -Also runs as a deployed WAR in WTP or regular Tomcat container. The `main()` app (normal Spring Boot launcher) should also work. \ No newline at end of file +Also runs as a deployed jar in a Jetty container. The `main()` app (normal Spring Boot launcher) should also work. \ No newline at end of file From 74d6ada58a3d5beaf9b664c84548a4c143896c5b Mon Sep 17 00:00:00 2001 From: William Edwards Date: Fri, 3 Oct 2014 11:34:52 +0100 Subject: [PATCH 9/9] test tidy up --- ...onTests.java => BasicIntegrationTest.java} | 4 +- .../demo/controller/ItemControllerTest.java | 84 ------------------- 2 files changed, 2 insertions(+), 86 deletions(-) rename src/test/java/demo/{AllIntegrationTests.java => BasicIntegrationTest.java} (90%) delete mode 100644 src/test/java/demo/controller/ItemControllerTest.java diff --git a/src/test/java/demo/AllIntegrationTests.java b/src/test/java/demo/BasicIntegrationTest.java similarity index 90% rename from src/test/java/demo/AllIntegrationTests.java rename to src/test/java/demo/BasicIntegrationTest.java index 294467e..5a4e9c0 100644 --- a/src/test/java/demo/AllIntegrationTests.java +++ b/src/test/java/demo/BasicIntegrationTest.java @@ -25,9 +25,9 @@ @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration @IntegrationTest("server.port=0") -public class AllIntegrationTests { +public class BasicIntegrationTest { - private static final Logger log = Logger.getLogger(AllIntegrationTests.class); + private static final Logger log = Logger.getLogger(BasicIntegrationTest.class); @Value("${local.server.port}") private int port; diff --git a/src/test/java/demo/controller/ItemControllerTest.java b/src/test/java/demo/controller/ItemControllerTest.java deleted file mode 100644 index a4c23f7..0000000 --- a/src/test/java/demo/controller/ItemControllerTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package demo.controller; - -import com.fasterxml.jackson.databind.ObjectMapper; -import demo.Application; -import demo.Item; -import demo.pojo.ItemDisplay; -import org.junit.After; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.IntegrationTest; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.boot.test.TestRestTemplate; -import org.springframework.http.*; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.util.Arrays; - -import static org.junit.Assert.*; - - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = Application.class) -@WebAppConfiguration -@IntegrationTest("server.port=0") -public class ItemControllerTest { - - private static final org.slf4j.Logger log = LoggerFactory.getLogger(ItemControllerTest.class); - - @Value("${local.server.port}") - private int port; - - @Test - public void testVersion() throws IOException { - String body = new TestRestTemplate().getForObject("http://127.0.0.1:" + port - + "/info", String.class); - log.info("found info = " + body); - assertTrue("Wrong body: " + body, body.contains("{\"version")); - } - - @Test - @Ignore - public void testSubmitRfq() throws Exception { - - ItemDisplay two = new ItemDisplay(); - two.value = "two"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); - - RestTemplate template = new RestTemplate(); - - ObjectMapper mapper = new ObjectMapper(); - String jsonItem = mapper.writeValueAsString(two); - - log.info("item = " + jsonItem); - HttpEntity requestEntity = new HttpEntity(jsonItem,headers); - - ResponseEntity entity = template.postForEntity("http://127.0.0.1:" + port + "/item/add", requestEntity, ItemDisplay.class); - - - String response = new TestRestTemplate().getForObject("http://127.0.0.1:" + port +"/item/size", String.class); - assertEquals("1",response); - - log.info("sleeping for 3100 ms"); - Thread.sleep(3100); - - response = new TestRestTemplate().getForObject("http://127.0.0.1:" + port +"/item/size", String.class); - assertEquals("0",response); - - } - - @After - public void end() - { - - } -} \ No newline at end of file