From 6e0eeb92446cd86449e3f795eff10256d903cd91 Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Mon, 2 Feb 2015 15:22:30 -0500 Subject: [PATCH 1/9] Formatting and comments. --- src/main/java/com/leanstacks/ws/Application.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/leanstacks/ws/Application.java b/src/main/java/com/leanstacks/ws/Application.java index 0869428..7fbe6cd 100644 --- a/src/main/java/com/leanstacks/ws/Application.java +++ b/src/main/java/com/leanstacks/ws/Application.java @@ -4,13 +4,19 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Spring Boot Main Application Class. Entry point for the application. + * Spring Boot main application class. */ @SpringBootApplication -public class Application -{ - public static void main( String[] args ) throws Exception - { +public class Application { + + /** + * Entry point for the application. + * @param args Command line arguments. + * @throws Exception Thrown when an unexpected exception is thrown from the + * application. + */ + public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } + } From 9b1e7c1819b9be5ab88ac8a25eedb8e0b7d58a24 Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Mon, 2 Feb 2015 16:10:26 -0500 Subject: [PATCH 2/9] Created getGreetings web service. --- pom.xml | 2 +- .../com/leanstacks/ws/model/Greeting.java | 31 ++++++++++++++ .../ws/web/api/GreetingController.java | 40 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leanstacks/ws/model/Greeting.java create mode 100644 src/main/java/com/leanstacks/ws/web/api/GreetingController.java diff --git a/pom.xml b/pom.xml index 0ce72dd..f6176df 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.leanstacks skeleton-ws-spring-boot - 0.1.0 + 0.2.0 org.springframework.boot diff --git a/src/main/java/com/leanstacks/ws/model/Greeting.java b/src/main/java/com/leanstacks/ws/model/Greeting.java new file mode 100644 index 0000000..a5febdb --- /dev/null +++ b/src/main/java/com/leanstacks/ws/model/Greeting.java @@ -0,0 +1,31 @@ +package com.leanstacks.ws.model; + +import java.math.BigInteger; + +public class Greeting { + + private BigInteger id; + + private String text; + + public Greeting() { + + } + + public BigInteger getId() { + return id; + } + + public void setId(BigInteger id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + +} diff --git a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java new file mode 100644 index 0000000..83d704f --- /dev/null +++ b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java @@ -0,0 +1,40 @@ +package com.leanstacks.ws.web.api; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.leanstacks.ws.model.Greeting; + +@RestController +public class GreetingController { + + @RequestMapping( + value = "/api/greetings", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getGreeting() { + + List greetings = new ArrayList(); + + Greeting g1 = new Greeting(); + g1.setId(BigInteger.valueOf(1)); + g1.setText("Hello World!"); + greetings.add(g1); + + Greeting g2 = new Greeting(); + g2.setId(BigInteger.valueOf(2)); + g2.setText("Hola Mundo!"); + greetings.add(g2); + + return new ResponseEntity>(greetings, HttpStatus.OK); + } + +} From a6e9bf7be1646fdb724a3a0d7e322014cfef4e0a Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Wed, 4 Feb 2015 11:33:15 -0500 Subject: [PATCH 3/9] Added CRUD web service endpoints. --- .../ws/web/api/GreetingController.java | 123 ++++++++++++++++-- 1 file changed, 110 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java index 83d704f..25e0c34 100644 --- a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java +++ b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java @@ -1,12 +1,15 @@ package com.leanstacks.ws.web.api; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @@ -16,25 +19,119 @@ @RestController public class GreetingController { - @RequestMapping( - value = "/api/greetings", - method = RequestMethod.GET, - produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> getGreeting() { + private static BigInteger nextId; + private static Map greetingMap; + + private static Greeting save(Greeting greeting) { + if (greetingMap == null) { + greetingMap = new HashMap(); + nextId = BigInteger.ONE; + } + // If Update... + if (greeting.getId() != null) { + Greeting oldGreeting = greetingMap.get(greeting.getId()); + if (oldGreeting == null) { + return null; + } + greetingMap.remove(greeting.getId()); + greetingMap.put(greeting.getId(), greeting); + return greeting; + } + // If Create + greeting.setId(nextId); + nextId = nextId.add(BigInteger.ONE); + greetingMap.put(greeting.getId(), greeting); + return greeting; + } - List greetings = new ArrayList(); + private static boolean delete(BigInteger id) { + Greeting deletedGreeting = greetingMap.remove(id); + if (deletedGreeting == null) { + return false; + } + return true; + } + static { Greeting g1 = new Greeting(); - g1.setId(BigInteger.valueOf(1)); g1.setText("Hello World!"); - greetings.add(g1); + save(g1); Greeting g2 = new Greeting(); - g2.setId(BigInteger.valueOf(2)); g2.setText("Hola Mundo!"); - greetings.add(g2); + save(g2); + } + + @RequestMapping( + value = "/api/greetings", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getGreetings() { + + Collection greetings = greetingMap.values(); + + return new ResponseEntity>(greetings, + HttpStatus.OK); + } + + @RequestMapping( + value = "/api/greetings/{id}", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity getGreeting(@PathVariable BigInteger id) { + + Greeting greeting = greetingMap.get(id); + if (greeting == null) { + return new ResponseEntity(HttpStatus.NOT_FOUND); + } + + return new ResponseEntity(greeting, HttpStatus.OK); + } + + @RequestMapping( + value = "/api/greetings", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity createGreeting( + @RequestBody Greeting greeting) { + + Greeting savedGreeting = save(greeting); + + return new ResponseEntity(savedGreeting, HttpStatus.CREATED); + } + + @RequestMapping( + value = "/api/greetings/{id}", + method = RequestMethod.PUT, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateGreeting( + @RequestBody Greeting greeting) { + + Greeting updatedGreeting = save(greeting); + if (updatedGreeting == null) { + return new ResponseEntity( + HttpStatus.INTERNAL_SERVER_ERROR); + } + + return new ResponseEntity(updatedGreeting, HttpStatus.OK); + } + + @RequestMapping( + value = "/api/greetings/{id}", + method = RequestMethod.DELETE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity deleteGreeting( + @PathVariable("id") BigInteger id, @RequestBody Greeting greeting) { + + boolean deleted = delete(id); + if (!deleted) { + return new ResponseEntity( + HttpStatus.INTERNAL_SERVER_ERROR); + } - return new ResponseEntity>(greetings, HttpStatus.OK); + return new ResponseEntity(HttpStatus.NO_CONTENT); } } From 6e15201acf65b62b1423c689db0a04f27ae65deb Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Sun, 8 Feb 2015 10:06:41 -0500 Subject: [PATCH 4/9] Added ExceptionHandler. Updated documentation. --- README.md | 88 ++++++++++++++++++- .../java/com/leanstacks/ws/Application.java | 2 + .../com/leanstacks/ws/model/Greeting.java | 5 ++ .../ws/web/api/GreetingController.java | 46 ++++++++-- .../ws/web/filter/SimpleCORSFilter.java | 56 ++++++++++++ .../resources/config/application.properties | 8 ++ 6 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/leanstacks/ws/web/filter/SimpleCORSFilter.java create mode 100644 src/main/resources/config/application.properties diff --git a/README.md b/README.md index 87fb5e2..d67da98 100644 --- a/README.md +++ b/README.md @@ -1 +1,87 @@ -# skeleton-ws-spring-boot +# Project Skeleton for Spring Boot Web Services + +## Acknowledgements + +This is a [LEAN**STACKS**](http://www.leanstacks.com) solution. + +## Getting Started + +This is a project skeleton for a [Spring Boot](http://projects.spring.io/spring-boot/) RESTful web services application. + +## Languages + +This project is authored in Java. + +## Installation + +### Fork the Repository + +Fork the [Spring Boot web services skeleton project](https://github.com/mwarman/skeleton-ws-spring-boot) on GitHub. Clone the project to the host machine. + +### Dependencies + +The project requires the following dependencies be installed on the host machine: + +* Java Development Kit 7 or later +* Apache Maven 3 or later + +## Running + +The project uses [Maven](http://maven.apache.org/) for build, package, and test workflow automation. The following Maven goals are the most commonly used. + +### spring-boot:run + +The `spring-boot:run` Maven goal performs the following workflow steps: + +* compiles Java classes to the /target directory +* copies all resources to the /target directory +* starts an embedded Apache Tomcat server + +To execute the `spring-boot:run` Maven goal, type the following command at a terminal prompt in the project base directory. + +``` +mvn spring-boot:run +``` + +Type `ctrl-C` to halt the web server. + +This goal is used for local machine development and functional testing. Use the `package` goal for server deployment. + +### package + +The `package` Maven goal performs the following workflow steps: + +* compiles Java classes to the /target directory +* copies all resources to the /target directory +* prepares an executable JAR file in the /target directory + +The `package` Maven goal is designed to prepare the application for distribution to server environments. The application and all dependencies are packaged into a single, executable JAR file. + +To execute the `package` goal, type the following command at a terminal prompt in the project base directory. + +``` +mvn clean package +``` + +The application distribution artifact is placed in the /target directory and is named using the `artifactId` and `version` from the pom.xml file. To run the JAR file use the following command: + +``` +java -jar example-1.0.0.jar +``` + +### test + +The `test` Maven goal performs the following workflow steps: + +* compiles Java classes to the /target directory +* copies all resources to the /target directory +* executes the unit test suites +* produces unit test reports + +The `test` Maven goal is designed to allow engineers the means to run the unit test suites against the main source code. This goal may also be used on continuous integration servers such as Jenkins, etc. + +To execute the `test` Maven goal, type the following command at a terminal prompt in the project base directory. + +``` +mvn clean test +``` diff --git a/src/main/java/com/leanstacks/ws/Application.java b/src/main/java/com/leanstacks/ws/Application.java index 7fbe6cd..732e67a 100644 --- a/src/main/java/com/leanstacks/ws/Application.java +++ b/src/main/java/com/leanstacks/ws/Application.java @@ -5,6 +5,8 @@ /** * Spring Boot main application class. + * + * @author Matt Warman */ @SpringBootApplication public class Application { diff --git a/src/main/java/com/leanstacks/ws/model/Greeting.java b/src/main/java/com/leanstacks/ws/model/Greeting.java index a5febdb..3d4f25d 100644 --- a/src/main/java/com/leanstacks/ws/model/Greeting.java +++ b/src/main/java/com/leanstacks/ws/model/Greeting.java @@ -2,6 +2,11 @@ import java.math.BigInteger; +/** + * The Greeting class is an entity model object. + * + * @author Matt Warman + */ public class Greeting { private BigInteger id; diff --git a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java index 25e0c34..b00ce97 100644 --- a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java +++ b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java @@ -5,9 +5,12 @@ import java.util.HashMap; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -16,9 +19,18 @@ import com.leanstacks.ws.model.Greeting; +/** + * The GreetingController class is a RESTful web service controller. The + * @RestController annotation informs Spring that each + * @RequestMapping method returns a @ResponseBody. + * + * @author Matt Warman + */ @RestController public class GreetingController { + private Logger logger = LoggerFactory.getLogger(this.getClass()); + private static BigInteger nextId; private static Map greetingMap; @@ -62,14 +74,25 @@ private static boolean delete(BigInteger id) { save(g2); } + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception e) { + logger.error("> handleException"); + logger.error("- Exception: ", e); + logger.error("< handleException"); + return new ResponseEntity(e, + HttpStatus.INTERNAL_SERVER_ERROR); + } + @RequestMapping( value = "/api/greetings", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> getGreetings() { + public ResponseEntity> getGreetings() throws Exception { + logger.info("> getGreetings"); Collection greetings = greetingMap.values(); + logger.info("< getGreetings"); return new ResponseEntity>(greetings, HttpStatus.OK); } @@ -78,13 +101,17 @@ public ResponseEntity> getGreetings() { value = "/api/greetings/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getGreeting(@PathVariable BigInteger id) { + public ResponseEntity getGreeting(@PathVariable BigInteger id) + throws Exception { + logger.info("> getGreeting"); Greeting greeting = greetingMap.get(id); if (greeting == null) { + logger.info("< getGreeting"); return new ResponseEntity(HttpStatus.NOT_FOUND); } + logger.info("< getGreeting"); return new ResponseEntity(greeting, HttpStatus.OK); } @@ -94,10 +121,12 @@ public ResponseEntity getGreeting(@PathVariable BigInteger id) { consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity createGreeting( - @RequestBody Greeting greeting) { + @RequestBody Greeting greeting) throws Exception { + logger.info("> createGreeting"); Greeting savedGreeting = save(greeting); + logger.info("< createGreeting"); return new ResponseEntity(savedGreeting, HttpStatus.CREATED); } @@ -107,14 +136,17 @@ public ResponseEntity createGreeting( consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity updateGreeting( - @RequestBody Greeting greeting) { + @RequestBody Greeting greeting) throws Exception { + logger.info("> updateGreeting"); Greeting updatedGreeting = save(greeting); if (updatedGreeting == null) { + logger.info("< updateGreeting"); return new ResponseEntity( HttpStatus.INTERNAL_SERVER_ERROR); } + logger.info("< updateGreeting"); return new ResponseEntity(updatedGreeting, HttpStatus.OK); } @@ -123,14 +155,18 @@ public ResponseEntity updateGreeting( method = RequestMethod.DELETE, consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity deleteGreeting( - @PathVariable("id") BigInteger id, @RequestBody Greeting greeting) { + @PathVariable("id") BigInteger id, @RequestBody Greeting greeting) + throws Exception { + logger.info("> deleteGreeting"); boolean deleted = delete(id); if (!deleted) { + logger.info("< deleteGreeting"); return new ResponseEntity( HttpStatus.INTERNAL_SERVER_ERROR); } + logger.info("< deleteGreeting"); return new ResponseEntity(HttpStatus.NO_CONTENT); } diff --git a/src/main/java/com/leanstacks/ws/web/filter/SimpleCORSFilter.java b/src/main/java/com/leanstacks/ws/web/filter/SimpleCORSFilter.java new file mode 100644 index 0000000..0dd2d0f --- /dev/null +++ b/src/main/java/com/leanstacks/ws/web/filter/SimpleCORSFilter.java @@ -0,0 +1,56 @@ +package com.leanstacks.ws.web.filter; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * The SimpleCORSFilter class is a standard web Filter which intercepts all + * inbound HTTP requests. The filter sets several Headers on the HTTP response + * which inform a browser that the web services handle Cross-Origin requests. + * + * @author Matt Warman + */ +@Component +public class SimpleCORSFilter implements Filter { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Override + public void destroy() { + + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, + FilterChain chain) throws IOException, ServletException { + logger.info("> doFilter"); + + HttpServletResponse response = (HttpServletResponse) res; + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Methods", + "DELETE, GET, OPTIONS, PATCH, POST, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", + "x-requested-with, content-type"); + + logger.info("< doFilter"); + chain.doFilter(req, res); + } + + @Override + public void init(FilterConfig config) throws ServletException { + + } + +} diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties new file mode 100644 index 0000000..bcf6dd0 --- /dev/null +++ b/src/main/resources/config/application.properties @@ -0,0 +1,8 @@ +## +# The Base Application Configuration File +## + +## +# Web Server Configuration +## +server.port= From 07f2e81ccd3e23ca70f57c1d096b1ec369208f0b Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Sun, 8 Feb 2015 10:37:45 -0500 Subject: [PATCH 5/9] Created business service layer. Added GreetingService and implementation. --- .../ws/service/GreetingService.java | 56 +++++++++ .../ws/service/GreetingServiceBean.java | 118 ++++++++++++++++++ .../ws/web/api/GreetingController.java | 63 +++------- 3 files changed, 188 insertions(+), 49 deletions(-) create mode 100644 src/main/java/com/leanstacks/ws/service/GreetingService.java create mode 100644 src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java diff --git a/src/main/java/com/leanstacks/ws/service/GreetingService.java b/src/main/java/com/leanstacks/ws/service/GreetingService.java new file mode 100644 index 0000000..fa94c30 --- /dev/null +++ b/src/main/java/com/leanstacks/ws/service/GreetingService.java @@ -0,0 +1,56 @@ +package com.leanstacks.ws.service; + +import java.math.BigInteger; +import java.util.Collection; + +import com.leanstacks.ws.model.Greeting; + +/** + * The GreetingService interface defines all public business behaviors for + * operations on the Greeting entity model. + * + * This interface should be injected into GreetingService clients, not the + * implementation bean. + * + * @author Matt Warman + */ +public interface GreetingService { + + /** + * Find all Greeting entities. + * @return A Collection of Greeting objects. + */ + Collection findAll(); + + /** + * Find a single Greeting entity by primary key identifier. + * @param id A BigInteger primary key identifier. + * @return A Greeting or null if none found. + */ + Greeting findOne(BigInteger id); + + /** + * Persists a Greeting entity in the data store. + * @param greeting A Greeting object to be persisted. + * @return A persisted Greeting object or null if a problem + * occurred. + */ + Greeting create(Greeting greeting); + + /** + * Updates a previously persisted Greeting entity in the data store. + * @param greeting A Greeting object to be updated. + * @return An updated Greeting object or null if a problem + * occurred. + */ + Greeting update(Greeting greeting); + + /** + * Removes a previously persisted Greeting entity from the data store. + * @param id A BigInteger primary key identifier. + * @return Returns true if the entity was removed from the data + * store or false if a problem occurred. + */ + boolean delete(BigInteger id); + +} diff --git a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java new file mode 100644 index 0000000..9e422d9 --- /dev/null +++ b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java @@ -0,0 +1,118 @@ +package com.leanstacks.ws.service; + +import java.math.BigInteger; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.leanstacks.ws.model.Greeting; + +/** + * The GreetingServiceBean encapsulates all business behaviors operating on the + * Greeting entity model. + * + * @author Matt Warman + */ +@Service +public class GreetingServiceBean implements GreetingService { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static BigInteger nextId; + private static Map greetingMap; + + private static Greeting saveGreeting(Greeting greeting) { + if (greetingMap == null) { + greetingMap = new HashMap(); + nextId = BigInteger.ONE; + } + // If Update... + if (greeting.getId() != null) { + Greeting oldGreeting = greetingMap.get(greeting.getId()); + if (oldGreeting == null) { + return null; + } + greetingMap.remove(greeting.getId()); + greetingMap.put(greeting.getId(), greeting); + return greeting; + } + // If Create + greeting.setId(nextId); + nextId = nextId.add(BigInteger.ONE); + greetingMap.put(greeting.getId(), greeting); + return greeting; + } + + private static boolean deleteGreeting(BigInteger id) { + Greeting deletedGreeting = greetingMap.remove(id); + if (deletedGreeting == null) { + return false; + } + return true; + } + + static { + Greeting g1 = new Greeting(); + g1.setText("Hello World!"); + saveGreeting(g1); + + Greeting g2 = new Greeting(); + g2.setText("Hola Mundo!"); + saveGreeting(g2); + } + + @Override + public Collection findAll() { + logger.info("> findAll"); + + Collection greetings = greetingMap.values(); + + logger.info("< findAll"); + return greetings; + } + + @Override + public Greeting findOne(BigInteger id) { + logger.info("> findOne {}", id); + + Greeting greeting = greetingMap.get(id); + + logger.info("< findOne {}", id); + return greeting; + } + + @Override + public Greeting create(Greeting greeting) { + logger.info("> create"); + + Greeting savedGreeting = saveGreeting(greeting); + + logger.info("< create"); + return savedGreeting; + } + + @Override + public Greeting update(Greeting greeting) { + logger.info("> update {}", greeting.getId()); + + Greeting updatedGreeting = saveGreeting(greeting); + + logger.info("< update {}", greeting.getId()); + return updatedGreeting; + } + + @Override + public boolean delete(BigInteger id) { + logger.info("> delete {}", id); + + boolean deleted = deleteGreeting(id); + + logger.info("< delete {}", id); + return deleted; + } + +} diff --git a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java index b00ce97..e89c597 100644 --- a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java +++ b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java @@ -2,11 +2,10 @@ import java.math.BigInteger; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -18,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController; import com.leanstacks.ws.model.Greeting; +import com.leanstacks.ws.service.GreetingService; /** * The GreetingController class is a RESTful web service controller. The @@ -31,48 +31,8 @@ public class GreetingController { private Logger logger = LoggerFactory.getLogger(this.getClass()); - private static BigInteger nextId; - private static Map greetingMap; - - private static Greeting save(Greeting greeting) { - if (greetingMap == null) { - greetingMap = new HashMap(); - nextId = BigInteger.ONE; - } - // If Update... - if (greeting.getId() != null) { - Greeting oldGreeting = greetingMap.get(greeting.getId()); - if (oldGreeting == null) { - return null; - } - greetingMap.remove(greeting.getId()); - greetingMap.put(greeting.getId(), greeting); - return greeting; - } - // If Create - greeting.setId(nextId); - nextId = nextId.add(BigInteger.ONE); - greetingMap.put(greeting.getId(), greeting); - return greeting; - } - - private static boolean delete(BigInteger id) { - Greeting deletedGreeting = greetingMap.remove(id); - if (deletedGreeting == null) { - return false; - } - return true; - } - - static { - Greeting g1 = new Greeting(); - g1.setText("Hello World!"); - save(g1); - - Greeting g2 = new Greeting(); - g2.setText("Hola Mundo!"); - save(g2); - } + @Autowired + private GreetingService greetingService; @ExceptionHandler(Exception.class) public ResponseEntity handleException(Exception e) { @@ -90,7 +50,7 @@ public ResponseEntity handleException(Exception e) { public ResponseEntity> getGreetings() throws Exception { logger.info("> getGreetings"); - Collection greetings = greetingMap.values(); + Collection greetings = greetingService.findAll(); logger.info("< getGreetings"); return new ResponseEntity>(greetings, @@ -105,7 +65,7 @@ public ResponseEntity getGreeting(@PathVariable BigInteger id) throws Exception { logger.info("> getGreeting"); - Greeting greeting = greetingMap.get(id); + Greeting greeting = greetingService.findOne(id); if (greeting == null) { logger.info("< getGreeting"); return new ResponseEntity(HttpStatus.NOT_FOUND); @@ -124,7 +84,12 @@ public ResponseEntity createGreeting( @RequestBody Greeting greeting) throws Exception { logger.info("> createGreeting"); - Greeting savedGreeting = save(greeting); + Greeting savedGreeting = greetingService.create(greeting); + if (savedGreeting == null) { + logger.info("< createGreeting"); + return new ResponseEntity( + HttpStatus.INTERNAL_SERVER_ERROR); + } logger.info("< createGreeting"); return new ResponseEntity(savedGreeting, HttpStatus.CREATED); @@ -139,7 +104,7 @@ public ResponseEntity updateGreeting( @RequestBody Greeting greeting) throws Exception { logger.info("> updateGreeting"); - Greeting updatedGreeting = save(greeting); + Greeting updatedGreeting = greetingService.update(greeting); if (updatedGreeting == null) { logger.info("< updateGreeting"); return new ResponseEntity( @@ -159,7 +124,7 @@ public ResponseEntity deleteGreeting( throws Exception { logger.info("> deleteGreeting"); - boolean deleted = delete(id); + boolean deleted = greetingService.delete(id); if (!deleted) { logger.info("< deleteGreeting"); return new ResponseEntity( From 655c2e46099d176812944ca4aa4582b200a6fe70 Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Sun, 8 Feb 2015 12:02:50 -0500 Subject: [PATCH 6/9] Created persistence layer. Added GreetingRepository with HSQLDB persistence. --- pom.xml | 10 +++ .../com/leanstacks/ws/model/Greeting.java | 15 +++- .../ws/repository/GreetingRepository.java | 11 +++ .../ws/service/GreetingService.java | 7 +- .../ws/service/GreetingServiceBean.java | 83 +++++++------------ .../ws/web/api/GreetingController.java | 15 +--- .../resources/config/application.properties | 4 + 7 files changed, 72 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/leanstacks/ws/repository/GreetingRepository.java diff --git a/pom.xml b/pom.xml index f6176df..a477626 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,16 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.hsqldb + hsqldb + runtime + diff --git a/src/main/java/com/leanstacks/ws/model/Greeting.java b/src/main/java/com/leanstacks/ws/model/Greeting.java index 3d4f25d..5259f23 100644 --- a/src/main/java/com/leanstacks/ws/model/Greeting.java +++ b/src/main/java/com/leanstacks/ws/model/Greeting.java @@ -1,27 +1,34 @@ package com.leanstacks.ws.model; -import java.math.BigInteger; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; /** * The Greeting class is an entity model object. * * @author Matt Warman */ +@Entity public class Greeting { - private BigInteger id; + @Id + @GeneratedValue + private Long id; + @NotNull private String text; public Greeting() { } - public BigInteger getId() { + public Long getId() { return id; } - public void setId(BigInteger id) { + public void setId(Long id) { this.id = id; } diff --git a/src/main/java/com/leanstacks/ws/repository/GreetingRepository.java b/src/main/java/com/leanstacks/ws/repository/GreetingRepository.java new file mode 100644 index 0000000..46fda5b --- /dev/null +++ b/src/main/java/com/leanstacks/ws/repository/GreetingRepository.java @@ -0,0 +1,11 @@ +package com.leanstacks.ws.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.leanstacks.ws.model.Greeting; + +@Repository +public interface GreetingRepository extends JpaRepository { + +} diff --git a/src/main/java/com/leanstacks/ws/service/GreetingService.java b/src/main/java/com/leanstacks/ws/service/GreetingService.java index fa94c30..e13bab4 100644 --- a/src/main/java/com/leanstacks/ws/service/GreetingService.java +++ b/src/main/java/com/leanstacks/ws/service/GreetingService.java @@ -1,6 +1,5 @@ package com.leanstacks.ws.service; -import java.math.BigInteger; import java.util.Collection; import com.leanstacks.ws.model.Greeting; @@ -27,7 +26,7 @@ public interface GreetingService { * @param id A BigInteger primary key identifier. * @return A Greeting or null if none found. */ - Greeting findOne(BigInteger id); + Greeting findOne(Long id); /** * Persists a Greeting entity in the data store. @@ -48,9 +47,7 @@ public interface GreetingService { /** * Removes a previously persisted Greeting entity from the data store. * @param id A BigInteger primary key identifier. - * @return Returns true if the entity was removed from the data - * store or false if a problem occurred. */ - boolean delete(BigInteger id); + void delete(Long id); } diff --git a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java index 9e422d9..f05005d 100644 --- a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java +++ b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java @@ -1,15 +1,14 @@ package com.leanstacks.ws.service; -import java.math.BigInteger; import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.leanstacks.ws.model.Greeting; +import com.leanstacks.ws.repository.GreetingRepository; /** * The GreetingServiceBean encapsulates all business behaviors operating on the @@ -22,64 +21,24 @@ public class GreetingServiceBean implements GreetingService { private Logger logger = LoggerFactory.getLogger(this.getClass()); - private static BigInteger nextId; - private static Map greetingMap; - - private static Greeting saveGreeting(Greeting greeting) { - if (greetingMap == null) { - greetingMap = new HashMap(); - nextId = BigInteger.ONE; - } - // If Update... - if (greeting.getId() != null) { - Greeting oldGreeting = greetingMap.get(greeting.getId()); - if (oldGreeting == null) { - return null; - } - greetingMap.remove(greeting.getId()); - greetingMap.put(greeting.getId(), greeting); - return greeting; - } - // If Create - greeting.setId(nextId); - nextId = nextId.add(BigInteger.ONE); - greetingMap.put(greeting.getId(), greeting); - return greeting; - } - - private static boolean deleteGreeting(BigInteger id) { - Greeting deletedGreeting = greetingMap.remove(id); - if (deletedGreeting == null) { - return false; - } - return true; - } - - static { - Greeting g1 = new Greeting(); - g1.setText("Hello World!"); - saveGreeting(g1); - - Greeting g2 = new Greeting(); - g2.setText("Hola Mundo!"); - saveGreeting(g2); - } + @Autowired + private GreetingRepository greetingRepository; @Override public Collection findAll() { logger.info("> findAll"); - Collection greetings = greetingMap.values(); + Collection greetings = greetingRepository.findAll(); logger.info("< findAll"); return greetings; } @Override - public Greeting findOne(BigInteger id) { + public Greeting findOne(Long id) { logger.info("> findOne {}", id); - Greeting greeting = greetingMap.get(id); + Greeting greeting = greetingRepository.findOne(id); logger.info("< findOne {}", id); return greeting; @@ -89,7 +48,16 @@ public Greeting findOne(BigInteger id) { public Greeting create(Greeting greeting) { logger.info("> create"); - Greeting savedGreeting = saveGreeting(greeting); + // Ensure the entity object to be created does NOT exist in the + // repository. Prevent the default behavior of save() which will update + // an existing entity if the entity matching the supplied id exists. + if (greeting.getId() != null) { + logger.error("Attempted to create a Greeting, but id attribute was not null."); + logger.info("< create"); + return null; + } + + Greeting savedGreeting = greetingRepository.save(greeting); logger.info("< create"); return savedGreeting; @@ -99,20 +67,29 @@ public Greeting create(Greeting greeting) { public Greeting update(Greeting greeting) { logger.info("> update {}", greeting.getId()); - Greeting updatedGreeting = saveGreeting(greeting); + // Ensure the entity object to be updated exists in the repository to + // prevent the default behavior of save() which will persist a new + // entity if the entity matching the id does not exist + Greeting greetingToUpdate = findOne(greeting.getId()); + if (greetingToUpdate == null) { + logger.error("Attempted to update a Greeting, but the entity does not exist."); + logger.info("< update {}", greeting.getId()); + return null; + } + + Greeting updatedGreeting = greetingRepository.save(greeting); logger.info("< update {}", greeting.getId()); return updatedGreeting; } @Override - public boolean delete(BigInteger id) { + public void delete(Long id) { logger.info("> delete {}", id); - boolean deleted = deleteGreeting(id); + greetingRepository.delete(id); logger.info("< delete {}", id); - return deleted; } } diff --git a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java index e89c597..988a4a4 100644 --- a/src/main/java/com/leanstacks/ws/web/api/GreetingController.java +++ b/src/main/java/com/leanstacks/ws/web/api/GreetingController.java @@ -1,6 +1,5 @@ package com.leanstacks.ws.web.api; -import java.math.BigInteger; import java.util.Collection; import org.slf4j.Logger; @@ -61,7 +60,7 @@ public ResponseEntity> getGreetings() throws Exception { value = "/api/greetings/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getGreeting(@PathVariable BigInteger id) + public ResponseEntity getGreeting(@PathVariable Long id) throws Exception { logger.info("> getGreeting"); @@ -119,17 +118,11 @@ public ResponseEntity updateGreeting( value = "/api/greetings/{id}", method = RequestMethod.DELETE, consumes = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity deleteGreeting( - @PathVariable("id") BigInteger id, @RequestBody Greeting greeting) - throws Exception { + public ResponseEntity deleteGreeting(@PathVariable("id") Long id, + @RequestBody Greeting greeting) throws Exception { logger.info("> deleteGreeting"); - boolean deleted = greetingService.delete(id); - if (!deleted) { - logger.info("< deleteGreeting"); - return new ResponseEntity( - HttpStatus.INTERNAL_SERVER_ERROR); - } + greetingService.delete(id); logger.info("< deleteGreeting"); return new ResponseEntity(HttpStatus.NO_CONTENT); diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index bcf6dd0..b19e199 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -6,3 +6,7 @@ # Web Server Configuration ## server.port= + +## +# Data Source Configuration +## From 0007f7009b1284ce4619b6ec40d4cadcad9ff0dc Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Sun, 8 Feb 2015 14:35:01 -0500 Subject: [PATCH 7/9] Added transaction support. Added @Transaction to GreetingService methods. --- src/main/java/com/leanstacks/ws/Application.java | 2 ++ .../java/com/leanstacks/ws/service/GreetingServiceBean.java | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/leanstacks/ws/Application.java b/src/main/java/com/leanstacks/ws/Application.java index 732e67a..dd505cb 100644 --- a/src/main/java/com/leanstacks/ws/Application.java +++ b/src/main/java/com/leanstacks/ws/Application.java @@ -2,6 +2,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Spring Boot main application class. @@ -9,6 +10,7 @@ * @author Matt Warman */ @SpringBootApplication +@EnableTransactionManagement public class Application { /** diff --git a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java index f05005d..0bdbf5e 100644 --- a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java +++ b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.leanstacks.ws.model.Greeting; import com.leanstacks.ws.repository.GreetingRepository; @@ -44,6 +45,7 @@ public Greeting findOne(Long id) { return greeting; } + @Transactional @Override public Greeting create(Greeting greeting) { logger.info("> create"); @@ -63,6 +65,7 @@ public Greeting create(Greeting greeting) { return savedGreeting; } + @Transactional @Override public Greeting update(Greeting greeting) { logger.info("> update {}", greeting.getId()); @@ -83,6 +86,7 @@ public Greeting update(Greeting greeting) { return updatedGreeting; } + @Transactional @Override public void delete(Long id) { logger.info("> delete {}", id); From 13e08cc451bec1149109c5c85bbfb933111a2371 Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Sun, 8 Feb 2015 15:37:21 -0500 Subject: [PATCH 8/9] Added cache support. Added caching annotations to GreetingService methods. --- pom.xml | 13 ++++++++++++- src/main/java/com/leanstacks/ws/Application.java | 12 ++++++++++++ .../ws/service/GreetingServiceBean.java | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a477626..cae194f 100644 --- a/pom.xml +++ b/pom.xml @@ -22,12 +22,23 @@ org.springframework.boot spring-boot-starter-data-jpa - + org.hsqldb hsqldb runtime + + + + org.springframework + spring-context-support + + + com.google.guava + guava + 18.0 + diff --git a/src/main/java/com/leanstacks/ws/Application.java b/src/main/java/com/leanstacks/ws/Application.java index dd505cb..40140f5 100644 --- a/src/main/java/com/leanstacks/ws/Application.java +++ b/src/main/java/com/leanstacks/ws/Application.java @@ -2,6 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.guava.GuavaCacheManager; +import org.springframework.context.annotation.Bean; import org.springframework.transaction.annotation.EnableTransactionManagement; /** @@ -11,6 +15,7 @@ */ @SpringBootApplication @EnableTransactionManagement +@EnableCaching public class Application { /** @@ -23,4 +28,11 @@ public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } + @Bean + public CacheManager cacheManager() { + GuavaCacheManager cacheManager = new GuavaCacheManager("greetings"); + + return cacheManager; + } + } diff --git a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java index 0bdbf5e..c1dda9f 100644 --- a/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java +++ b/src/main/java/com/leanstacks/ws/service/GreetingServiceBean.java @@ -5,6 +5,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -35,6 +38,9 @@ public Collection findAll() { return greetings; } + @Cacheable( + value = "greetings", + key = "#id") @Override public Greeting findOne(Long id) { logger.info("> findOne {}", id); @@ -45,6 +51,9 @@ public Greeting findOne(Long id) { return greeting; } + @CachePut( + value = "greetings", + key = "#result.id") @Transactional @Override public Greeting create(Greeting greeting) { @@ -65,6 +74,9 @@ public Greeting create(Greeting greeting) { return savedGreeting; } + @CachePut( + value = "greetings", + key = "#greeting.id") @Transactional @Override public Greeting update(Greeting greeting) { @@ -86,6 +98,9 @@ public Greeting update(Greeting greeting) { return updatedGreeting; } + @CacheEvict( + value = "greetings", + key = "#id") @Transactional @Override public void delete(Long id) { From acb15bc192161ac21b2b3b7525625e9ac8cc0838 Mon Sep 17 00:00:00 2001 From: Matt Warman Date: Wed, 11 Feb 2015 07:05:17 -0500 Subject: [PATCH 9/9] Added scheduled batch execution support. Added @EnableScheduling. Created GreetingBatchBean. Added configurable schedules. --- .../java/com/leanstacks/ws/Application.java | 2 + .../ws/batch/GreetingBatchBean.java | 132 ++++++++++++++++++ .../resources/config/application.properties | 11 ++ src/main/resources/data/hsqldb/data.sql | 2 + 4 files changed, 147 insertions(+) create mode 100644 src/main/java/com/leanstacks/ws/batch/GreetingBatchBean.java create mode 100644 src/main/resources/data/hsqldb/data.sql diff --git a/src/main/java/com/leanstacks/ws/Application.java b/src/main/java/com/leanstacks/ws/Application.java index 40140f5..526766b 100644 --- a/src/main/java/com/leanstacks/ws/Application.java +++ b/src/main/java/com/leanstacks/ws/Application.java @@ -6,6 +6,7 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement; /** @@ -16,6 +17,7 @@ @SpringBootApplication @EnableTransactionManagement @EnableCaching +@EnableScheduling public class Application { /** diff --git a/src/main/java/com/leanstacks/ws/batch/GreetingBatchBean.java b/src/main/java/com/leanstacks/ws/batch/GreetingBatchBean.java new file mode 100644 index 0000000..0171543 --- /dev/null +++ b/src/main/java/com/leanstacks/ws/batch/GreetingBatchBean.java @@ -0,0 +1,132 @@ +package com.leanstacks.ws.batch; + +import java.util.Collection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import com.leanstacks.ws.model.Greeting; +import com.leanstacks.ws.service.GreetingService; + +/** + * The GreetingBatchBean contains @Scheduled methods operating on + * Greeting entities to perform batch operations. + * + * @author Matt Warman + */ +@Component +public class GreetingBatchBean { + + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private GreetingService greetingService; + + /** + * Use a cron expression to execute logic on a schedule. Expression: second + * minute hour day-of-month month weekday + * + * @see http + * ://docs.spring.io/spring/docs/current/javadoc-api/org/springframework + * /scheduling/support/CronSequenceGenerator.html + */ + @Scheduled( + cron = "${batch.greeting.cron}") + public void cronJob() { + logger.info("> cronJob"); + + // Add scheduled logic here + + Collection greetings = greetingService.findAll(); + logger.info("There are {} greetings in the data store.", + greetings.size()); + + logger.info("< cronJob"); + } + + /** + * Execute logic beginning at fixed intervals. Use the + * fixedRate element to indicate how frequently the method is + * to be invoked. + */ + @Scheduled( + fixedRateString = "${batch.greeting.fixedrate}") + public void fixedRateJob() { + logger.info("> fixedRateJob"); + + // Add scheduled logic here + + Collection greetings = greetingService.findAll(); + logger.info("There are {} greetings in the data store.", + greetings.size()); + + logger.info("< fixedRateJob"); + } + + /** + * Execute logic beginning at fixed intervals with a delay after the + * application starts. Use the fixedRate element to indicate + * how frequently the method is to be invoked. Use the + * initialDelay element to indicate how long to wait after + * application startup to schedule the first execution. + */ + @Scheduled( + initialDelayString = "${batch.greeting.initialdelay}", + fixedRateString = "${batch.greeting.fixedrate}") + public void fixedRateJobWithInitialDelay() { + logger.info("> fixedRateJobWithInitialDelay"); + + // Add scheduled logic here + + Collection greetings = greetingService.findAll(); + logger.info("There are {} greetings in the data store.", + greetings.size()); + + logger.info("< fixedRateJobWithInitialDelay"); + } + + /** + * Execute logic with a delay between the end of the last execution and the + * beginning of the next. Use the fixedDelay element to + * indicate the time to wait between executions. + */ + @Scheduled( + fixedDelayString = "${batch.greeting.fixeddelay}") + public void fixedDelayJob() { + logger.info("> fixedDelayJob"); + + // Add scheduled logic here + + Collection greetings = greetingService.findAll(); + logger.info("There are {} greetings in the data store.", + greetings.size()); + + logger.info("< fixedDelayJob"); + } + + /** + * Execute logic with a delay between the end of the last execution and the + * beginning of the next. Use the fixedDelay element to + * indicate the time to wait between executions. Use the + * initialDelay element to indicate how long to wait after + * application startup to schedule the first execution. + */ + @Scheduled( + initialDelayString = "${batch.greeting.initialdelay}", + fixedDelayString = "${batch.greeting.fixeddelay}") + public void fixedDelayJobWithInitialDelay() { + logger.info("> fixedDelayJobWithInitialDelay"); + + // Add scheduled logic here + + Collection greetings = greetingService.findAll(); + logger.info("There are {} greetings in the data store.", + greetings.size()); + + logger.info("< fixedDelayJobWithInitialDelay"); + } + +} diff --git a/src/main/resources/config/application.properties b/src/main/resources/config/application.properties index b19e199..e244104 100644 --- a/src/main/resources/config/application.properties +++ b/src/main/resources/config/application.properties @@ -10,3 +10,14 @@ server.port= ## # Data Source Configuration ## + +# Initialization +spring.datasource.data=classpath:/data/hsqldb/data.sql + +## +# Batch Configuration +## +batch.greeting.fixedrate=360000 +batch.greeting.fixeddelay=360000 +batch.greeting.initialdelay=15000 +batch.greeting.cron=0 0 * * * * \ No newline at end of file diff --git a/src/main/resources/data/hsqldb/data.sql b/src/main/resources/data/hsqldb/data.sql new file mode 100644 index 0000000..55190bc --- /dev/null +++ b/src/main/resources/data/hsqldb/data.sql @@ -0,0 +1,2 @@ +INSERT INTO Greeting (text) VALUES ('Hello World!'); +INSERT INTO Greeting (text) VALUES ('Hola Mundo!'); \ No newline at end of file