├── .gitignore
├── README.md
├── async-processing
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── xpadro
│ │ └── spring
│ │ └── web
│ │ ├── MainApp.java
│ │ ├── controller
│ │ ├── AsyncCallableController.java
│ │ ├── AsyncDeferredController.java
│ │ └── BlockingController.java
│ │ └── service
│ │ ├── TaskService.java
│ │ └── TaskServiceImpl.java
│ └── webapp
│ └── WEB-INF
│ └── web.xml
├── rest-controlleradvice
├── .classpath
├── .gitignore
├── .project
├── .settings
│ ├── .jsdtscope
│ ├── org.eclipse.jdt.core.prefs
│ ├── org.eclipse.m2e.core.prefs
│ ├── org.eclipse.wst.common.component
│ ├── org.eclipse.wst.common.project.facet.core.xml
│ ├── org.eclipse.wst.jsdt.ui.superType.container
│ └── org.eclipse.wst.jsdt.ui.superType.name
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ ├── log4j.xml
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── rest
│ │ │ ├── controller
│ │ │ ├── AddPersonController.java
│ │ │ ├── GetPersonController.java
│ │ │ ├── UpdatePersonController.java
│ │ │ └── advice
│ │ │ │ └── CentralControllerHandler.java
│ │ │ ├── exception
│ │ │ └── PersonNotFoundException.java
│ │ │ ├── model
│ │ │ └── Person.java
│ │ │ ├── repository
│ │ │ ├── PersonRepository.java
│ │ │ └── impl
│ │ │ │ └── PersonRepositoryImpl.java
│ │ │ └── validator
│ │ │ └── PersonValidator.java
│ ├── resources
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── rest
│ │ │ └── configuration
│ │ │ ├── app-context.xml
│ │ │ └── root-context.xml
│ └── webapp
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ └── index.jsp
│ └── test
│ └── java
│ └── xpadro
│ └── spring
│ └── rest
│ └── client
│ └── PersonRestServiceTesting.java
├── rest-converters
├── .classpath
├── .gitignore
├── .project
├── .settings
│ ├── .jsdtscope
│ ├── org.eclipse.jdt.core.prefs
│ ├── org.eclipse.m2e.core.prefs
│ ├── org.eclipse.wst.common.component
│ ├── org.eclipse.wst.common.project.facet.core.xml
│ ├── org.eclipse.wst.jsdt.ui.superType.container
│ └── org.eclipse.wst.jsdt.ui.superType.name
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── rest
│ │ │ ├── controller
│ │ │ └── MvcRestController.java
│ │ │ ├── model
│ │ │ ├── Car.java
│ │ │ └── User.java
│ │ │ └── repository
│ │ │ ├── CarRepository.java
│ │ │ ├── UserRepository.java
│ │ │ └── impl
│ │ │ ├── CarRepositoryImpl.java
│ │ │ └── UserRepositoryImpl.java
│ ├── resources
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── rest
│ │ │ └── configuration
│ │ │ ├── app-context.xml
│ │ │ ├── db-context.xml
│ │ │ └── root-context.xml
│ └── webapp
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ └── index.jsp
│ └── test
│ └── java
│ └── xpadro
│ └── spring
│ └── rest
│ └── client
│ └── RestTesting.java
├── rest-subresources
├── .classpath
├── .gitignore
├── .project
├── .settings
│ ├── .jsdtscope
│ ├── org.eclipse.jdt.core.prefs
│ ├── org.eclipse.m2e.core.prefs
│ ├── org.eclipse.wst.common.component
│ ├── org.eclipse.wst.common.project.facet.core.xml
│ ├── org.eclipse.wst.jsdt.ui.superType.container
│ └── org.eclipse.wst.jsdt.ui.superType.name
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── xpadro
│ │ └── rest
│ │ └── ri
│ │ ├── model
│ │ ├── Item.java
│ │ ├── TypeAItem.java
│ │ └── TypeBItem.java
│ │ ├── repository
│ │ ├── TypeAItemRepository.java
│ │ └── TypeBItemRepository.java
│ │ └── resources
│ │ ├── ItemResource.java
│ │ ├── TypeAResource.java
│ │ ├── TypeBResource.java
│ │ └── WarehouseResource.java
│ └── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
├── rest_test
├── .classpath
├── .gitignore
├── .project
├── .settings
│ ├── .jsdtscope
│ ├── org.eclipse.jdt.core.prefs
│ ├── org.eclipse.wst.common.component
│ ├── org.eclipse.wst.common.project.facet.core.xml
│ ├── org.eclipse.wst.jsdt.ui.superType.container
│ ├── org.eclipse.wst.jsdt.ui.superType.name
│ └── org.maven.ide.eclipse.prefs
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ ├── log4j.xml
│ │ └── xpadro
│ │ │ └── tutorial
│ │ │ └── rest
│ │ │ ├── controller
│ │ │ └── WarehouseController.java
│ │ │ ├── exception
│ │ │ └── ProductNotFoundException.java
│ │ │ ├── model
│ │ │ ├── Product.java
│ │ │ └── Warehouse.java
│ │ │ └── repository
│ │ │ ├── WarehouseRepository.java
│ │ │ └── WarehouseRepositoryImpl.java
│ ├── resources
│ │ └── xpadro
│ │ │ └── tutorial
│ │ │ └── rest
│ │ │ └── configuration
│ │ │ ├── app-context.xml
│ │ │ └── root-context.xml
│ └── webapp
│ │ └── WEB-INF
│ │ └── web.xml
│ └── test
│ └── java
│ └── xpadro
│ └── tutorial
│ └── rest
│ └── client
│ └── TestWarehouse.java
├── spring-rest-api-v32
├── .classpath
├── .gitignore
├── .project
├── .settings
│ ├── .jsdtscope
│ ├── org.eclipse.jdt.core.prefs
│ ├── org.eclipse.m2e.core.prefs
│ ├── org.eclipse.wst.common.component
│ ├── org.eclipse.wst.common.project.facet.core.xml
│ ├── org.eclipse.wst.jsdt.ui.superType.container
│ ├── org.eclipse.wst.jsdt.ui.superType.name
│ └── org.eclipse.wst.validation.prefs
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ ├── log4j.xml
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── web
│ │ │ ├── controller
│ │ │ └── SeriesController.java
│ │ │ ├── model
│ │ │ └── Series.java
│ │ │ └── service
│ │ │ ├── SeriesService.java
│ │ │ └── impl
│ │ │ └── SeriesServiceImpl.java
│ ├── resources
│ │ └── xpadro
│ │ │ └── spring
│ │ │ └── web
│ │ │ └── configuration
│ │ │ ├── app-context.xml
│ │ │ ├── db-context.xml
│ │ │ └── root-context.xml
│ └── webapp
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ └── index.jsp
│ └── test
│ ├── java
│ └── xpadro
│ │ └── spring
│ │ └── web
│ │ └── test
│ │ ├── SeriesFunctionalTesting.java
│ │ └── SeriesIntegrationTesting.java
│ └── resources
│ └── xpadro
│ └── spring
│ └── web
│ └── test
│ └── configuration
│ └── test-root-context.xml
└── spring-rest-api-v4
├── .classpath
├── .gitignore
├── .project
├── .settings
├── .jsdtscope
├── org.eclipse.jdt.core.prefs
├── org.eclipse.m2e.core.prefs
├── org.eclipse.wst.common.component
├── org.eclipse.wst.common.project.facet.core.xml
├── org.eclipse.wst.jsdt.ui.superType.container
├── org.eclipse.wst.jsdt.ui.superType.name
└── org.eclipse.wst.validation.prefs
├── environment
└── development
│ └── workspace
│ └── spring-rest-api-v4
│ └── target
│ └── m2e-wtp
│ └── web-resources
│ └── .gitignore
├── pom.xml
└── src
├── main
├── java
│ ├── log4j.xml
│ └── xpadro
│ │ └── spring
│ │ └── web
│ │ ├── controller
│ │ └── SeriesController.java
│ │ ├── model
│ │ └── Series.java
│ │ └── service
│ │ ├── SeriesService.java
│ │ └── impl
│ │ └── SeriesServiceImpl.java
├── resources
│ └── xpadro
│ │ └── spring
│ │ └── web
│ │ └── configuration
│ │ ├── app-context.xml
│ │ ├── db-context.xml
│ │ └── root-context.xml
└── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
└── test
├── java
└── xpadro
│ └── spring
│ └── web
│ └── test
│ ├── SeriesAsyncCallableFunctionalTest.java
│ ├── SeriesAsyncFunctionalTest.java
│ ├── SeriesFunctionalBaseTests.java
│ ├── SeriesFunctionalTest.java
│ └── SeriesIntegrationTest.java
└── resources
└── xpadro
└── spring
└── web
└── test
└── configuration
└── test-root-context.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | spring-rest
2 | ===========
3 |
4 | Samples of RESTful web services using Spring MVC
5 |
6 | - rest_test: Implementation of RESTful web services using Spring MVC. The application controller contains several CRUD operations that are tested using the restTemplate class.
7 |
8 | Blog post related to this project:
9 | http://xpadro.com/2013/02/create-and-test-rest-services-with.html
10 |
11 |
12 | - rest-converters: This project shows how message converters work when using the RestTemplate class. Depending on which Object is returned by the controller, a different converter will be applied to the response body.
13 |
14 | Blog post related to this project:
15 | http://xpadro.com/2013/02/accessing-restful-services-http-message.html
16 |
17 |
18 | - rest-controlleradvice: Shows how to centralize exception handling from different controllers using the @ControllerAdvice annotation.
19 |
20 | Blog post related to this project:
21 | http://xpadro.com/2013/03/centralize-validation-and-exception.html
22 |
23 |
24 | - rest-subresources: This is a JAX-RS project that uses a subresource locator which decide at runtime what subresource will be returned.
25 |
26 | Blog post related to this project:
27 | http://xpadro.com/2013/05/handling-different-subresources-with.html
28 |
29 |
30 | - spring-rest-api-v32: A Spring MVC RESTful web application. This app implements a REST API which accesses a MongoDB database in order to handle data from TV series. It also contains examples on how to implement integration tests (mockMvc) and functional tests (restTemplate). This project has been implemented in Spring 3.2.3 version and has been used as a base to implement the spring-rest-api-v4 project (also in this repository).
31 |
32 | Blog post related to this project: N/A
33 |
34 |
35 | - spring-rest-api-v4: This project is the result of taking spring-rest-api-v32 (also in this repository) and upgrading it to version 4.0.0.RELEASE. It also contains some of the improvements included in this version of Spring, as commented in the blog entry.
36 |
37 | Blog post related to this project:
38 | http://xpadro.com/2014/01/migrating-spring-mvc-restful-web.html
39 |
--------------------------------------------------------------------------------
/async-processing/pom.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | 4.0.0
5 | xpadro.spring.web
6 | async-processing
7 | war
8 | 1.0-SNAPSHOT
9 | async-processing Maven Webapp
10 | http://maven.apache.org
11 |
12 |
13 | org.springframework.boot
14 | spring-boot-starter-parent
15 | 1.2.4.RELEASE
16 |
17 |
18 |
19 |
20 | org.springframework.boot
21 | spring-boot-starter-web
22 |
23 |
24 | org.springframework.boot
25 | spring-boot-starter-actuator
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-test
30 | test
31 |
32 |
33 |
34 |
35 | 1.8
36 |
37 |
38 |
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-maven-plugin
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/MainApp.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class MainApp {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(MainApp.class, args);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/controller/AsyncCallableController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.controller;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import xpadro.spring.web.service.TaskService;
10 |
11 | import java.util.concurrent.Callable;
12 |
13 | @RestController
14 | public class AsyncCallableController {
15 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
16 | private final TaskService taskService;
17 |
18 | @Autowired
19 | public AsyncCallableController(TaskService taskService) {
20 | this.taskService = taskService;
21 | }
22 |
23 | @RequestMapping(value = "/callable", method = RequestMethod.GET, produces = "text/html")
24 | public Callable executeSlowTask() {
25 | logger.info("Request received");
26 | Callable callable = taskService::execute;
27 | logger.info("Servlet thread released");
28 |
29 | return callable;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/controller/AsyncDeferredController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.controller;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import org.springframework.web.context.request.async.DeferredResult;
10 | import xpadro.spring.web.service.TaskService;
11 |
12 | import java.util.concurrent.CompletableFuture;
13 |
14 | @RestController
15 | public class AsyncDeferredController {
16 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
17 | private final TaskService taskService;
18 |
19 | @Autowired
20 | public AsyncDeferredController(TaskService taskService) {
21 | this.taskService = taskService;
22 | }
23 |
24 | @RequestMapping(value = "/deferred", method = RequestMethod.GET, produces = "text/html")
25 | public DeferredResult executeSlowTask() {
26 | logger.info("Request received");
27 | DeferredResult deferredResult = new DeferredResult<>();
28 | CompletableFuture.supplyAsync(taskService::execute)
29 | .whenCompleteAsync((result, throwable) -> deferredResult.setResult(result));
30 | logger.info("Servlet thread released");
31 |
32 | return deferredResult;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/controller/BlockingController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.controller;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.RestController;
9 | import xpadro.spring.web.service.TaskService;
10 |
11 | @RestController
12 | public class BlockingController {
13 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
14 | private final TaskService taskService;
15 |
16 | @Autowired
17 | public BlockingController(TaskService taskService) {
18 | this.taskService = taskService;
19 | }
20 |
21 | @RequestMapping(value = "/block", method = RequestMethod.GET, produces = "text/html")
22 | public String executeSlowTask() {
23 | logger.info("Request received");
24 | String result = taskService.execute();
25 | logger.info("Servlet thread released");
26 |
27 | return result;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/service/TaskService.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service;
2 |
3 | public interface TaskService {
4 |
5 | String execute();
6 | }
7 |
--------------------------------------------------------------------------------
/async-processing/src/main/java/xpadro/spring/web/service/TaskServiceImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.stereotype.Service;
6 |
7 | @Service
8 | public class TaskServiceImpl implements TaskService {
9 | private final Logger logger = LoggerFactory.getLogger(this.getClass());
10 |
11 | @Override
12 | public String execute() {
13 | try {
14 | Thread.sleep(5000);
15 | logger.info("Slow task executed");
16 | return "Task finished";
17 | } catch (InterruptedException e) {
18 | throw new RuntimeException();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/async-processing/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Asynchronous Processing with Spring
7 |
8 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.gitignore:
--------------------------------------------------------------------------------
1 | target
--------------------------------------------------------------------------------
/rest-controlleradvice/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | rest-controlleradvice
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.wst.validation.validationbuilder
25 |
26 |
27 |
28 |
29 | org.eclipse.m2e.core.maven2Builder
30 |
31 |
32 |
33 |
34 | org.springframework.ide.eclipse.core.springbuilder
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.ide.eclipse.core.springnature
41 | org.eclipse.jem.workbench.JavaEMFNature
42 | org.eclipse.wst.common.modulecore.ModuleCoreNature
43 | org.eclipse.jdt.core.javanature
44 | org.eclipse.m2e.core.maven2Nature
45 | org.eclipse.wst.common.project.facet.core.nature
46 | org.eclipse.wst.jsdt.core.jsNature
47 |
48 |
49 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.6
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
12 | org.eclipse.jdt.core.compiler.source=1.6
13 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/rest-controlleradvice/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/rest-controlleradvice/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | xpadro.spring.rest
5 | rest-controlleradvice
6 | war
7 | 0.0.1-SNAPSHOT
8 | rest-controlleradvice Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 3.2.1.RELEASE
13 | 2.5
14 | 1.2
15 | 1.2.14
16 | 4.8.1
17 | 1.4.2
18 | 4.3.1.Final
19 |
20 |
21 |
22 |
23 |
24 | org.springframework
25 | spring-context
26 | ${spring.version}
27 |
28 |
29 | org.springframework
30 | spring-webmvc
31 | ${spring.version}
32 |
33 |
34 | org.springframework
35 | spring-web
36 | ${spring.version}
37 |
38 |
39 |
40 |
41 | javax.servlet
42 | servlet-api
43 | ${servlet.version}
44 | provided
45 |
46 |
47 | javax.servlet
48 | jstl
49 | ${jstl.version}
50 |
51 |
52 |
53 |
54 | log4j
55 | log4j
56 | ${log4j.version}
57 |
58 |
59 |
60 |
61 | org.springframework
62 | spring-test
63 | ${spring.version}
64 |
65 |
66 | junit
67 | junit
68 | ${junit.version}
69 |
70 |
71 |
72 |
73 | org.codehaus.jackson
74 | jackson-mapper-asl
75 | 1.4.2
76 |
77 |
78 |
79 | org.hibernate
80 | hibernate-validator
81 | ${hibernate.version}
82 |
83 |
84 |
85 |
86 | rest-controlleradvice
87 |
88 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/controller/AddPersonController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 | import javax.validation.Valid;
6 |
7 | import org.apache.log4j.Logger;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RequestMethod;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 |
16 | import xpadro.spring.rest.model.Person;
17 | import xpadro.spring.rest.repository.PersonRepository;
18 |
19 | /**
20 | * Adds a new person
21 | * @author xpadro
22 | *
23 | */
24 | @Controller
25 | public class AddPersonController {
26 | private static Logger logger = Logger.getLogger("main");
27 |
28 | @Autowired
29 | private PersonRepository personRepository;
30 |
31 | /**
32 | * CREATE operation. Adds a new person
33 | * @param person
34 | * @param request
35 | * @param response
36 | */
37 | @RequestMapping(value="/persons", method=RequestMethod.POST)
38 | @ResponseStatus(HttpStatus.CREATED)
39 | public void addPerson(@Valid @RequestBody Person person, HttpServletRequest request, HttpServletResponse response) {
40 | personRepository.addPerson(person);
41 | logger.info("Person added: "+person.getId());
42 | response.setHeader("Location", request.getRequestURL().append("/").append(person.getId()).toString());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/controller/GetPersonController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.controller;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.web.bind.annotation.PathVariable;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 |
10 | import xpadro.spring.rest.model.Person;
11 | import xpadro.spring.rest.repository.PersonRepository;
12 |
13 | /**
14 | * Returns an existing person
15 | * @author xpadro
16 | *
17 | */
18 | @Controller
19 | public class GetPersonController {
20 | @Autowired
21 | private PersonRepository personRepository;
22 |
23 | /**
24 | * READ operation. Returns an existing person
25 | * @param id
26 | * @return
27 | */
28 | @RequestMapping(value="/persons/{personId}", method=RequestMethod.GET)
29 | public @ResponseBody Person getPerson(@PathVariable("personId") long id) {
30 | return personRepository.getPerson(id);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/controller/UpdatePersonController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 | import javax.validation.Valid;
6 |
7 | import org.apache.log4j.Logger;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RequestMethod;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 |
16 | import xpadro.spring.rest.model.Person;
17 | import xpadro.spring.rest.repository.PersonRepository;
18 |
19 | /**
20 | * Modifies an existing person
21 | * @author xpadro
22 | *
23 | */
24 | @Controller
25 | public class UpdatePersonController {
26 | private static Logger logger = Logger.getLogger("main");
27 |
28 | @Autowired
29 | private PersonRepository personRepository;
30 |
31 | /**
32 | * UPDATE operation. Modifies an existing person
33 | * @param person
34 | * @param request
35 | * @param response
36 | */
37 | @RequestMapping(value="/persons", method=RequestMethod.PUT)
38 | @ResponseStatus(HttpStatus.CREATED)
39 | public void updatePerson(@Valid @RequestBody Person person, HttpServletRequest request, HttpServletResponse response) {
40 | personRepository.updatePerson(person);
41 | logger.info("Person updated: "+person.getId());
42 | response.setHeader("Location", request.getRequestURL().append("/").append(person.getId()).toString());
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/controller/advice/CentralControllerHandler.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.controller.advice;
2 |
3 | import org.springframework.http.HttpStatus;
4 | import org.springframework.http.ResponseEntity;
5 | import org.springframework.web.bind.MethodArgumentNotValidException;
6 | import org.springframework.web.bind.WebDataBinder;
7 | import org.springframework.web.bind.annotation.ControllerAdvice;
8 | import org.springframework.web.bind.annotation.ExceptionHandler;
9 | import org.springframework.web.bind.annotation.InitBinder;
10 |
11 | import xpadro.spring.rest.exception.PersonNotFoundException;
12 | import xpadro.spring.rest.validator.PersonValidator;
13 |
14 | @ControllerAdvice
15 | public class CentralControllerHandler {
16 |
17 | @InitBinder
18 | public void initBinder(WebDataBinder binder) {
19 | binder.setValidator(new PersonValidator());
20 | }
21 |
22 | @ExceptionHandler({PersonNotFoundException.class})
23 | public ResponseEntity handlePersonNotFound(PersonNotFoundException pe) {
24 | return new ResponseEntity(pe.getMessage(), HttpStatus.NOT_FOUND);
25 | }
26 |
27 | @ExceptionHandler({MethodArgumentNotValidException.class})
28 | public ResponseEntity handleValidationException(MethodArgumentNotValidException pe) {
29 | return new ResponseEntity(pe.getMessage(), HttpStatus.BAD_REQUEST);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/exception/PersonNotFoundException.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.exception;
2 |
3 | /**
4 | * Exception to be thrown when trying to get a non existent person
5 | * @author xpadro
6 | *
7 | */
8 | public class PersonNotFoundException extends RuntimeException {
9 | private static final long serialVersionUID = -3845574518872003019L;
10 |
11 | public PersonNotFoundException() {
12 | super();
13 | }
14 |
15 | public PersonNotFoundException(String message) {
16 | super(message);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/model/Person.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.model;
2 |
3 |
4 | public class Person {
5 |
6 | private long id;
7 | private String name;
8 | private String surname;
9 | private String city;
10 |
11 | public Person() {}
12 |
13 | public Person(long id, String name, String surname, String city) {
14 | this.id = id;
15 | this.name = name;
16 | this.surname = surname;
17 | this.city = city;
18 | }
19 |
20 |
21 | /**
22 | * @return the id
23 | */
24 | public long getId() {
25 | return id;
26 | }
27 |
28 | /**
29 | * @param id the id to set
30 | */
31 | public void setId(long id) {
32 | this.id = id;
33 | }
34 |
35 | /**
36 | * @return the name
37 | */
38 | public String getName() {
39 | return name;
40 | }
41 |
42 | /**
43 | * @param name the name to set
44 | */
45 | public void setName(String name) {
46 | this.name = name;
47 | }
48 |
49 | /**
50 | * @return the surname
51 | */
52 | public String getSurname() {
53 | return surname;
54 | }
55 |
56 | /**
57 | * @param surname the surname to set
58 | */
59 | public void setSurname(String surname) {
60 | this.surname = surname;
61 | }
62 |
63 | /**
64 | * @return the city
65 | */
66 | public String getCity() {
67 | return city;
68 | }
69 |
70 | /**
71 | * @param city the city to set
72 | */
73 | public void setCity(String city) {
74 | this.city = city;
75 | }
76 |
77 | /* (non-Javadoc)
78 | * @see java.lang.Object#hashCode()
79 | */
80 | @Override
81 | public int hashCode() {
82 | final int prime = 31;
83 | int result = 1;
84 | result = prime * result + ((city == null) ? 0 : city.hashCode());
85 | result = prime * result + (int) (id ^ (id >>> 32));
86 | result = prime * result + ((name == null) ? 0 : name.hashCode());
87 | result = prime * result + ((surname == null) ? 0 : surname.hashCode());
88 | return result;
89 | }
90 |
91 | /* (non-Javadoc)
92 | * @see java.lang.Object#equals(java.lang.Object)
93 | */
94 | @Override
95 | public boolean equals(Object obj) {
96 | if (this == obj)
97 | return true;
98 | if (obj == null)
99 | return false;
100 | if (getClass() != obj.getClass())
101 | return false;
102 | Person other = (Person) obj;
103 | if (city == null) {
104 | if (other.city != null)
105 | return false;
106 | } else if (!city.equals(other.city))
107 | return false;
108 | if (id != other.id)
109 | return false;
110 | if (name == null) {
111 | if (other.name != null)
112 | return false;
113 | } else if (!name.equals(other.name))
114 | return false;
115 | if (surname == null) {
116 | if (other.surname != null)
117 | return false;
118 | } else if (!surname.equals(other.surname))
119 | return false;
120 | return true;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/repository/PersonRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository;
2 |
3 | import xpadro.spring.rest.exception.PersonNotFoundException;
4 | import xpadro.spring.rest.model.Person;
5 |
6 | /**
7 | * Manages data from persons
8 | * @author xpadro
9 | *
10 | */
11 | public interface PersonRepository {
12 |
13 | /**
14 | * Returns the person identified by the id
15 | * @param id
16 | * @return the person
17 | * @throws PersonNotFoundException if no person is found with specified id
18 | */
19 | public Person getPerson(long id);
20 |
21 | /**
22 | * Adds a new person
23 | * @param person
24 | */
25 | public void addPerson(Person person);
26 |
27 | /**
28 | * Modifies an existing person
29 | * @param person
30 | * @throws PersonNotFoundException if no person is found with specified id
31 | */
32 | public void updatePerson(Person person);
33 | }
34 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/repository/impl/PersonRepositoryImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository.impl;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import org.springframework.stereotype.Repository;
7 |
8 | import xpadro.spring.rest.exception.PersonNotFoundException;
9 | import xpadro.spring.rest.model.Person;
10 | import xpadro.spring.rest.repository.PersonRepository;
11 |
12 | @Repository
13 | public class PersonRepositoryImpl implements PersonRepository {
14 | private Map persons;
15 |
16 | public PersonRepositoryImpl() {
17 | persons = new HashMap();
18 | createDummyPersons();
19 | }
20 |
21 | @Override
22 | public Person getPerson(long id) {
23 | Person person = persons.get(id);
24 | if (person == null) {
25 | throw new PersonNotFoundException("No person found with id "+id);
26 | }
27 |
28 | return person;
29 | }
30 |
31 | @Override
32 | public void addPerson(Person person) {
33 | persons.put(person.getId(), person);
34 | }
35 |
36 | private void createDummyPersons() {
37 | Person person = new Person(1, "Xavi", "Padro", "Barcelona");
38 | persons.put(1l, person);
39 | }
40 |
41 | @Override
42 | public void updatePerson(Person person) {
43 | if (persons.get(person.getId()) == null) {
44 | throw new PersonNotFoundException("No person found with id "+person.getId());
45 | }
46 | persons.put(person.getId(), person);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/java/xpadro/spring/rest/validator/PersonValidator.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.validator;
2 |
3 | import org.springframework.validation.Errors;
4 | import org.springframework.validation.ValidationUtils;
5 | import org.springframework.validation.Validator;
6 |
7 | import xpadro.spring.rest.model.Person;
8 |
9 | /**
10 | * Validates that a person is from a registered city
11 | * @author xpadro
12 | *
13 | */
14 | public class PersonValidator implements Validator {
15 |
16 | public boolean supports(Class> clazz) {
17 | return clazz.equals(Person.class);
18 | }
19 |
20 | public void validate(Object target, Errors errors) {
21 | Person person = (Person) target;
22 |
23 | ValidationUtils.rejectIfEmpty(errors, "city", "city.empty");
24 | if (!"Barcelona".equals(person.getCity()) && !"Liverpool".equals(person.getCity())) {
25 | errors.rejectValue("city", "city.not.valid", "Invalid city: "+person.getCity());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/resources/xpadro/spring/rest/configuration/app-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/resources/xpadro/spring/rest/configuration/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | SpringRestControllerAdvice
4 |
5 |
6 |
7 | contextConfigLocation
8 | classpath:xpadro/spring/rest/configuration/root-context.xml
9 |
10 |
11 |
12 |
13 | org.springframework.web.context.ContextLoaderListener
14 |
15 |
16 |
17 |
18 | springServlet
19 | org.springframework.web.servlet.DispatcherServlet
20 |
21 | contextConfigLocation
22 | classpath:xpadro/spring/rest/configuration/app-context.xml
23 |
24 |
25 |
26 | springServlet
27 | /spring/*
28 |
29 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | @ControllerAdvice sample
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rest-controlleradvice/src/test/java/xpadro/spring/rest/client/PersonRestServiceTesting.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.client;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import java.net.URI;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.test.context.ContextConfiguration;
12 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13 | import org.springframework.web.client.HttpClientErrorException;
14 | import org.springframework.web.client.RestTemplate;
15 |
16 | import xpadro.spring.rest.model.Person;
17 |
18 | @RunWith(SpringJUnit4ClassRunner.class)
19 | @ContextConfiguration(locations={
20 | "classpath:xpadro/spring/rest/configuration/root-context.xml",
21 | "classpath:xpadro/spring/rest/configuration/app-context.xml"})
22 | public class PersonRestServiceTesting {
23 | private RestTemplate restTemplate = new RestTemplate();
24 |
25 |
26 | /**
27 | * Tests retrieving an existing person
28 | */
29 | @Test
30 | public void getExistingPerson() {
31 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons/{personId}";
32 | Person person = restTemplate.getForObject(uri, Person.class, 1l);
33 | assertNotNull(person);
34 | assertEquals("Xavi", person.getName());
35 | }
36 |
37 | /**
38 | * Tests error handling when trying to retrieve a non existent person
39 | */
40 | @Test
41 | public void getNonExistingPerson() {
42 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons/{personId}";
43 | try {
44 | restTemplate.getForObject(uri, Person.class, 5l);
45 | throw new AssertionError("Should have returned an 404 error code");
46 | } catch (HttpClientErrorException e) {
47 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
48 | }
49 | }
50 |
51 | /**
52 | * Tests the addition of a new person
53 | */
54 | @Test
55 | public void addValidPerson() {
56 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons";
57 | Person person = new Person(2l, "John", "Lennon", "Liverpool");
58 | URI newPersonLocation = restTemplate.postForLocation(uri, person, 2l);
59 |
60 | Person createdPerson = restTemplate.getForObject(newPersonLocation, Person.class);
61 | assertEquals(person, createdPerson);
62 | assertNotNull(createdPerson.getId());
63 | assertEquals("John", person.getName());
64 | }
65 |
66 | /**
67 | * Tests error handling when trying to add a person with invalid data
68 | */
69 | @Test
70 | public void addInvalidPerson() {
71 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons";
72 | Person person = new Person(3l, "James", "Steward", "London");
73 | try {
74 | restTemplate.postForLocation(uri, person, 3l);
75 | throw new AssertionError("Should have returned an 400 error code");
76 | } catch (HttpClientErrorException e) {
77 | assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
78 | }
79 | }
80 |
81 | /**
82 | * Tests updating an existing person
83 | */
84 | @Test
85 | public void updateValidPerson() {
86 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons";
87 | Person person = new Person(2l, "George", "Harrison", "Liverpool");
88 | restTemplate.put(uri, person, 2l);
89 |
90 | uri = "http://localhost:8081/rest-controlleradvice/spring/persons/{personId}";
91 | Person createdPerson = restTemplate.getForObject(uri, Person.class, 2l);
92 | assertEquals(person, createdPerson);
93 | assertNotNull(createdPerson.getId());
94 | assertEquals("George", person.getName());
95 | }
96 |
97 | /**
98 | * Tests error handling when trying to update an existing person with invalid data
99 | */
100 | @Test
101 | public void updateInvalidPerson() {
102 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons";
103 | Person person = new Person(2l, "John", "Smith", "New York");
104 | try {
105 | restTemplate.put(uri, person, 2l);
106 | throw new AssertionError("Should have returned an 400 error code");
107 | } catch (HttpClientErrorException e) {
108 | assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode());
109 | }
110 | }
111 |
112 | /**
113 | * Tests error handling when trying to update a non existing person
114 | */
115 | @Test
116 | public void updateNonExistingPerson() {
117 | String uri = "http://localhost:8081/rest-controlleradvice/spring/persons";
118 | Person person = new Person(5l, "Marc", "Brown", "Barcelona");
119 | try {
120 | restTemplate.put(uri, person, 5l);
121 | throw new AssertionError("Should have returned an 404 error code");
122 | } catch (HttpClientErrorException e) {
123 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/rest-converters/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/rest-converters/.gitignore:
--------------------------------------------------------------------------------
1 | target
--------------------------------------------------------------------------------
/rest-converters/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | rest-converters
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.wst.validation.validationbuilder
25 |
26 |
27 |
28 |
29 | org.eclipse.m2e.core.maven2Builder
30 |
31 |
32 |
33 |
34 | org.springframework.ide.eclipse.core.springbuilder
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.ide.eclipse.core.springnature
41 | org.eclipse.jem.workbench.JavaEMFNature
42 | org.eclipse.wst.common.modulecore.ModuleCoreNature
43 | org.eclipse.jdt.core.javanature
44 | org.eclipse.m2e.core.maven2Nature
45 | org.eclipse.wst.common.project.facet.core.nature
46 | org.eclipse.wst.jsdt.core.jsNature
47 |
48 |
49 |
--------------------------------------------------------------------------------
/rest-converters/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.compliance=1.6
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.6
9 |
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/rest-converters/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/rest-converters/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | xpadro.spring.rest
5 | rest-converters
6 | war
7 | 0.0.1-SNAPSHOT
8 | rest-converters Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 3.2.1.RELEASE
13 | 1.3.3.RELEASE
14 | 2.5
15 | 1.2
16 | 1.2.14
17 | 4.8.1
18 | 1.4.2
19 |
20 |
21 |
22 |
23 |
24 | org.springframework
25 | spring-context
26 | ${spring.version}
27 |
28 |
29 | org.springframework
30 | spring-webmvc
31 | ${spring.version}
32 |
33 |
34 | org.springframework
35 | spring-web
36 | ${spring.version}
37 |
38 |
39 |
40 |
41 | org.springframework.data
42 | spring-data-mongodb
43 | ${spring.mongo.version}
44 |
45 |
46 |
47 |
48 |
49 | javax.servlet
50 | servlet-api
51 | ${servlet.version}
52 | provided
53 |
54 |
55 | javax.servlet
56 | jstl
57 | ${jstl.version}
58 |
59 |
60 |
61 |
62 | log4j
63 | log4j
64 | ${log4j.version}
65 |
66 |
67 |
68 |
69 | org.springframework
70 | spring-test
71 | ${spring.version}
72 |
73 |
74 | junit
75 | junit
76 | ${junit.version}
77 |
78 |
79 |
80 |
81 | org.codehaus.jackson
82 | jackson-mapper-asl
83 | 1.4.2
84 |
85 |
86 |
87 | rest-converters
88 |
89 |
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/controller/MvcRestController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 |
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.stereotype.Controller;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RequestBody;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RequestMethod;
13 | import org.springframework.web.bind.annotation.ResponseBody;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 |
16 | import xpadro.spring.rest.model.Car;
17 | import xpadro.spring.rest.model.User;
18 | import xpadro.spring.rest.repository.CarRepository;
19 | import xpadro.spring.rest.repository.UserRepository;
20 |
21 | @Controller
22 | public class MvcRestController {
23 | @Autowired
24 | private UserRepository userRepository;
25 |
26 | @Autowired
27 | private CarRepository carRepository;
28 |
29 |
30 | /**
31 | * Returns the requested user by its id.
32 | * The response will be converted to JSON
33 | * @param id
34 | * @return The requested user
35 | */
36 | @RequestMapping(value="/users/{userId}", method=RequestMethod.GET)
37 | public @ResponseBody User getUser(@PathVariable("userId") long id) {
38 | return userRepository.getUser(id);
39 | }
40 |
41 |
42 | /**
43 | * Returns the name of the requested user.
44 | * The response will be converted to String
45 | * @param id
46 | * @return
47 | */
48 | @RequestMapping(value="/usernames/{userId}", method=RequestMethod.GET)
49 | public @ResponseBody String getUsername(@PathVariable("userId") long id) {
50 | StringBuilder result = new StringBuilder();
51 | User user = userRepository.getUser(id);
52 | return result.append(user.getName()).append(" ").append(user.getSurname()).toString();
53 | }
54 |
55 | /**
56 | * Returns the requested car by its id.
57 | * The response will be converted to XML
58 | * @param id
59 | * @return
60 | */
61 | @RequestMapping(value="/cars/{carId}", method=RequestMethod.GET)
62 | public @ResponseBody Car getCar(@PathVariable("carId") long id) {
63 | return carRepository.getCar(id);
64 | }
65 |
66 | /**
67 | * Inserts a new user to the DB
68 | * @param user
69 | * @param request
70 | * @param response
71 | */
72 | @RequestMapping(value="/users", method=RequestMethod.POST)
73 | @ResponseStatus(HttpStatus.CREATED)
74 | public void insertUser(@RequestBody User user, HttpServletRequest request, HttpServletResponse response) {
75 | userRepository.insertUser(user);
76 | response.setHeader("Location", request.getRequestURL().append("/").append(user.getId()).toString());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/model/Car.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.model;
2 |
3 | import java.io.Serializable;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | @XmlRootElement(name="car")
9 | public class Car implements Serializable {
10 | private static final long serialVersionUID = -4143762939567940616L;
11 | private long id;
12 | private String brand;
13 | private String model;
14 |
15 | public Car() { }
16 |
17 | public Car(long id, String brand, String model) {
18 | this.id = id;
19 | this.brand = brand;
20 | this.model = model;
21 | }
22 |
23 | @XmlElement
24 | public long getId() {
25 | return id;
26 | }
27 |
28 | public void setId(long id) {
29 | this.id = id;
30 | }
31 |
32 | @XmlElement
33 | public String getBrand() {
34 | return brand;
35 | }
36 |
37 | public void setBrand(String brand) {
38 | this.brand = brand;
39 | }
40 |
41 | @XmlElement
42 | public String getModel() {
43 | return model;
44 | }
45 |
46 | public void setModel(String model) {
47 | this.model = model;
48 | }
49 | }
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/model/User.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.model;
2 |
3 | import java.io.Serializable;
4 |
5 | public class User implements Serializable {
6 |
7 | private static final long serialVersionUID = -149936843837396000L;
8 | private long id;
9 | private String name;
10 | private String surname;
11 |
12 | public User() {}
13 |
14 | public User(long id, String name, String surname) {
15 | this.id = id;
16 | this.name = name;
17 | this.surname = surname;
18 | }
19 |
20 | /**
21 | * @return the id
22 | */
23 | public long getId() {
24 | return id;
25 | }
26 | /**
27 | * @param id the id to set
28 | */
29 | public void setId(long id) {
30 | this.id = id;
31 | }
32 | /**
33 | * @return the name
34 | */
35 | public String getName() {
36 | return name;
37 | }
38 | /**
39 | * @param name the name to set
40 | */
41 | public void setName(String name) {
42 | this.name = name;
43 | }
44 | /**
45 | * @return the surname
46 | */
47 | public String getSurname() {
48 | return surname;
49 | }
50 | /**
51 | * @param surname the surname to set
52 | */
53 | public void setSurname(String surname) {
54 | this.surname = surname;
55 | }
56 |
57 | /* (non-Javadoc)
58 | * @see java.lang.Object#hashCode()
59 | */
60 | @Override
61 | public int hashCode() {
62 | final int prime = 31;
63 | int result = 1;
64 | result = prime * result + (int) (id ^ (id >>> 32));
65 | result = prime * result + ((name == null) ? 0 : name.hashCode());
66 | result = prime * result + ((surname == null) ? 0 : surname.hashCode());
67 | return result;
68 | }
69 |
70 | /* (non-Javadoc)
71 | * @see java.lang.Object#equals(java.lang.Object)
72 | */
73 | @Override
74 | public boolean equals(Object obj) {
75 | if (this == obj)
76 | return true;
77 | if (obj == null)
78 | return false;
79 | if (getClass() != obj.getClass())
80 | return false;
81 | User other = (User) obj;
82 | if (id != other.id)
83 | return false;
84 | if (name == null) {
85 | if (other.name != null)
86 | return false;
87 | } else if (!name.equals(other.name))
88 | return false;
89 | if (surname == null) {
90 | if (other.surname != null)
91 | return false;
92 | } else if (!surname.equals(other.surname))
93 | return false;
94 | return true;
95 | }
96 |
97 | /* (non-Javadoc)
98 | * @see java.lang.Object#toString()
99 | */
100 | @Override
101 | public String toString() {
102 | return "User [id=" + id + ", name=" + name + ", surname=" + surname
103 | + "]";
104 | }
105 | }
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/repository/CarRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository;
2 |
3 | import xpadro.spring.rest.model.Car;
4 |
5 |
6 | /**
7 | * Manages data from cars
8 | * @author xpadro
9 | *
10 | */
11 | public interface CarRepository {
12 |
13 | /**
14 | * Returns the car identified by the id
15 | * @param id
16 | * @return the car
17 | */
18 | public Car getCar(long id);
19 | }
20 |
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository;
2 |
3 | import xpadro.spring.rest.model.User;
4 |
5 | /**
6 | * Manages data from users
7 | * @author xpadro
8 | *
9 | */
10 | public interface UserRepository {
11 |
12 | /**
13 | * Returns the user identified by the id
14 | * @param id
15 | * @return the user
16 | */
17 | public User getUser(long id);
18 |
19 | /**
20 | * Inserts a user into the DB
21 | * @param user
22 | */
23 | public void insertUser(User user);
24 | }
25 |
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/repository/impl/CarRepositoryImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository.impl;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.data.mongodb.core.MongoOperations;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import xpadro.spring.rest.model.Car;
8 | import xpadro.spring.rest.repository.CarRepository;
9 |
10 | @Repository
11 | public class CarRepositoryImpl implements CarRepository {
12 | @Autowired
13 | private MongoOperations mongoOps;
14 |
15 | @Override
16 | public Car getCar(long id) {
17 | return mongoOps.findById(1, Car.class);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/rest-converters/src/main/java/xpadro/spring/rest/repository/impl/UserRepositoryImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.repository.impl;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.data.mongodb.core.MongoOperations;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import xpadro.spring.rest.model.User;
8 | import xpadro.spring.rest.repository.UserRepository;
9 |
10 | @Repository
11 | public class UserRepositoryImpl implements UserRepository {
12 | @Autowired
13 | private MongoOperations mongoOps;
14 |
15 | @Override
16 | public User getUser(long id) {
17 | return mongoOps.findById(id, User.class);
18 | }
19 |
20 | @Override
21 | public void insertUser(User user) {
22 | mongoOps.insert(user);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/rest-converters/src/main/resources/xpadro/spring/rest/configuration/app-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/rest-converters/src/main/resources/xpadro/spring/rest/configuration/db-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/rest-converters/src/main/resources/xpadro/spring/rest/configuration/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/rest-converters/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | SpringRestConverters
4 |
5 |
6 |
7 | contextConfigLocation
8 | classpath:xpadro/spring/rest/configuration/root-context.xml
9 |
10 |
11 |
12 |
13 | org.springframework.web.context.ContextLoaderListener
14 |
15 |
16 |
17 |
18 | springServlet
19 | org.springframework.web.servlet.DispatcherServlet
20 |
21 | contextConfigLocation
22 | classpath:xpadro/spring/rest/configuration/app-context.xml
23 |
24 |
25 |
26 | springServlet
27 | /spring/*
28 |
29 |
--------------------------------------------------------------------------------
/rest-converters/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rest-converters/src/test/java/xpadro/spring/rest/client/RestTesting.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.rest.client;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import java.net.URI;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import org.junit.Before;
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.data.mongodb.core.MongoOperations;
15 | import org.springframework.http.converter.HttpMessageConverter;
16 | import org.springframework.http.converter.StringHttpMessageConverter;
17 | import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
18 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
19 | import org.springframework.test.context.ContextConfiguration;
20 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
21 | import org.springframework.web.client.RestTemplate;
22 |
23 | import xpadro.spring.rest.model.Car;
24 | import xpadro.spring.rest.model.User;
25 |
26 | @RunWith(SpringJUnit4ClassRunner.class)
27 | @ContextConfiguration(locations={
28 | "classpath:xpadro/spring/rest/configuration/root-context.xml",
29 | "classpath:xpadro/spring/rest/configuration/app-context.xml"})
30 | public class RestTesting {
31 | private static final String BASE_URI = "http://localhost:8080/rest-converters/spring/";
32 | private RestTemplate restTemplate = new RestTemplate();
33 |
34 | @Autowired
35 | private MongoOperations mongoOps;
36 |
37 | @Before
38 | public void setup() {
39 | List> converters = new ArrayList>();
40 | converters.add(new StringHttpMessageConverter());
41 | converters.add(new Jaxb2RootElementHttpMessageConverter());
42 | converters.add(new MappingJacksonHttpMessageConverter());
43 | restTemplate.setMessageConverters(converters);
44 |
45 | initializeDatabase();
46 | }
47 |
48 | private void initializeDatabase() {
49 | mongoOps.dropCollection("user");
50 | mongoOps.dropCollection("car");
51 |
52 | mongoOps.insert(new User(1, "Xavi", "Padro"));
53 | mongoOps.insert(new Car(1, "Ferrari", "GTO"));
54 | }
55 |
56 |
57 | /**
58 | * Tests accessing to an existing user
59 | * This test should use the MappingJacksonHttpMessageConverter
60 | */
61 | @Test
62 | public void getUser() {
63 | String uri = BASE_URI + "users/{userId}";
64 | User user = restTemplate.getForObject(uri, User.class, 1l);
65 | assertNotNull(user);
66 | assertEquals("Xavi", user.getName());
67 | }
68 |
69 | /**
70 | * Tests accessing to an existing user
71 | * This test should use the StringHttpMessageConverter
72 | */
73 | @Test
74 | public void getUserName() {
75 | String uri = BASE_URI + "usernames/{userId}";
76 | String username = restTemplate.getForObject(uri, String.class, 1l);
77 | assertNotNull(username);
78 | assertEquals("Xavi Padro", username);
79 | }
80 |
81 | /**
82 | * Tests accessing to an existing car
83 | * This test should use the Jaxb2RootElementHttpMessageConverter
84 | */
85 | @Test
86 | public void getCar() {
87 | String uri = BASE_URI + "cars/{carId}";
88 | Car car = restTemplate.getForObject(uri, Car.class, 1l);
89 | assertNotNull(car);
90 | assertEquals("Ferrari", car.getBrand());
91 | }
92 |
93 | /**
94 | * Tests a new user insertion
95 | */
96 | @Test
97 | public void insertUser() {
98 | String uri = BASE_URI + "users";
99 | User user = new User(2, "John", "Smith");
100 | URI newUserLocation = restTemplate.postForLocation(uri, user);
101 | assertEquals("http://localhost:8080/rest-converters/spring/users/2", newUserLocation.toString());
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/rest-subresources/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/rest-subresources/.gitignore:
--------------------------------------------------------------------------------
1 | target
--------------------------------------------------------------------------------
/rest-subresources/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | rest-subresources
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.wst.validation.validationbuilder
25 |
26 |
27 |
28 |
29 | org.eclipse.m2e.core.maven2Builder
30 |
31 |
32 |
33 |
34 |
35 | org.eclipse.jem.workbench.JavaEMFNature
36 | org.eclipse.wst.common.modulecore.ModuleCoreNature
37 | org.eclipse.jdt.core.javanature
38 | org.eclipse.m2e.core.maven2Nature
39 | org.eclipse.wst.common.project.facet.core.nature
40 | org.eclipse.wst.jsdt.core.jsNature
41 |
42 |
43 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
4 | org.eclipse.jdt.core.compiler.compliance=1.5
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.5
9 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/rest-subresources/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/rest-subresources/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | xpadro.rest.ri
5 | rest-subresources
6 | war
7 | 0.0.1-SNAPSHOT
8 | rest-subresources Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 1.17.1
13 |
14 |
15 |
16 |
17 | com.sun.jersey
18 | jersey-server
19 | ${jersey.version}
20 |
21 |
22 | com.sun.jersey
23 | jersey-servlet
24 | ${jersey.version}
25 |
26 |
27 | com.sun.jersey
28 | jersey-json
29 | ${jersey.version}
30 |
31 |
32 |
33 | rest-subresources
34 |
35 |
36 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/model/Item.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.model;
2 |
3 | import java.io.Serializable;
4 |
5 | public class Item implements Serializable {
6 | private static final long serialVersionUID = 1L;
7 | private int id;
8 | private float price;
9 | private String type;
10 |
11 |
12 | public Item() {}
13 |
14 | public Item(int id, float price, String type) {
15 | this.id = id;
16 | this.price = price;
17 | this.type = type;
18 | }
19 |
20 |
21 | /**
22 | * @return the id
23 | */
24 | public int getId() {
25 | return id;
26 | }
27 | /**
28 | * @param id the id to set
29 | */
30 | public void setId(int id) {
31 | this.id = id;
32 | }
33 |
34 | /**
35 | * @return the price
36 | */
37 | public float getPrice() {
38 | return price;
39 | }
40 |
41 | /**
42 | * @param price the price to set
43 | */
44 | public void setPrice(float price) {
45 | this.price = price;
46 | }
47 |
48 | /**
49 | * @return the type
50 | */
51 | public String getType() {
52 | return type;
53 | }
54 |
55 | /**
56 | * @param type the type to set
57 | */
58 | public void setType(String type) {
59 | this.type = type;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/model/TypeAItem.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.model;
2 |
3 | public class TypeAItem extends Item {
4 | private static final long serialVersionUID = 1L;
5 | private String code;
6 |
7 | public TypeAItem() {}
8 |
9 | public TypeAItem(int id, float price, String code) {
10 | super(id, price, "A");
11 | this.code = code;
12 | }
13 |
14 | /**
15 | * @return the code
16 | */
17 | public String getCode() {
18 | return code;
19 | }
20 |
21 | /**
22 | * @param code the code to set
23 | */
24 | public void setCode(String code) {
25 | this.code = code;
26 | }
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/model/TypeBItem.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.model;
2 |
3 | public class TypeBItem extends Item {
4 | private static final long serialVersionUID = 1L;
5 |
6 | public TypeBItem() {}
7 |
8 | public TypeBItem(int id, float price) {
9 | super(id, price, "B");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/repository/TypeAItemRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.repository;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import xpadro.rest.ri.model.TypeAItem;
7 |
8 | public class TypeAItemRepository {
9 | private Map items;
10 |
11 | public TypeAItemRepository() {
12 | items = new HashMap();
13 | items.put(11, new TypeAItem(11, 50.99f, "56FG84"));
14 | items.put(12, new TypeAItem(12, 35.50f, "12SS34"));
15 | items.put(13, new TypeAItem(13, 19.90f, "87HU75"));
16 | }
17 |
18 | public TypeAItem retrieveItem(int id) {
19 | return items.get(id);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/repository/TypeBItemRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.repository;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import xpadro.rest.ri.model.TypeBItem;
7 |
8 | public class TypeBItemRepository {
9 | private Map items;
10 |
11 | public TypeBItemRepository() {
12 | items = new HashMap();
13 | items.put(1, new TypeBItem(1, 33.50f));
14 | items.put(2, new TypeBItem(2, 55.50f));
15 | items.put(3, new TypeBItem(3, 95.99f));
16 | }
17 |
18 | public TypeBItem retrieveItem(int id) {
19 | return items.get(id);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/resources/ItemResource.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.resources;
2 |
3 | public interface ItemResource {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/resources/TypeAResource.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.resources;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Produces;
5 | import javax.ws.rs.WebApplicationException;
6 | import javax.ws.rs.core.MediaType;
7 | import javax.ws.rs.core.Response;
8 |
9 | import xpadro.rest.ri.model.TypeAItem;
10 | import xpadro.rest.ri.repository.TypeAItemRepository;
11 |
12 | /**
13 | * Type A Subresource
14 | */
15 | public class TypeAResource implements ItemResource {
16 | private int itemId;
17 | private TypeAItemRepository itemRepository = new TypeAItemRepository();
18 |
19 | public TypeAResource(int id) {
20 | this.itemId = id;
21 | }
22 |
23 | @GET
24 | @Produces(MediaType.APPLICATION_JSON)
25 | public TypeAItem getTypeAItem() {
26 | TypeAItem item = itemRepository.retrieveItem(itemId);
27 | if (item == null) {
28 | throw new WebApplicationException(Response.Status.NOT_FOUND);
29 | }
30 |
31 | return item;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/resources/TypeBResource.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.resources;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Produces;
5 | import javax.ws.rs.WebApplicationException;
6 | import javax.ws.rs.core.MediaType;
7 | import javax.ws.rs.core.Response;
8 |
9 | import xpadro.rest.ri.model.TypeBItem;
10 | import xpadro.rest.ri.repository.TypeBItemRepository;
11 |
12 | /**
13 | * Type B Subresource
14 | */
15 | public class TypeBResource implements ItemResource {
16 | private int itemId;
17 | private TypeBItemRepository itemRepository = new TypeBItemRepository();
18 |
19 | public TypeBResource(int id) {
20 | this.itemId = id;
21 | }
22 |
23 | @GET
24 | @Produces(MediaType.APPLICATION_JSON)
25 | public TypeBItem getTypeBItem() {
26 | TypeBItem item = itemRepository.retrieveItem(itemId);
27 | if (item == null) {
28 | throw new WebApplicationException(Response.Status.NOT_FOUND);
29 | }
30 |
31 | return item;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/java/xpadro/rest/ri/resources/WarehouseResource.java:
--------------------------------------------------------------------------------
1 | package xpadro.rest.ri.resources;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.PathParam;
6 |
7 | /**
8 | * Root resource
9 | */
10 | @Path("/warehouse")
11 | public class WarehouseResource {
12 |
13 | @GET
14 | public String getWarehouseInfo() {
15 | return "Warehouse location: Barcelona";
16 | }
17 |
18 | @Path("/items/{itemId}")
19 | public ItemResource getItem(@PathParam("itemId") Integer itemId) {
20 | ItemResource itemResource = null;
21 |
22 | if (itemId > 10) {
23 | itemResource = new TypeAResource(itemId);
24 | }
25 | else {
26 | itemResource = new TypeBResource(itemId);
27 | }
28 |
29 | return itemResource;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
9 | Jersey Servlet
10 | com.sun.jersey.spi.container.servlet.ServletContainer
11 |
12 | com.sun.jersey.config.property.packages
13 | xpadro.rest.ri.resources
14 |
15 |
16 | com.sun.jersey.api.json.POJOMappingFeature
17 | true
18 |
19 | 1
20 |
21 |
22 |
23 | Jersey Servlet
24 | /rest/*
25 |
26 |
27 |
--------------------------------------------------------------------------------
/rest-subresources/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/rest_test/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/rest_test/.gitignore:
--------------------------------------------------------------------------------
1 | target
--------------------------------------------------------------------------------
/rest_test/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | rest_test
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.wst.common.project.facet.core.builder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 | org.eclipse.wst.validation.validationbuilder
30 |
31 |
32 |
33 |
34 |
35 | org.eclipse.jem.workbench.JavaEMFNature
36 | org.eclipse.wst.common.modulecore.ModuleCoreNature
37 | org.eclipse.jdt.core.javanature
38 | org.eclipse.m2e.core.maven2Nature
39 | org.eclipse.wst.common.project.facet.core.nature
40 | org.eclipse.wst.jsdt.core.jsNature
41 |
42 |
43 |
--------------------------------------------------------------------------------
/rest_test/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/rest_test/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
4 | org.eclipse.jdt.core.compiler.compliance=1.6
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.6
9 |
--------------------------------------------------------------------------------
/rest_test/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/rest_test/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/rest_test/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/rest_test/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/rest_test/.settings/org.maven.ide.eclipse.prefs:
--------------------------------------------------------------------------------
1 | #Sun Feb 03 11:31:23 CET 2013
2 | activeProfiles=
3 | eclipse.preferences.version=1
4 | fullBuildGoals=process-test-resources
5 | includeModules=false
6 | resolveWorkspaceProjects=true
7 | resourceFilterGoals=process-resources resources\:testResources
8 | skipCompilerPlugin=true
9 | version=1
10 |
--------------------------------------------------------------------------------
/rest_test/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | xpadro.tutorial.rest
4 | rest_test
5 | 0.0.1-SNAPSHOT
6 |
7 |
8 | 3.2.1.RELEASE
9 | 2.5
10 | 1.2
11 | 1.2.14
12 | 4.8.1
13 | 1.4.2
14 |
15 |
16 |
17 |
18 |
19 | org.springframework
20 | spring-context
21 | ${spring.version}
22 |
23 |
24 | org.springframework
25 | spring-webmvc
26 | ${spring.version}
27 |
28 |
29 | org.springframework
30 | spring-web
31 | ${spring.version}
32 |
33 |
34 |
35 |
36 | javax.servlet
37 | servlet-api
38 | ${servlet.version}
39 | provided
40 |
41 |
42 | javax.servlet
43 | jstl
44 | ${jstl.version}
45 |
46 |
47 |
48 |
49 | log4j
50 | log4j
51 | ${log4j.version}
52 |
53 |
54 |
55 |
56 | org.springframework
57 | spring-test
58 | ${spring.version}
59 |
60 |
61 | junit
62 | junit
63 | ${junit.version}
64 |
65 |
66 |
67 |
68 | org.codehaus.jackson
69 | jackson-mapper-asl
70 | ${json.version}
71 |
72 |
73 |
74 | war
75 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/controller/WarehouseController.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 |
6 | import org.apache.log4j.Logger;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.stereotype.Controller;
10 | import org.springframework.web.bind.WebDataBinder;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.InitBinder;
13 | import org.springframework.web.bind.annotation.PathVariable;
14 | import org.springframework.web.bind.annotation.RequestBody;
15 | import org.springframework.web.bind.annotation.RequestMapping;
16 | import org.springframework.web.bind.annotation.RequestMethod;
17 | import org.springframework.web.bind.annotation.ResponseBody;
18 | import org.springframework.web.bind.annotation.ResponseStatus;
19 | import org.springframework.web.context.request.WebRequest;
20 |
21 | import xpadro.tutorial.rest.exception.ProductNotFoundException;
22 | import xpadro.tutorial.rest.model.Product;
23 | import xpadro.tutorial.rest.model.Warehouse;
24 | import xpadro.tutorial.rest.repository.WarehouseRepository;
25 |
26 | /**
27 | * Contains CRUD operations on warehouses and its products.
28 | * @author xpadro
29 | *
30 | */
31 | @Controller
32 | public class WarehouseController {
33 | private static Logger logger = Logger.getLogger("main");
34 |
35 | @Autowired
36 | private WarehouseRepository warehouseRepository;
37 |
38 |
39 | /**
40 | * Returns the warehouse requested by its id.
41 | * @param id
42 | * @return The requested warehouse
43 | */
44 | @RequestMapping(value="/warehouses/{warehouseId}", method=RequestMethod.GET)
45 | public @ResponseBody Warehouse getWarehouse(@PathVariable("warehouseId") int id) {
46 | return warehouseRepository.getWarehouse(id);
47 | }
48 |
49 | /**
50 | * Adds a new product to the specified warehouse.
51 | * @param warehouseId The id of the warehouse where to add the new product
52 | * @param product The new product to be created
53 | * @param request
54 | * @param response
55 | */
56 | @RequestMapping(value="/warehouses/{warehouseId}/products", method=RequestMethod.POST)
57 | @ResponseStatus(HttpStatus.CREATED)
58 | public void addProduct(@PathVariable("warehouseId") int warehouseId, @RequestBody Product product,
59 | HttpServletRequest request, HttpServletResponse response) {
60 |
61 | warehouseRepository.addProduct(warehouseId, product);
62 | response.setHeader("Location", request.getRequestURL().append("/").append(product.getId()).toString());
63 | }
64 |
65 | /**
66 | * Removes a product from a specified warehouse.
67 | * @param warehouseId The id of the warehouse where to remove the product
68 | * @param productId The id of the product to be removed
69 | * @param request
70 | * @param response
71 | */
72 | @RequestMapping(value="/warehouses/{warehouseId}/products/{productId}", method=RequestMethod.DELETE)
73 | @ResponseStatus(HttpStatus.NO_CONTENT)
74 | public void removeProduct(@PathVariable("warehouseId") int warehouseId, @PathVariable("productId") int productId,
75 | HttpServletRequest request, HttpServletResponse response) {
76 |
77 | warehouseRepository.removeProduct(warehouseId, productId);
78 | }
79 |
80 | /**
81 | * Returns the product from a specified warehouse.
82 | * @param warehouseId The id of the warehouse where to get the product
83 | * @param productId
84 | * @return
85 | */
86 | @RequestMapping(value="/warehouses/{warehouseId}/products/{productId}", method=RequestMethod.GET)
87 | public @ResponseBody Product getProduct(@PathVariable("warehouseId") int warehouseId, @PathVariable("productId") int productId) {
88 | return warehouseRepository.getProduct(warehouseId, productId);
89 | }
90 |
91 | /**
92 | * Handles ProductNotFoundException and returns a 404 response status code
93 | */
94 | @ResponseStatus(HttpStatus.NOT_FOUND)
95 | @ExceptionHandler({ProductNotFoundException.class})
96 | public void handleProductNotFound(ProductNotFoundException pe) {
97 | logger.warn("Product not found. Code: "+pe.getMessage());
98 | }
99 |
100 |
101 | @InitBinder
102 | public void testBinder(WebDataBinder binder, WebRequest req) {
103 | System.out.println();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.exception;
2 |
3 | /**
4 | * A runtime exception that arises when a warehouse doesn't contain a specified product
5 | * @author xpadro
6 | *
7 | */
8 | public class ProductNotFoundException extends RuntimeException {
9 | private static final long serialVersionUID = -4372776309073614775L;
10 |
11 | public ProductNotFoundException(String productId) {
12 | super(productId);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/model/Product.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.model;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * A product contained in a warehouse.
7 | * @author xpadro
8 | *
9 | */
10 | public class Product implements Serializable {
11 | private static final long serialVersionUID = 1018938490349056134L;
12 | private Integer id;
13 | private String description;
14 |
15 |
16 | public Product() {
17 |
18 | }
19 |
20 | public Product(Integer id, String description) {
21 | this.id = id;
22 | this.description = description;
23 | }
24 |
25 | /**
26 | * @return the id
27 | */
28 | public Integer getId() {
29 | return id;
30 | }
31 |
32 | /**
33 | * @param id the id to set
34 | */
35 | public void setId(Integer id) {
36 | this.id = id;
37 | }
38 |
39 | /**
40 | * @return the description
41 | */
42 | public String getDescription() {
43 | return description;
44 | }
45 |
46 | /**
47 | * @param description the description to set
48 | */
49 | public void setDescription(String description) {
50 | this.description = description;
51 | }
52 |
53 | @Override
54 | public int hashCode() {
55 | final int prime = 31;
56 | int result = 1;
57 | result = prime * result
58 | + ((description == null) ? 0 : description.hashCode());
59 | result = prime * result + ((id == null) ? 0 : id.hashCode());
60 | return result;
61 | }
62 |
63 | @Override
64 | public boolean equals(Object obj) {
65 | if (this == obj)
66 | return true;
67 | if (obj == null)
68 | return false;
69 | if (getClass() != obj.getClass())
70 | return false;
71 | Product other = (Product) obj;
72 | if (description == null) {
73 | if (other.description != null)
74 | return false;
75 | } else if (!description.equals(other.description))
76 | return false;
77 | if (id == null) {
78 | if (other.id != null)
79 | return false;
80 | } else if (!id.equals(other.id))
81 | return false;
82 | return true;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/model/Warehouse.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.model;
2 |
3 | import java.io.Serializable;
4 | import java.util.Set;
5 |
6 | import xpadro.tutorial.rest.exception.ProductNotFoundException;
7 |
8 | /**
9 | * A warehouse identified in the system by its id. Each warehouse can contain several products.
10 | * @author xpadro
11 | *
12 | */
13 | public class Warehouse implements Serializable {
14 | private static final long serialVersionUID = 3944671568023013152L;
15 | private Integer id;
16 | private String name;
17 | private Set products;
18 |
19 |
20 | public Warehouse() {
21 |
22 | }
23 |
24 | public Warehouse(int id, String name) {
25 | this.id = id;
26 | this.name = name;
27 | }
28 |
29 | public Warehouse(int id, String name, Set products) {
30 | this.id = id;
31 | this.name = name;
32 | this.products = products;
33 | }
34 |
35 |
36 | /**
37 | * @return the id
38 | */
39 | public Integer getId() {
40 | return id;
41 | }
42 |
43 | /**
44 | * @param id the id to set
45 | */
46 | public void setId(Integer id) {
47 | this.id = id;
48 | }
49 |
50 | /**
51 | * @return the name
52 | */
53 | public String getName() {
54 | return name;
55 | }
56 |
57 | /**
58 | * @param name the name to set
59 | */
60 | public void setName(String name) {
61 | this.name = name;
62 | }
63 |
64 | /**
65 | * @return the inventory
66 | */
67 | public Set getProducts() {
68 | return products;
69 | }
70 |
71 | /**
72 | * @param inventory the inventory to set
73 | */
74 | public void setProducts(Set products) {
75 | this.products = products;
76 | }
77 |
78 | /**
79 | * Returns a product by its id. Throws an exception if the product can't be found.
80 | * @param productId
81 | * @return the requested product
82 | */
83 | public Product getProduct(int productId) {
84 | for (Product product:products) {
85 | if (productId == product.getId()) {
86 | return product;
87 | }
88 | }
89 | throw new ProductNotFoundException(String.valueOf(productId));
90 | }
91 |
92 | /**
93 | * Adds a product to the warehouse's inventory
94 | * @param product
95 | */
96 | public void addProduct(Product product) {
97 | products.add(product);
98 | }
99 |
100 | /**
101 | * Removes an existing product from the warehouse's inventory
102 | * @param productId
103 | */
104 | public void removeProduct(int productId) {
105 | for (Product product:products) {
106 | if (productId == product.getId()) {
107 | products.remove(product);
108 | return;
109 | }
110 | }
111 | }
112 |
113 | @Override
114 | public int hashCode() {
115 | final int prime = 31;
116 | int result = 1;
117 | result = prime * result + ((id == null) ? 0 : id.hashCode());
118 | result = prime * result + ((name == null) ? 0 : name.hashCode());
119 | return result;
120 | }
121 |
122 | @Override
123 | public boolean equals(Object obj) {
124 | if (this == obj)
125 | return true;
126 | if (obj == null)
127 | return false;
128 | if (getClass() != obj.getClass())
129 | return false;
130 | Warehouse other = (Warehouse) obj;
131 | if (id == null) {
132 | if (other.id != null)
133 | return false;
134 | } else if (!id.equals(other.id))
135 | return false;
136 | if (name == null) {
137 | if (other.name != null)
138 | return false;
139 | } else if (!name.equals(other.name))
140 | return false;
141 | return true;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/repository/WarehouseRepository.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.repository;
2 |
3 | import java.util.Set;
4 |
5 | import xpadro.tutorial.rest.model.Product;
6 | import xpadro.tutorial.rest.model.Warehouse;
7 |
8 | /**
9 | * Manages data from warehouses and its products
10 | * @author xpadro
11 | *
12 | */
13 | public interface WarehouseRepository {
14 |
15 | /**
16 | * Returns the warehouse identified by the id
17 | * @param id
18 | * @return the warehouse
19 | */
20 | public Warehouse getWarehouse(Integer id);
21 |
22 | /**
23 | * Creates a new warehouse
24 | * @param warehouse
25 | */
26 | public void createWarehouse(Warehouse warehouse);
27 |
28 | /**
29 | * Removes an existing warehouse identified by the id
30 | * @param warehouseId
31 | */
32 | public void removeWarehouse(int warehouseId);
33 |
34 | /**
35 | * Returns the list of all products contained in the warehouse identified by the id
36 | * @param warehouseId
37 | * @return
38 | */
39 | public Set getProducts(int warehouseId);
40 |
41 | /**
42 | * Gets a product by its id that is contained in the warehouse
43 | * @param warehouseId
44 | * @param productId
45 | * @return the product
46 | */
47 | public Product getProduct(int warehouseId, int productId);
48 |
49 | /**
50 | * Adds a new product to an existing warehouse
51 | * @param warehouseId
52 | * @param product
53 | */
54 | public void addProduct(int warehouseId, Product product);
55 |
56 | /**
57 | * Removes an existing product identified by the id
58 | * @param warehouseId
59 | * @param productId
60 | */
61 | public void removeProduct(int warehouseId, int productId);
62 | }
63 |
--------------------------------------------------------------------------------
/rest_test/src/main/java/xpadro/tutorial/rest/repository/WarehouseRepositoryImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.repository;
2 |
3 | import java.util.HashMap;
4 | import java.util.HashSet;
5 | import java.util.Map;
6 | import java.util.Set;
7 |
8 | import org.springframework.stereotype.Repository;
9 |
10 | import xpadro.tutorial.rest.model.Product;
11 | import xpadro.tutorial.rest.model.Warehouse;
12 |
13 | /**
14 | * A stub repository that uses dummy data for testing
15 | * @author xpadro
16 | *
17 | */
18 | @Repository
19 | public class WarehouseRepositoryImpl implements WarehouseRepository {
20 | private Map warehouses;
21 |
22 |
23 | public WarehouseRepositoryImpl() {
24 | warehouses = new HashMap();
25 | createDummyWarehouses();
26 | }
27 |
28 | @Override
29 | public Warehouse getWarehouse(Integer id) {
30 | return warehouses.get(id);
31 | }
32 |
33 | @Override
34 | public void createWarehouse(Warehouse warehouse) {
35 | warehouses.put(warehouse.getId(), warehouse);
36 | }
37 |
38 | @Override
39 | public void removeWarehouse(int warehouseId) {
40 | warehouses.remove(warehouseId);
41 | }
42 |
43 | @Override
44 | public Set getProducts(int warehouseId) {
45 | return warehouses.get(warehouseId).getProducts();
46 | }
47 |
48 | @Override
49 | public Product getProduct(int warehouseId, int productId) {
50 | return warehouses.get(warehouseId).getProduct(productId);
51 | }
52 |
53 | @Override
54 | public void addProduct(int warehouseId, Product product) {
55 | warehouses.get(warehouseId).addProduct(product);
56 | }
57 |
58 | @Override
59 | public void removeProduct(int warehouseId, int productId) {
60 | warehouses.get(warehouseId).removeProduct(productId);
61 | }
62 |
63 | private void createDummyWarehouses() {
64 | Set products = new HashSet();
65 | Product product = new Product(1, "PROD_004");
66 | products.add(product);
67 | product = new Product(2, "PROD_015");
68 | products.add(product);
69 | product = new Product(3, "PROD_125");
70 | products.add(product);
71 | Warehouse warehouse = new Warehouse(1, "WAR_BCN_004", products);
72 |
73 | warehouses.put(1, warehouse);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/rest_test/src/main/resources/xpadro/tutorial/rest/configuration/app-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/rest_test/src/main/resources/xpadro/tutorial/rest/configuration/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/rest_test/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | SpringRestTest
4 |
5 |
6 |
7 | contextConfigLocation
8 | classpath:xpadro/tutorial/rest/configuration/root-context.xml
9 |
10 |
11 |
12 |
13 | org.springframework.web.context.ContextLoaderListener
14 |
15 |
16 |
17 |
18 | springServlet
19 | org.springframework.web.servlet.DispatcherServlet
20 |
21 | contextConfigLocation
22 | classpath:xpadro/tutorial/rest/configuration/app-context.xml
23 |
24 |
25 |
26 | springServlet
27 | /spring/*
28 |
29 |
--------------------------------------------------------------------------------
/rest_test/src/test/java/xpadro/tutorial/rest/client/TestWarehouse.java:
--------------------------------------------------------------------------------
1 | package xpadro.tutorial.rest.client;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import java.net.URI;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.test.context.ContextConfiguration;
12 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13 | import org.springframework.web.client.HttpClientErrorException;
14 | import org.springframework.web.client.RestTemplate;
15 |
16 | import xpadro.tutorial.rest.model.Product;
17 | import xpadro.tutorial.rest.model.Warehouse;
18 |
19 | @RunWith(SpringJUnit4ClassRunner.class)
20 | @ContextConfiguration(locations={
21 | "classpath:xpadro/tutorial/rest/configuration/root-context.xml",
22 | "classpath:xpadro/tutorial/rest/configuration/app-context.xml"})
23 | public class TestWarehouse {
24 | private static final int WAREHOUSE_ID = 1;
25 | private static final int PRODUCT_ID = 4;
26 |
27 | private RestTemplate restTemplate = new RestTemplate();
28 |
29 | /**
30 | * Tests accessing to an existing warehouse
31 | */
32 | @Test
33 | public void getWarehouse() {
34 | String uri = "http://localhost:8080/rest_test/spring/warehouses/{warehouseId}";
35 | Warehouse warehouse = restTemplate.getForObject(uri, Warehouse.class, WAREHOUSE_ID);
36 | assertNotNull(warehouse);
37 | assertEquals("WAR_BCN_004", warehouse.getName());
38 | }
39 |
40 | /**
41 | * Tests the addition of a new product to an existing warehouse.
42 | */
43 | @Test
44 | public void addProduct() {
45 | //Adds the new product
46 | String uri = "http://localhost:8080/rest_test/spring/warehouses/{warehouseId}/products";
47 | Product product = new Product(PRODUCT_ID, "PROD_999");
48 | URI newProductLocation = restTemplate.postForLocation(uri, product, WAREHOUSE_ID);
49 |
50 | //Checks we can access to the created product
51 | Product createdProduct = restTemplate.getForObject(newProductLocation, Product.class);
52 | assertEquals(product, createdProduct);
53 | assertNotNull(createdProduct.getId());
54 | }
55 |
56 | /**
57 | * Tests the removal of an existing product
58 | */
59 | @Test
60 | public void removeProduct() {
61 | String uri = "http://localhost:8080/rest_test/spring/warehouses/{warehouseId}/products/{productId}";
62 | restTemplate.delete(uri, WAREHOUSE_ID, PRODUCT_ID);
63 |
64 | try {
65 | restTemplate.getForObject(uri, Product.class, WAREHOUSE_ID, PRODUCT_ID);
66 | throw new AssertionError("Should have returned an 404 error code");
67 | } catch (HttpClientErrorException e) {
68 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.gitignore:
--------------------------------------------------------------------------------
1 | target
--------------------------------------------------------------------------------
/spring-rest-api-v32/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | spring-rest-api-v32
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.wst.validation.validationbuilder
25 |
26 |
27 |
28 |
29 | org.eclipse.m2e.core.maven2Builder
30 |
31 |
32 |
33 |
34 | org.springframework.ide.eclipse.core.springbuilder
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.ide.eclipse.core.springnature
41 | org.eclipse.jem.workbench.JavaEMFNature
42 | org.eclipse.wst.common.modulecore.ModuleCoreNature
43 | org.eclipse.jdt.core.javanature
44 | org.eclipse.m2e.core.maven2Nature
45 | org.eclipse.wst.common.project.facet.core.nature
46 | org.eclipse.wst.jsdt.core.jsNature
47 |
48 |
49 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
4 | org.eclipse.jdt.core.compiler.compliance=1.7
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.7
9 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/spring-rest-api-v32/.settings/org.eclipse.wst.validation.prefs:
--------------------------------------------------------------------------------
1 | disabled=06target
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | xpadro.spring.web
5 | spring-rest-api-v32
6 | war
7 | 0.0.1-SNAPSHOT
8 | spring-rest-api-v32 Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 3.2.3.RELEASE
13 | 1.3.3.RELEASE
14 | 2.5
15 | 1.2
16 | 4.8.1
17 | 1.4.2
18 | 1.7.2
19 | 1.2.16
20 | 1.3
21 | 1.9.5
22 | 0.8.1
23 | 1.4.2
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | org.springframework
32 | spring-context
33 | ${spring.version}
34 |
35 |
36 | org.springframework
37 | spring-webmvc
38 | ${spring.version}
39 |
40 |
41 |
42 |
43 | org.springframework.data
44 | spring-data-mongodb
45 | ${spring.mongo.version}
46 |
47 |
48 | org.slf4j
49 | slf4j-api
50 |
51 |
52 |
53 |
54 |
55 |
56 | javax.servlet
57 | servlet-api
58 | ${servlet.version}
59 | provided
60 |
61 |
62 | javax.servlet
63 | jstl
64 | ${jstl.version}
65 |
66 |
67 |
68 |
69 | org.slf4j
70 | slf4j-log4j12
71 | ${slf4j.version}
72 |
73 |
74 | log4j
75 | log4j
76 | ${log4j.version}
77 |
78 |
79 |
80 |
81 | org.springframework
82 | spring-test
83 | ${spring.version}
84 | test
85 |
86 |
87 | org.hamcrest
88 | hamcrest-all
89 | ${hamcrest.version}
90 | test
91 |
92 |
93 | junit
94 | junit
95 | ${junit.version}
96 | test
97 |
98 |
99 | hamcrest-core
100 | org.hamcrest
101 |
102 |
103 |
104 |
105 | org.mockito
106 | mockito-core
107 | ${mockito.version}
108 | test
109 |
110 |
111 | org.hamcrest
112 | hamcrest-core
113 |
114 |
115 |
116 |
117 | com.jayway.jsonpath
118 | json-path-assert
119 | ${jsonpath.version}
120 | test
121 |
122 |
123 |
124 |
125 | org.codehaus.jackson
126 | jackson-mapper-asl
127 | ${jackson.version}
128 |
129 |
130 |
131 |
132 |
133 | spring-rest-api-v32
134 |
135 |
136 | maven-compiler-plugin
137 |
138 | 1.7
139 | 1.7
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/java/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/java/xpadro/spring/web/controller/SeriesController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 |
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.ResponseEntity;
9 | import org.springframework.stereotype.Controller;
10 | import org.springframework.web.bind.annotation.PathVariable;
11 | import org.springframework.web.bind.annotation.RequestBody;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RequestMethod;
14 | import org.springframework.web.bind.annotation.ResponseBody;
15 | import org.springframework.web.bind.annotation.ResponseStatus;
16 |
17 | import xpadro.spring.web.model.Series;
18 | import xpadro.spring.web.service.SeriesService;
19 |
20 | @Controller
21 | @RequestMapping(value="/series")
22 | public class SeriesController {
23 |
24 | private SeriesService seriesService;
25 |
26 | @Autowired
27 | public SeriesController(SeriesService seriesService) {
28 | this.seriesService = seriesService;
29 | }
30 |
31 |
32 | /**
33 | * Returns all registered series
34 | * @return
35 | */
36 | @RequestMapping(method=RequestMethod.GET)
37 | @ResponseBody
38 | public Series[] getAllSeries() {
39 | return seriesService.getAllSeries();
40 | }
41 |
42 | /**
43 | * Returns the requested series by its id.
44 | * @param id
45 | * @return The requested series
46 | */
47 | @RequestMapping(value="/{seriesId}", method=RequestMethod.GET)
48 | public ResponseEntity getSeries(@PathVariable("seriesId") long id) {
49 | Series series = seriesService.getSeries(id);
50 |
51 | if (series == null) {
52 | return new ResponseEntity(HttpStatus.NOT_FOUND);
53 | }
54 |
55 | return new ResponseEntity(series, HttpStatus.OK);
56 | }
57 |
58 | /**
59 | * Inserts a new series to the DB
60 | * @param series
61 | * @param request
62 | * @param response
63 | */
64 | @RequestMapping(method=RequestMethod.POST)
65 | @ResponseStatus(HttpStatus.CREATED)
66 | public void insertSeries(@RequestBody Series series, HttpServletRequest request, HttpServletResponse response) {
67 | seriesService.insertSeries(series);
68 | response.setHeader("Location", request.getRequestURL().append("/").append(series.getId()).toString());
69 | }
70 |
71 | /**
72 | * Deletes the specified series
73 | * @param id
74 | */
75 | @RequestMapping(value="/{seriesId}", method=RequestMethod.DELETE)
76 | @ResponseStatus(HttpStatus.NO_CONTENT)
77 | public void deleteSeries(@PathVariable("seriesId") long id) {
78 | seriesService.deleteSeries(id);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/java/xpadro/spring/web/model/Series.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.model;
2 |
3 | import java.io.Serializable;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | @XmlRootElement(name="series")
9 | public class Series implements Serializable {
10 | private static final long serialVersionUID = 2646831820313826686L;
11 |
12 | private long id;
13 | private String name;
14 | private String country;
15 | private String genre;
16 |
17 | public Series() {}
18 |
19 | public Series(long id, String name, String country, String genre) {
20 | this.id = id;
21 | this.name = name;
22 | this.country = country;
23 | this.genre = genre;
24 | }
25 |
26 | @XmlElement
27 | public long getId() {
28 | return id;
29 | }
30 |
31 | public void setId(long id) {
32 | this.id = id;
33 | }
34 |
35 | @XmlElement
36 | public String getName() {
37 | return name;
38 | }
39 |
40 | public void setName(String name) {
41 | this.name = name;
42 | }
43 |
44 | @XmlElement
45 | public String getCountry() {
46 | return country;
47 | }
48 |
49 | public void setCountry(String country) {
50 | this.country = country;
51 | }
52 |
53 | @XmlElement
54 | public String getGenre() {
55 | return genre;
56 | }
57 |
58 | public void setGenre(String genre) {
59 | this.genre = genre;
60 | }
61 |
62 |
63 |
64 | /*
65 | private Series(SeriesBuilder builder) {
66 | id = builder.id;
67 | name = builder.name;
68 | country = builder.country;
69 | genre = builder.genre;
70 | }
71 |
72 |
73 |
74 | public long getId() {
75 | return id;
76 | }
77 |
78 |
79 | public String getName() {
80 | return name;
81 | }
82 |
83 |
84 | public String getCountry() {
85 | return country;
86 | }
87 |
88 |
89 | public String getGenre() {
90 | return genre;
91 | }
92 |
93 |
94 | public static class SeriesBuilder {
95 | private final long id;
96 | private final String name;
97 |
98 | private String country;
99 | private String genre;
100 |
101 |
102 | public SeriesBuilder(long id, String name) {
103 | this.id = id;
104 | this.name = name;
105 | }
106 |
107 |
108 | public SeriesBuilder withCountry(String country) {
109 | this.country = country;
110 | return this;
111 | }
112 |
113 | public SeriesBuilder withGenre(String genre) {
114 | this.genre = genre;
115 | return this;
116 | }
117 |
118 | public Series build() {
119 | return new Series(this);
120 | }
121 | }
122 | */
123 | }
124 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/java/xpadro/spring/web/service/SeriesService.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service;
2 |
3 | import xpadro.spring.web.model.Series;
4 |
5 | /**
6 | * Manages data from series
7 | * @author xpadro
8 | *
9 | */
10 | public interface SeriesService {
11 |
12 | /**
13 | * Returns all series
14 | * @return
15 | */
16 | Series[] getAllSeries();
17 |
18 | /**
19 | * Returns the series identified by the id
20 | * @param id
21 | * @return the series
22 | */
23 | Series getSeries(long id);
24 |
25 | /**
26 | * Inserts a series into the DB
27 | * @param series
28 | */
29 | void insertSeries(Series series);
30 |
31 | /**
32 | * Deletes the specified series
33 | * @param id
34 | */
35 | void deleteSeries(long id);
36 | }
37 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/java/xpadro/spring/web/service/impl/SeriesServiceImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service.impl;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.data.mongodb.core.MongoOperations;
7 | import org.springframework.data.mongodb.core.query.Criteria;
8 | import org.springframework.data.mongodb.core.query.Query;
9 | import org.springframework.stereotype.Service;
10 |
11 | import xpadro.spring.web.model.Series;
12 | import xpadro.spring.web.service.SeriesService;
13 |
14 | /**
15 | * Handles data using a mongoDB database
16 | * @author xpadro
17 | *
18 | */
19 | @Service
20 | public class SeriesServiceImpl implements SeriesService {
21 |
22 | @Autowired
23 | private MongoOperations mongoOps;
24 |
25 |
26 | @Override
27 | public Series[] getAllSeries() {
28 | List seriesList = mongoOps.findAll(Series.class);
29 | return seriesList.toArray(new Series[0]);
30 | }
31 |
32 | @Override
33 | public Series getSeries(long id) {
34 | return mongoOps.findById(id, Series.class);
35 | }
36 |
37 | @Override
38 | public void insertSeries(Series series) {
39 | mongoOps.insert(series);
40 | }
41 |
42 |
43 | @Override
44 | public void deleteSeries(long id) {
45 | Query query = new Query();
46 | Criteria criteria = new Criteria("_id").is(id);
47 | query.addCriteria(criteria);
48 |
49 | mongoOps.remove(query, Series.class);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/resources/xpadro/spring/web/configuration/app-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/resources/xpadro/spring/web/configuration/db-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/resources/xpadro/spring/web/configuration/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Spring MVC - RESTful web services
7 |
8 |
9 |
10 | contextConfigLocation
11 | classpath:xpadro/spring/web/configuration/root-context.xml
12 |
13 |
14 |
15 |
16 | org.springframework.web.context.ContextLoaderListener
17 |
18 |
19 |
20 |
21 | springServlet
22 | org.springframework.web.servlet.DispatcherServlet
23 |
24 | contextConfigLocation
25 | classpath:xpadro/spring/web/configuration/app-context.xml
26 |
27 |
28 |
29 | springServlet
30 | /spring/*
31 |
32 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | RESTful Web Services with Spring MVC
4 |
5 |
6 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/test/java/xpadro/spring/web/test/SeriesFunctionalTesting.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.fail;
6 |
7 | import java.net.URI;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 | import org.springframework.beans.factory.annotation.Autowired;
15 | import org.springframework.dao.DataAccessResourceFailureException;
16 | import org.springframework.data.mongodb.core.MongoOperations;
17 | import org.springframework.http.HttpStatus;
18 | import org.springframework.http.MediaType;
19 | import org.springframework.http.ResponseEntity;
20 | import org.springframework.http.converter.HttpMessageConverter;
21 | import org.springframework.http.converter.StringHttpMessageConverter;
22 | import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
23 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
24 | import org.springframework.test.context.ContextConfiguration;
25 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
26 | import org.springframework.web.client.HttpClientErrorException;
27 | import org.springframework.web.client.RestTemplate;
28 |
29 | import xpadro.spring.web.model.Series;
30 |
31 | @RunWith(SpringJUnit4ClassRunner.class)
32 | @ContextConfiguration(locations={
33 | "classpath:xpadro/spring/web/configuration/root-context.xml",
34 | "classpath:xpadro/spring/web/configuration/app-context.xml"})
35 | public class SeriesFunctionalTesting {
36 | private static final String BASE_URI = "http://localhost:8080/spring-rest-api-v32/spring/series";
37 | private RestTemplate restTemplate = new RestTemplate();
38 |
39 | @Autowired
40 | private MongoOperations mongoOps;
41 |
42 | @Before
43 | public void setup() {
44 | List> converters = new ArrayList>();
45 | converters.add(new StringHttpMessageConverter());
46 | converters.add(new Jaxb2RootElementHttpMessageConverter());
47 | converters.add(new MappingJacksonHttpMessageConverter());
48 | restTemplate.setMessageConverters(converters);
49 |
50 | initializeDatabase();
51 | }
52 |
53 | private void initializeDatabase() {
54 | try {
55 | mongoOps.dropCollection("series");
56 |
57 | mongoOps.insert(new Series(1, "The walking dead", "USA", "Thriller"));
58 | mongoOps.insert(new Series(2, "Homeland", "USA", "Drama"));
59 | } catch (DataAccessResourceFailureException e) {
60 | fail("MongoDB instance is not running");
61 | }
62 | }
63 |
64 |
65 | @Test
66 | public void getAllSeries() {
67 | Series[] series = restTemplate.getForObject(BASE_URI, Series[].class);
68 |
69 | assertNotNull(series);
70 | assertEquals(2, series.length);
71 | assertEquals(1L, series[0].getId());
72 | assertEquals("The walking dead", series[0].getName());
73 | assertEquals("USA", series[0].getCountry());
74 | assertEquals("Thriller", series[0].getGenre());
75 | assertEquals(2L, series[1].getId());
76 | assertEquals("Homeland", series[1].getName());
77 | assertEquals("USA", series[1].getCountry());
78 | assertEquals("Drama", series[1].getGenre());
79 | }
80 |
81 |
82 | @Test
83 | public void getJsonSeries() {
84 | List> converters = new ArrayList>();
85 | converters.add(new MappingJacksonHttpMessageConverter());
86 | restTemplate.setMessageConverters(converters);
87 |
88 | String uri = BASE_URI + "/{seriesId}";
89 | ResponseEntity seriesEntity = restTemplate.getForEntity(uri, Series.class, 1l);
90 | assertNotNull(seriesEntity.getBody());
91 | assertEquals(1l, seriesEntity.getBody().getId());
92 | assertEquals("The walking dead", seriesEntity.getBody().getName());
93 | assertEquals("USA", seriesEntity.getBody().getCountry());
94 | assertEquals("Thriller", seriesEntity.getBody().getGenre());
95 |
96 | assertEquals(MediaType.parseMediaType("application/json;charset=UTF-8"), seriesEntity.getHeaders().getContentType());
97 | }
98 |
99 | @Test
100 | public void getXmlSeries() {
101 | String uri = BASE_URI + "/{seriesId}";
102 | ResponseEntity seriesEntity = restTemplate.getForEntity(uri, Series.class, 1L);
103 | assertNotNull(seriesEntity.getBody());
104 | assertEquals(1l, seriesEntity.getBody().getId());
105 | assertEquals("The walking dead", seriesEntity.getBody().getName());
106 | assertEquals("USA", seriesEntity.getBody().getCountry());
107 | assertEquals("Thriller", seriesEntity.getBody().getGenre());
108 |
109 | assertEquals(MediaType.APPLICATION_XML, seriesEntity.getHeaders().getContentType());
110 | }
111 |
112 | @Test
113 | public void getNotFoundSeries() {
114 | String uri = BASE_URI + "/{seriesId}";
115 |
116 | try {
117 | restTemplate.getForEntity(uri, Series.class, 5L);
118 | } catch (HttpClientErrorException e) {
119 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
120 | }
121 | }
122 |
123 | @Test
124 | public void insertNewSeries() {
125 | Series series = new Series();
126 | series.setId(4L);
127 | series.setName("mySeries");
128 | series.setCountry("England");
129 | series.setGenre("sci-fi");
130 |
131 | URI newUserLocation = restTemplate.postForLocation(BASE_URI, series);
132 | assertEquals(BASE_URI + "/4", newUserLocation.toString());
133 | }
134 |
135 | @Test
136 | public void deleteExistingSeries() {
137 | String uri = BASE_URI + "/{seriesId}";
138 | restTemplate.delete(uri, 2L);
139 |
140 | try {
141 | restTemplate.getForEntity(uri, Series.class, 2L);
142 | } catch (HttpClientErrorException e) {
143 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/test/java/xpadro/spring/web/test/SeriesIntegrationTesting.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.hamcrest.Matchers.hasSize;
4 | import static org.hamcrest.Matchers.is;
5 | import static org.hamcrest.Matchers.endsWith;
6 | import static org.mockito.Mockito.*;
7 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
9 | import org.springframework.test.context.ContextConfiguration;
10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 | import org.springframework.test.context.web.WebAppConfiguration;
12 | import org.springframework.test.web.servlet.MockMvc;
13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
14 | import org.junit.Before;
15 | import org.junit.Test;
16 | import org.junit.runner.RunWith;
17 |
18 | import org.springframework.beans.factory.annotation.Autowired;
19 | import org.springframework.web.context.WebApplicationContext;
20 | import org.springframework.http.MediaType;
21 |
22 | import xpadro.spring.web.model.Series;
23 | import xpadro.spring.web.service.SeriesService;
24 |
25 | @RunWith(SpringJUnit4ClassRunner.class)
26 | @WebAppConfiguration
27 | @ContextConfiguration(locations={
28 | "classpath:xpadro/spring/web/test/configuration/test-root-context.xml",
29 | "classpath:xpadro/spring/web/configuration/app-context.xml"})
30 | public class SeriesIntegrationTesting {
31 | private static final String BASE_URI = "/series";
32 |
33 | private MockMvc mockMvc;
34 |
35 | @Autowired
36 | private WebApplicationContext webApplicationContext;
37 |
38 | @Autowired
39 | private SeriesService seriesService;
40 |
41 |
42 | @Before
43 | public void setUp() {
44 | reset(seriesService);
45 | mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
46 |
47 | when(seriesService.getAllSeries()).thenReturn(new Series[]{
48 | new Series(1, "The walking dead", "USA", "Thriller"),
49 | new Series(2, "Homeland", "USA", "Drama")});
50 |
51 | when(seriesService.getSeries(1L)).thenReturn(new Series(1, "Fringe", "USA", "Thriller"));
52 | }
53 |
54 |
55 | @Test
56 | public void getAllSeries() throws Exception {
57 | mockMvc.perform(get(BASE_URI)
58 | .accept(MediaType.APPLICATION_JSON))
59 | .andExpect(status().isOk())
60 | .andExpect(content().contentType("application/json;charset=UTF-8"))
61 | .andExpect(jsonPath("$", hasSize(2)))
62 | .andExpect(jsonPath("$[0].id", is(1)))
63 | .andExpect(jsonPath("$[0].name", is("The walking dead")))
64 | .andExpect(jsonPath("$[0].country", is("USA")))
65 | .andExpect(jsonPath("$[0].genre", is("Thriller")))
66 | .andExpect(jsonPath("$[1].id", is(2)))
67 | .andExpect(jsonPath("$[1].name", is("Homeland")))
68 | .andExpect(jsonPath("$[1].country", is("USA")))
69 | .andExpect(jsonPath("$[1].genre", is("Drama")));
70 |
71 | verify(seriesService, times(1)).getAllSeries();
72 | verifyZeroInteractions(seriesService);
73 | }
74 |
75 | @Test
76 | public void getJsonSeries() throws Exception {
77 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 1L)
78 | .accept(MediaType.APPLICATION_JSON))
79 | .andExpect(status().isOk())
80 | .andExpect(content().contentType("application/json;charset=UTF-8"))
81 | .andExpect(jsonPath("$.id", is(1)))
82 | .andExpect(jsonPath("$.name", is("Fringe")))
83 | .andExpect(jsonPath("$.country", is("USA")))
84 | .andExpect(jsonPath("$.genre", is("Thriller")));
85 |
86 | verify(seriesService, times(1)).getSeries(1L);
87 | verifyZeroInteractions(seriesService);
88 | }
89 |
90 | @Test
91 | public void getXmlSeries() throws Exception {
92 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 1L)
93 | .accept(MediaType.APPLICATION_XML))
94 | .andExpect(status().isOk())
95 | .andExpect(content().contentType(MediaType.APPLICATION_XML))
96 | .andExpect(xpath("/series/id").string("1"))
97 | .andExpect(xpath("/series/name").string("Fringe"))
98 | .andExpect(xpath("/series/country").string("USA"))
99 | .andExpect(xpath("/series/genre").string("Thriller"));
100 |
101 |
102 | verify(seriesService, times(1)).getSeries(1L);
103 | verifyZeroInteractions(seriesService);
104 | }
105 |
106 | @Test
107 | public void getNotFoundSeries() throws Exception {
108 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 5L)
109 | .accept(MediaType.APPLICATION_JSON))
110 | .andExpect(status().isNotFound());
111 |
112 | verify(seriesService, times(1)).getSeries(5L);
113 | verifyZeroInteractions(seriesService);
114 | }
115 |
116 | @Test
117 | public void insertNewSeries() throws Exception {
118 | mockMvc.perform(post(BASE_URI)
119 | .content("{ \"id\": 3, \"name\": \"mySeries\", \"country\": \"England\", \"genre\": \"sci-fi\" } }")
120 | .contentType(MediaType.APPLICATION_JSON)
121 | .accept(MediaType.APPLICATION_JSON))
122 | .andExpect(status().isCreated())
123 | .andExpect(header().string("Location", endsWith("/series/3")));
124 |
125 | verify(seriesService, times(1)).insertSeries(any(Series.class));
126 | verifyZeroInteractions(seriesService);
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/spring-rest-api-v32/src/test/resources/xpadro/spring/web/test/configuration/test-root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | spring-rest-api-v4
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.wst.validation.validationbuilder
25 |
26 |
27 |
28 |
29 | org.springframework.ide.eclipse.core.springbuilder
30 |
31 |
32 |
33 |
34 | org.eclipse.m2e.core.maven2Builder
35 |
36 |
37 |
38 |
39 |
40 | org.springframework.ide.eclipse.core.springnature
41 | org.eclipse.jem.workbench.JavaEMFNature
42 | org.eclipse.wst.common.modulecore.ModuleCoreNature
43 | org.eclipse.jdt.core.javanature
44 | org.eclipse.m2e.core.maven2Nature
45 | org.eclipse.wst.common.project.facet.core.nature
46 | org.eclipse.wst.jsdt.core.jsNature
47 |
48 |
49 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
4 | org.eclipse.jdt.core.compiler.compliance=1.7
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.7
9 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/spring-rest-api-v4/.settings/org.eclipse.wst.validation.prefs:
--------------------------------------------------------------------------------
1 | disabled=06target
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/environment/development/workspace/spring-rest-api-v4/target/m2e-wtp/web-resources/.gitignore:
--------------------------------------------------------------------------------
1 | /META-INF
2 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | xpadro.spring.web
5 | spring-rest-api-v4
6 | war
7 | 0.0.1-SNAPSHOT
8 | spring-rest-api-v4 Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 4.0.0.RELEASE
13 | 1.3.3.RELEASE
14 | 3.1.0
15 | 1.2
16 | 4.8.1
17 | 1.4.2
18 | 1.7.2
19 | 1.2.16
20 | 1.3
21 | 1.9.5
22 | 0.8.1
23 | 1.4.2
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | org.springframework
32 | spring-context
33 | ${spring.version}
34 |
35 |
36 | org.springframework
37 | spring-webmvc
38 | ${spring.version}
39 |
40 |
41 |
42 |
43 | org.springframework.data
44 | spring-data-mongodb
45 | ${spring.mongo.version}
46 |
47 |
48 | org.slf4j
49 | slf4j-api
50 |
51 |
52 |
53 |
54 |
55 |
56 | javax.servlet
57 | javax.servlet-api
58 | ${servlet.version}
59 | provided
60 |
61 |
62 |
63 | javax.servlet
64 | jstl
65 | ${jstl.version}
66 |
67 |
68 |
69 |
70 | org.slf4j
71 | slf4j-log4j12
72 | ${slf4j.version}
73 |
74 |
75 | log4j
76 | log4j
77 | ${log4j.version}
78 |
79 |
80 |
81 |
82 | org.springframework
83 | spring-test
84 | ${spring.version}
85 | test
86 |
87 |
88 | org.hamcrest
89 | hamcrest-all
90 | ${hamcrest.version}
91 | test
92 |
93 |
94 | junit
95 | junit
96 | ${junit.version}
97 | test
98 |
99 |
100 | hamcrest-core
101 | org.hamcrest
102 |
103 |
104 |
105 |
106 | org.mockito
107 | mockito-core
108 | ${mockito.version}
109 | test
110 |
111 |
112 | org.hamcrest
113 | hamcrest-core
114 |
115 |
116 |
117 |
118 | com.jayway.jsonpath
119 | json-path-assert
120 | ${jsonpath.version}
121 | test
122 |
123 |
124 |
125 |
132 |
133 | com.fasterxml.jackson.core
134 | jackson-core
135 | 2.3.0
136 |
137 |
138 | com.fasterxml.jackson.core
139 | jackson-databind
140 | 2.3.0
141 |
142 |
143 |
144 |
145 |
146 |
147 | spring-rest-api-v4
148 |
149 |
150 | maven-compiler-plugin
151 |
152 | 1.7
153 | 1.7
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/java/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/java/xpadro/spring/web/controller/SeriesController.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.controller;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 |
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.ResponseEntity;
9 | import org.springframework.web.bind.annotation.PathVariable;
10 | import org.springframework.web.bind.annotation.RequestBody;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RequestMethod;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 | import org.springframework.web.bind.annotation.RestController;
15 |
16 | import xpadro.spring.web.model.Series;
17 | import xpadro.spring.web.service.SeriesService;
18 |
19 | @RestController
20 | @RequestMapping(value="/series")
21 | public class SeriesController {
22 |
23 | private SeriesService seriesService;
24 |
25 | @Autowired
26 | public SeriesController(SeriesService seriesService) {
27 | this.seriesService = seriesService;
28 | }
29 |
30 |
31 | /**
32 | * Returns all registered series
33 | * @return
34 | * @throws InterruptedException
35 | */
36 | @RequestMapping(method=RequestMethod.GET)
37 | public Series[] getAllSeries() throws InterruptedException {
38 | Thread.sleep(4000); //pause to better show sync/async RestTemplate behavior
39 | return seriesService.getAllSeries();
40 | }
41 |
42 | /**
43 | * Returns the requested series by its id.
44 | * @param id
45 | * @return The requested series
46 | */
47 | @RequestMapping(value="/{seriesId}", method=RequestMethod.GET)
48 | public ResponseEntity getSeries(@PathVariable("seriesId") long id) {
49 | Series series = seriesService.getSeries(id);
50 |
51 | if (series == null) {
52 | return new ResponseEntity(HttpStatus.NOT_FOUND);
53 | }
54 |
55 | return new ResponseEntity(series, HttpStatus.OK);
56 | }
57 |
58 | /**
59 | * Inserts a new series to the DB
60 | * @param series
61 | * @param request
62 | * @param response
63 | */
64 | @RequestMapping(method=RequestMethod.POST)
65 | @ResponseStatus(HttpStatus.CREATED)
66 | public void insertSeries(@RequestBody Series series, HttpServletRequest request, HttpServletResponse response) {
67 | seriesService.insertSeries(series);
68 | response.setHeader("Location", request.getRequestURL().append("/").append(series.getId()).toString());
69 | }
70 |
71 | /**
72 | * Deletes the specified series
73 | * @param id
74 | */
75 | @RequestMapping(value="/{seriesId}", method=RequestMethod.DELETE)
76 | @ResponseStatus(HttpStatus.NO_CONTENT)
77 | public void deleteSeries(@PathVariable("seriesId") long id) {
78 | seriesService.deleteSeries(id);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/java/xpadro/spring/web/model/Series.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.model;
2 |
3 | import java.io.Serializable;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | @XmlRootElement(name="series")
9 | public class Series implements Serializable {
10 | private static final long serialVersionUID = 2646831820313826686L;
11 |
12 | private long id;
13 | private String name;
14 | private String country;
15 | private String genre;
16 |
17 | public Series() {}
18 |
19 | public Series(long id, String name, String country, String genre) {
20 | this.id = id;
21 | this.name = name;
22 | this.country = country;
23 | this.genre = genre;
24 | }
25 |
26 | @XmlElement
27 | public long getId() {
28 | return id;
29 | }
30 |
31 | public void setId(long id) {
32 | this.id = id;
33 | }
34 |
35 | @XmlElement
36 | public String getName() {
37 | return name;
38 | }
39 |
40 | public void setName(String name) {
41 | this.name = name;
42 | }
43 |
44 | @XmlElement
45 | public String getCountry() {
46 | return country;
47 | }
48 |
49 | public void setCountry(String country) {
50 | this.country = country;
51 | }
52 |
53 | @XmlElement
54 | public String getGenre() {
55 | return genre;
56 | }
57 |
58 | public void setGenre(String genre) {
59 | this.genre = genre;
60 | }
61 |
62 |
63 |
64 | /*
65 | private Series(SeriesBuilder builder) {
66 | id = builder.id;
67 | name = builder.name;
68 | country = builder.country;
69 | genre = builder.genre;
70 | }
71 |
72 |
73 |
74 | public long getId() {
75 | return id;
76 | }
77 |
78 |
79 | public String getName() {
80 | return name;
81 | }
82 |
83 |
84 | public String getCountry() {
85 | return country;
86 | }
87 |
88 |
89 | public String getGenre() {
90 | return genre;
91 | }
92 |
93 |
94 | public static class SeriesBuilder {
95 | private final long id;
96 | private final String name;
97 |
98 | private String country;
99 | private String genre;
100 |
101 |
102 | public SeriesBuilder(long id, String name) {
103 | this.id = id;
104 | this.name = name;
105 | }
106 |
107 |
108 | public SeriesBuilder withCountry(String country) {
109 | this.country = country;
110 | return this;
111 | }
112 |
113 | public SeriesBuilder withGenre(String genre) {
114 | this.genre = genre;
115 | return this;
116 | }
117 |
118 | public Series build() {
119 | return new Series(this);
120 | }
121 | }
122 | */
123 | }
124 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/java/xpadro/spring/web/service/SeriesService.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service;
2 |
3 | import xpadro.spring.web.model.Series;
4 |
5 | /**
6 | * Manages data from series
7 | * @author xpadro
8 | *
9 | */
10 | public interface SeriesService {
11 |
12 | /**
13 | * Returns all series
14 | * @return
15 | */
16 | Series[] getAllSeries();
17 |
18 | /**
19 | * Returns the series identified by the id
20 | * @param id
21 | * @return the series
22 | */
23 | Series getSeries(long id);
24 |
25 | /**
26 | * Inserts a series into the DB
27 | * @param series
28 | */
29 | void insertSeries(Series series);
30 |
31 | /**
32 | * Deletes the specified series
33 | * @param id
34 | */
35 | void deleteSeries(long id);
36 | }
37 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/java/xpadro/spring/web/service/impl/SeriesServiceImpl.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.service.impl;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.data.mongodb.core.MongoOperations;
7 | import org.springframework.data.mongodb.core.query.Criteria;
8 | import org.springframework.data.mongodb.core.query.Query;
9 | import org.springframework.stereotype.Service;
10 |
11 | import xpadro.spring.web.model.Series;
12 | import xpadro.spring.web.service.SeriesService;
13 |
14 | /**
15 | * Handles data using a mongoDB database
16 | * @author xpadro
17 | *
18 | */
19 | @Service
20 | public class SeriesServiceImpl implements SeriesService {
21 |
22 | @Autowired
23 | private MongoOperations mongoOps;
24 |
25 |
26 | @Override
27 | public Series[] getAllSeries() {
28 | List seriesList = mongoOps.findAll(Series.class);
29 | return seriesList.toArray(new Series[0]);
30 | }
31 |
32 | @Override
33 | public Series getSeries(long id) {
34 | return mongoOps.findById(id, Series.class);
35 | }
36 |
37 | @Override
38 | public void insertSeries(Series series) {
39 | mongoOps.insert(series);
40 | }
41 |
42 |
43 | @Override
44 | public void deleteSeries(long id) {
45 | Query query = new Query();
46 | Criteria criteria = new Criteria("_id").is(id);
47 | query.addCriteria(criteria);
48 |
49 | mongoOps.remove(query, Series.class);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/resources/xpadro/spring/web/configuration/app-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/resources/xpadro/spring/web/configuration/db-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/resources/xpadro/spring/web/configuration/root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Spring MVC - RESTful web services
7 |
8 |
9 |
10 | contextConfigLocation
11 | classpath:xpadro/spring/web/configuration/root-context.xml
12 |
13 |
14 |
15 |
16 | org.springframework.web.context.ContextLoaderListener
17 |
18 |
19 |
20 |
21 | springServlet
22 | org.springframework.web.servlet.DispatcherServlet
23 |
24 | contextConfigLocation
25 | classpath:xpadro/spring/web/configuration/app-context.xml
26 |
27 |
28 |
29 | springServlet
30 | /spring/*
31 |
32 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | RESTful Web Services with Spring MVC
4 |
5 |
6 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/java/xpadro/spring/web/test/SeriesAsyncCallableFunctionalTest.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.fail;
6 |
7 | import java.util.concurrent.ExecutionException;
8 |
9 | import org.junit.Before;
10 | import org.junit.Test;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.util.concurrent.ListenableFuture;
15 | import org.springframework.util.concurrent.ListenableFutureCallback;
16 | import org.springframework.web.client.AsyncRestTemplate;
17 |
18 | import xpadro.spring.web.model.Series;
19 |
20 | public class SeriesAsyncCallableFunctionalTest extends SeriesFunctionalBaseTests {
21 | private static final String BASE_URI = "http://localhost:8080/spring-rest-api-v4/spring/series";
22 | private static Logger logger = LoggerFactory.getLogger(SeriesAsyncCallableFunctionalTest.class);
23 |
24 | private AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
25 |
26 | @Before
27 | public void setup() {
28 | initializeDatabase();
29 | }
30 |
31 |
32 | @Test
33 | public void getAllSeriesAsyncCallable() throws InterruptedException, ExecutionException {
34 | logger.info("Calling async callable /series");
35 | ListenableFuture> futureEntity = asyncRestTemplate.getForEntity(BASE_URI, Series[].class);
36 | futureEntity.addCallback(new ListenableFutureCallback>() {
37 | @Override
38 | public void onSuccess(ResponseEntity entity) {
39 | logger.info("Response received (async callable)");
40 | Series[] series = entity.getBody();
41 | validateList(series);
42 | }
43 |
44 | @Override
45 | public void onFailure(Throwable t) {
46 | fail();
47 | }
48 | });
49 | logger.info("Doing other async callable stuff ...");
50 | Thread.sleep(6000); //waits for the service to send the response
51 | }
52 |
53 | private void validateList(Series[] series) {
54 | assertNotNull(series);
55 | assertEquals(2, series.length);
56 | assertEquals(1L, series[0].getId());
57 | assertEquals("The walking dead", series[0].getName());
58 | assertEquals("USA", series[0].getCountry());
59 | assertEquals("Thriller", series[0].getGenre());
60 | assertEquals(2L, series[1].getId());
61 | assertEquals("Homeland", series[1].getName());
62 | assertEquals("USA", series[1].getCountry());
63 | assertEquals("Drama", series[1].getGenre());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/java/xpadro/spring/web/test/SeriesAsyncFunctionalTest.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import java.util.concurrent.ExecutionException;
7 | import java.util.concurrent.Future;
8 |
9 | import org.junit.Before;
10 | import org.junit.Test;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.web.client.AsyncRestTemplate;
15 |
16 | import xpadro.spring.web.model.Series;
17 |
18 | public class SeriesAsyncFunctionalTest extends SeriesFunctionalBaseTests {
19 | private static final String BASE_URI = "http://localhost:8080/spring-rest-api-v4/spring/series";
20 | private static Logger logger = LoggerFactory.getLogger(SeriesAsyncFunctionalTest.class);
21 |
22 | private AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
23 |
24 | @Before
25 | public void setup() {
26 | initializeDatabase();
27 | }
28 |
29 |
30 | @Test
31 | public void getAllSeriesAsync() throws InterruptedException, ExecutionException {
32 | logger.info("Calling async /series");
33 | Future> futureEntity = asyncRestTemplate.getForEntity(BASE_URI, Series[].class);
34 | logger.info("Doing other async stuff...");
35 |
36 | logger.info("Blocking to receive response...");
37 | ResponseEntity entity = futureEntity.get();
38 | logger.info("Response received");
39 | Series[] series = entity.getBody();
40 |
41 | assertNotNull(series);
42 | assertEquals(2, series.length);
43 | assertEquals(1L, series[0].getId());
44 | assertEquals("The walking dead", series[0].getName());
45 | assertEquals("USA", series[0].getCountry());
46 | assertEquals("Thriller", series[0].getGenre());
47 | assertEquals(2L, series[1].getId());
48 | assertEquals("Homeland", series[1].getName());
49 | assertEquals("USA", series[1].getCountry());
50 | assertEquals("Drama", series[1].getGenre());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/java/xpadro/spring/web/test/SeriesFunctionalBaseTests.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.junit.Assert.fail;
4 |
5 | import org.junit.runner.RunWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.dao.DataAccessResourceFailureException;
8 | import org.springframework.data.mongodb.core.MongoOperations;
9 | import org.springframework.test.context.ContextConfiguration;
10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 |
12 | import xpadro.spring.web.model.Series;
13 |
14 | @RunWith(SpringJUnit4ClassRunner.class)
15 | @ContextConfiguration(locations={
16 | "classpath:xpadro/spring/web/configuration/root-context.xml",
17 | "classpath:xpadro/spring/web/configuration/app-context.xml"})
18 | public class SeriesFunctionalBaseTests {
19 | @Autowired
20 | private MongoOperations mongoOps;
21 |
22 | protected void initializeDatabase() {
23 | try {
24 | mongoOps.dropCollection("series");
25 |
26 | mongoOps.insert(new Series(1, "The walking dead", "USA", "Thriller"));
27 | mongoOps.insert(new Series(2, "Homeland", "USA", "Drama"));
28 | } catch (DataAccessResourceFailureException e) {
29 | fail("MongoDB instance is not running");
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/java/xpadro/spring/web/test/SeriesFunctionalTest.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 |
6 | import java.net.URI;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import org.junit.Before;
11 | import org.junit.Test;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.MediaType;
14 | import org.springframework.http.ResponseEntity;
15 | import org.springframework.http.converter.HttpMessageConverter;
16 | import org.springframework.http.converter.StringHttpMessageConverter;
17 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
18 | import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
19 | import org.springframework.web.client.HttpClientErrorException;
20 | import org.springframework.web.client.RestTemplate;
21 |
22 | import xpadro.spring.web.model.Series;
23 |
24 | public class SeriesFunctionalTest extends SeriesFunctionalBaseTests {
25 | private static final String BASE_URI = "http://localhost:8080/spring-rest-api-v4/spring/series";
26 | private RestTemplate restTemplate = new RestTemplate();
27 |
28 | @Before
29 | public void setup() {
30 | List> converters = new ArrayList>();
31 | converters.add(new StringHttpMessageConverter());
32 | converters.add(new Jaxb2RootElementHttpMessageConverter());
33 | converters.add(new MappingJackson2HttpMessageConverter());
34 | restTemplate.setMessageConverters(converters);
35 |
36 | initializeDatabase();
37 | }
38 |
39 |
40 | @Test
41 | public void getAllSeries() {
42 | Series[] series = restTemplate.getForObject(BASE_URI, Series[].class);
43 |
44 | assertNotNull(series);
45 | assertEquals(2, series.length);
46 | assertEquals(1L, series[0].getId());
47 | assertEquals("The walking dead", series[0].getName());
48 | assertEquals("USA", series[0].getCountry());
49 | assertEquals("Thriller", series[0].getGenre());
50 | assertEquals(2L, series[1].getId());
51 | assertEquals("Homeland", series[1].getName());
52 | assertEquals("USA", series[1].getCountry());
53 | assertEquals("Drama", series[1].getGenre());
54 | }
55 |
56 | @Test
57 | public void getJsonSeries() {
58 | List> converters = new ArrayList>();
59 | converters.add(new MappingJackson2HttpMessageConverter());
60 | restTemplate.setMessageConverters(converters);
61 |
62 | String uri = BASE_URI + "/{seriesId}";
63 | ResponseEntity seriesEntity = restTemplate.getForEntity(uri, Series.class, 1l);
64 | assertNotNull(seriesEntity.getBody());
65 | assertEquals(1l, seriesEntity.getBody().getId());
66 | assertEquals("The walking dead", seriesEntity.getBody().getName());
67 | assertEquals("USA", seriesEntity.getBody().getCountry());
68 | assertEquals("Thriller", seriesEntity.getBody().getGenre());
69 |
70 | assertEquals(MediaType.parseMediaType("application/json;charset=UTF-8"), seriesEntity.getHeaders().getContentType());
71 | }
72 |
73 | @Test
74 | public void getXmlSeries() {
75 | String uri = BASE_URI + "/{seriesId}";
76 | ResponseEntity seriesEntity = restTemplate.getForEntity(uri, Series.class, 1L);
77 | assertNotNull(seriesEntity.getBody());
78 | assertEquals(1l, seriesEntity.getBody().getId());
79 | assertEquals("The walking dead", seriesEntity.getBody().getName());
80 | assertEquals("USA", seriesEntity.getBody().getCountry());
81 | assertEquals("Thriller", seriesEntity.getBody().getGenre());
82 |
83 | assertEquals(MediaType.APPLICATION_XML, seriesEntity.getHeaders().getContentType());
84 | }
85 |
86 | @Test
87 | public void getNotFoundSeries() {
88 | String uri = BASE_URI + "/{seriesId}";
89 |
90 | try {
91 | restTemplate.getForEntity(uri, Series.class, 5L);
92 | } catch (HttpClientErrorException e) {
93 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
94 | }
95 | }
96 |
97 | @Test
98 | public void insertNewSeries() {
99 | Series series = new Series();
100 | series.setId(4L);
101 | series.setName("mySeries");
102 | series.setCountry("England");
103 | series.setGenre("sci-fi");
104 |
105 | URI newUserLocation = restTemplate.postForLocation(BASE_URI, series);
106 | assertEquals(BASE_URI + "/4", newUserLocation.toString());
107 | }
108 |
109 | @Test
110 | public void deleteExistingSeries() {
111 | String uri = BASE_URI + "/{seriesId}";
112 | restTemplate.delete(uri, 2L);
113 |
114 | try {
115 | restTemplate.getForEntity(uri, Series.class, 2L);
116 | } catch (HttpClientErrorException e) {
117 | assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/java/xpadro/spring/web/test/SeriesIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package xpadro.spring.web.test;
2 |
3 | import static org.hamcrest.Matchers.hasSize;
4 | import static org.hamcrest.Matchers.is;
5 | import static org.hamcrest.Matchers.endsWith;
6 | import static org.mockito.Mockito.*;
7 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
8 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
9 | import org.springframework.test.context.ContextConfiguration;
10 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 | import org.springframework.test.context.web.WebAppConfiguration;
12 | import org.springframework.test.web.servlet.MockMvc;
13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
14 | import org.junit.Before;
15 | import org.junit.Test;
16 | import org.junit.runner.RunWith;
17 |
18 | import org.springframework.beans.factory.annotation.Autowired;
19 | import org.springframework.web.context.WebApplicationContext;
20 | import org.springframework.http.MediaType;
21 |
22 | import xpadro.spring.web.model.Series;
23 | import xpadro.spring.web.service.SeriesService;
24 |
25 | @RunWith(SpringJUnit4ClassRunner.class)
26 | @WebAppConfiguration
27 | @ContextConfiguration(locations={
28 | "classpath:xpadro/spring/web/test/configuration/test-root-context.xml",
29 | "classpath:xpadro/spring/web/configuration/app-context.xml"})
30 | public class SeriesIntegrationTest {
31 | private static final String BASE_URI = "/series";
32 |
33 | private MockMvc mockMvc;
34 |
35 | @Autowired
36 | private WebApplicationContext webApplicationContext;
37 |
38 | @Autowired
39 | private SeriesService seriesService;
40 |
41 |
42 | @Before
43 | public void setUp() {
44 | reset(seriesService);
45 | mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
46 |
47 | when(seriesService.getAllSeries()).thenReturn(new Series[]{
48 | new Series(1, "The walking dead", "USA", "Thriller"),
49 | new Series(2, "Homeland", "USA", "Drama")});
50 |
51 | when(seriesService.getSeries(1L)).thenReturn(new Series(1, "Fringe", "USA", "Thriller"));
52 | }
53 |
54 |
55 | @Test
56 | public void getAllSeries() throws Exception {
57 | mockMvc.perform(get(BASE_URI)
58 | .accept(MediaType.APPLICATION_JSON))
59 | .andExpect(status().isOk())
60 | .andExpect(content().contentType("application/json;charset=UTF-8"))
61 | .andExpect(jsonPath("$", hasSize(2)))
62 | .andExpect(jsonPath("$[0].id", is(1)))
63 | .andExpect(jsonPath("$[0].name", is("The walking dead")))
64 | .andExpect(jsonPath("$[0].country", is("USA")))
65 | .andExpect(jsonPath("$[0].genre", is("Thriller")))
66 | .andExpect(jsonPath("$[1].id", is(2)))
67 | .andExpect(jsonPath("$[1].name", is("Homeland")))
68 | .andExpect(jsonPath("$[1].country", is("USA")))
69 | .andExpect(jsonPath("$[1].genre", is("Drama")));
70 |
71 | verify(seriesService, times(1)).getAllSeries();
72 | verifyZeroInteractions(seriesService);
73 | }
74 |
75 | @Test
76 | public void getJsonSeries() throws Exception {
77 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 1L)
78 | .accept(MediaType.APPLICATION_JSON))
79 | .andExpect(status().isOk())
80 | .andExpect(content().contentType("application/json;charset=UTF-8"))
81 | .andExpect(jsonPath("$.id", is(1)))
82 | .andExpect(jsonPath("$.name", is("Fringe")))
83 | .andExpect(jsonPath("$.country", is("USA")))
84 | .andExpect(jsonPath("$.genre", is("Thriller")));
85 |
86 | verify(seriesService, times(1)).getSeries(1L);
87 | verifyZeroInteractions(seriesService);
88 | }
89 |
90 | @Test
91 | public void getXmlSeries() throws Exception {
92 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 1L)
93 | .accept(MediaType.APPLICATION_XML))
94 | .andExpect(status().isOk())
95 | .andExpect(content().contentType(MediaType.APPLICATION_XML))
96 | .andExpect(xpath("/series/id").string("1"))
97 | .andExpect(xpath("/series/name").string("Fringe"))
98 | .andExpect(xpath("/series/country").string("USA"))
99 | .andExpect(xpath("/series/genre").string("Thriller"));
100 |
101 |
102 | verify(seriesService, times(1)).getSeries(1L);
103 | verifyZeroInteractions(seriesService);
104 | }
105 |
106 | @Test
107 | public void getNotFoundSeries() throws Exception {
108 | mockMvc.perform(get(BASE_URI + "/{seriesId}", 5L)
109 | .accept(MediaType.APPLICATION_JSON))
110 | .andExpect(status().isNotFound());
111 |
112 | verify(seriesService, times(1)).getSeries(5L);
113 | verifyZeroInteractions(seriesService);
114 | }
115 |
116 | @Test
117 | public void insertNewSeries() throws Exception {
118 | mockMvc.perform(post(BASE_URI)
119 | .content("{ \"id\": 3, \"name\": \"mySeries\", \"country\": \"England\", \"genre\": \"sci-fi\" } }")
120 | .contentType(MediaType.APPLICATION_JSON)
121 | .accept(MediaType.APPLICATION_JSON))
122 | .andExpect(status().isCreated())
123 | .andExpect(header().string("Location", endsWith("/series/3")));
124 |
125 | verify(seriesService, times(1)).insertSeries(any(Series.class));
126 | verifyZeroInteractions(seriesService);
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/spring-rest-api-v4/src/test/resources/xpadro/spring/web/test/configuration/test-root-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------