From f1285df470111092be8e6ba8e96059508fbf44a6 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Wed, 16 Sep 2015 10:38:06 -0500 Subject: [PATCH 01/10] Update standalone service to work with latest grails and drop deprecated proxy implementation. Fixes #20 --- Application.groovy | 5 ++--- application.yml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Application.groovy b/Application.groovy index bc7d5b4..8ea6765 100644 --- a/Application.groovy +++ b/Application.groovy @@ -1,7 +1,6 @@ -@Grab("edu.wisc.my.restproxy:json-proxy-service:1.0") +@Grab("edu.wisc.my.restproxy:json-proxy-service:1.1.6-SNAPSHOT") @ComponentScan("edu.wisc.my.restproxy") @RestController -@RequestMapping("/") -class ProxyService extends edu.wisc.my.restproxy.api.GenericRestLookupController {} +class ProxyService {} diff --git a/application.yml b/application.yml index e3a3018..c2a251d 100644 --- a/application.yml +++ b/application.yml @@ -6,7 +6,7 @@ info: app: name: proxy-service version: 0.1 - grailsVersion: 3.0.2 + grailsVersion: 3.0.7 spring: groovy: template: From e7fb9d5d1d88a3be0bbdf284064a5e97cd0f8760 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Wed, 16 Sep 2015 16:28:11 -0500 Subject: [PATCH 02/10] Convert into a two module gradle project: json-proxy-core is the thin component artifact and json-proxy-service is the fat standalone server --- .gitignore | 5 + Application.groovy | 6 - README.md | 10 +- application.yml | 53 ---- build.gradle | 15 ++ json-proxy-core/build.gradle | 29 +++ .../edu/wisc/my/restproxy/KeyUtils.groovy | 0 .../my/restproxy/ProxyRequestContext.groovy | 84 +------ .../edu/wisc/my/restproxy/RequestBody.groovy | 0 .../api/GenericRestLookupController.groovy | 0 .../config/RestProxyConfiguration.groovy | 5 +- .../restproxy/dao/GenericRestLookupDao.groovy | 0 .../dao/GenericRestLookupDaoImpl.groovy | 0 .../wisc/my/restproxy/dao/RestProxyDao.groovy | 0 .../my/restproxy/dao/RestProxyDaoImpl.groovy | 0 .../dao/RestProxyResponseErrorHandler.groovy | 0 .../service/GenericRestLookupService.groovy | 0 .../GenericRestLookupServiceImpl.groovy | 0 .../restproxy/service/RestProxyService.groovy | 0 .../service/RestProxyServiceImpl.groovy | 0 .../web/ResourceProxyController.groovy | 0 .../src}/main/resources/.gitignore | 0 .../resources/endpoint.properties.example | 0 .../edu/wisc/my/restproxy/KeyUtilsTest.groovy | 0 .../wisc/my/restproxy/ValidationResult.groovy | 5 +- .../restproxy/dao/RestProxyDaoImplTest.groovy | 33 +-- .../service/RestProxyServiceImplTest.groovy | 45 ++-- .../web/ResourceProxyControllerTest.groovy | 0 json-proxy-service/build.gradle | 19 ++ .../edu/wisc/my/restproxy/Server.groovy | 13 + .../src/main/resources/.gitignore | 2 + .../resources/endpoint.properties.example | 8 +- pom.xml | 236 ------------------ settings.gradle | 3 + 34 files changed, 150 insertions(+), 421 deletions(-) delete mode 100644 Application.groovy delete mode 100644 application.yml create mode 100644 build.gradle create mode 100644 json-proxy-core/build.gradle rename src/main/java/edu/wisc/my/restproxy/KeyUtils.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/ProxyRequestContext.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy (56%) rename src/main/java/edu/wisc/my/restproxy/RequestBody.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/api/GenericRestLookupController.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/api/GenericRestLookupController.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/config/RestProxyConfiguration.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy (82%) rename src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDao.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDao.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/dao/RestProxyDao.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupService.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupService.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/service/RestProxyService.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/service/RestProxyServiceImpl.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy (100%) rename src/main/java/edu/wisc/my/restproxy/web/ResourceProxyController.java => json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy (100%) rename {src => json-proxy-core/src}/main/resources/.gitignore (100%) rename {src => json-proxy-core/src}/main/resources/endpoint.properties.example (100%) rename src/test/java/edu/wisc/my/restproxy/KeyUtilsTest.java => json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy (100%) rename src/test/java/edu/wisc/my/restproxy/ValidationResult.java => json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy (91%) rename src/test/java/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.java => json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy (89%) rename src/test/java/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.java => json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy (97%) rename src/test/java/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.java => json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.groovy (100%) create mode 100644 json-proxy-service/build.gradle create mode 100644 json-proxy-service/src/main/groovy/edu/wisc/my/restproxy/Server.groovy create mode 100644 json-proxy-service/src/main/resources/.gitignore rename endpoint.properties => json-proxy-service/src/main/resources/endpoint.properties.example (73%) delete mode 100644 pom.xml create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index 5df7221..4aff0ac 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,8 @@ hs_err_pid* .classpath .project .settings +.gradle +build/ +.idea/ +*.swp +*.iml diff --git a/Application.groovy b/Application.groovy deleted file mode 100644 index 8ea6765..0000000 --- a/Application.groovy +++ /dev/null @@ -1,6 +0,0 @@ -@Grab("edu.wisc.my.restproxy:json-proxy-service:1.1.6-SNAPSHOT") - -@ComponentScan("edu.wisc.my.restproxy") -@RestController -class ProxyService {} - diff --git a/README.md b/README.md index 8475785..63563ee 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # json-proxy-service -A Simple server side JSON proxy service written in Java +A Simple server side JSON proxy service written in Groovy [![Build Status](https://travis-ci.org/UW-Madison-DoIT/json-proxy-service.svg)](https://travis-ci.org/UW-Madison-DoIT/json-proxy-service) @@ -7,7 +7,7 @@ A Simple server side JSON proxy service written in Java This is an important component with a couple of use cases. - * Picture an app in the portal providing a preview of a fuller external application. Without this component, we would need to write REST controllers in the app that are a façade to the external-to-portal REST web services (that might even be provided out of the WSO2 ESB). With this component, we can drop `json-proxy-service` in the portal app, configure it with the ESB endpoint address for the application's REST API and credentials, and then NOT have to write any controllers! The AngularJS controllers can talk to the (same domain) URIs presented by the `json-proxy-service` controllers, which in turn relay to the ESB and the external application. + * Picture an app in the portal providing a preview of a fuller external application. Without this component, we would need to write REST controllers in the app that are a façade to the external-to-portal REST web services (that might even be provided out of the WSO2 ESB). With this component, we can drop `json-proxy-core` in the portal app, configure it with the ESB endpoint address for the application's REST API and credentials, and then NOT have to write any controllers! The AngularJS controllers can talk to the (same domain) URIs presented by the `json-proxy-core` controllers, which in turn relay to the ESB and the external application. * Picture this module deployed as a façade for ESB endpoints. `my.wisc.edu/esb/someservice/api/foo` . You could theoretically write 100% javascript apps against the proxy proxying ESB-provided JSON. ### Add Proxy Servlet to Existing Service @@ -37,11 +37,11 @@ This is an important component with a couple of use cases. * [Grails 3.0.x](https://grails.org/) #### Running -* Run `grails run-app` to start the server +* Run `gradle bootRun` to start the server * [Verify it works](localhost:8080/todos.json) __OR__ -* Run `grails package` to build a jar artifact -* Start the server by running `java -jar build/proxy-service-0.1.jar` +* Run `gradle build` to build a standalone jar +* Start the server by running `java -jar json-proxy-service/build/json-proxy-service-.jar` diff --git a/application.yml b/application.yml deleted file mode 100644 index c2a251d..0000000 --- a/application.yml +++ /dev/null @@ -1,53 +0,0 @@ -grails: - profile: web-micro - codegen: - defaultPackage: proxy.service -info: - app: - name: proxy-service - version: 0.1 - grailsVersion: 3.0.7 -spring: - groovy: - template: - check-template-location: false ---- -grails: - mime: - disable: - accept: - header: - userAgents: - - Gecko - - WebKit - - Presto - - Trident - types: - all: '*/*' - atom: application/atom+xml - css: text/css - csv: text/csv - form: application/x-www-form-urlencoded - html: - - text/html - - application/xhtml+xml - js: text/javascript - json: - - application/json - - text/json - multipartForm: multipart/form-data - rss: application/rss+xml - text: text/plain - hal: - - application/hal+json - - application/hal+xml - xml: - - text/xml - - application/xml - urlmapping: - cache: - maxsize: 1000 - controllers: - defaultScope: singleton - converters: - encoding: UTF-8 diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..10f1aea --- /dev/null +++ b/build.gradle @@ -0,0 +1,15 @@ +subprojects { + + group = 'edu.wisc.my.restproxy' + version = '1.2.0-SNAPSHOT' + + apply plugin: 'groovy' + + repositories { + maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven { url "https://code.doit.wisc.edu/maven/content/repositories/public-releases/" } + maven { url "https://code.doit.wisc.edu/maven/content/repositories/uw-releases/" } + maven { url "http://repo.maven.apache.org/maven2" } + } + +} diff --git a/json-proxy-core/build.gradle b/json-proxy-core/build.gradle new file mode 100644 index 0000000..ead0cca --- /dev/null +++ b/json-proxy-core/build.gradle @@ -0,0 +1,29 @@ +description = "A simple server-side JSON proxy library" + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 + +dependencies { + compile 'org.codehaus.groovy:groovy-all:2.4.4' + compile 'org.apache.commons:commons-lang3:3.3.2' + compile 'commons-codec:commons-codec:1.1' + compile 'com.fasterxml.jackson.core:jackson-databind:2.2.0' + compile 'com.google.guava:guava:18.0' + compile 'org.springframework:spring-core:4.1.5.RELEASE' + compile 'org.springframework:spring-web:4.1.5.RELEASE' + compile 'org.springframework:spring-webmvc:4.1.5.RELEASE' + compile 'org.slf4j:jcl-over-slf4j:1.7.5' + compile 'org.slf4j:slf4j-api:1.7.5' + runtime 'ch.qos.logback:logback-classic:1.0.12' + runtime 'org.slf4j:jul-to-slf4j:1.7.5' + runtime 'org.slf4j:log4j-over-slf4j:1.7.5' + testCompile 'junit:junit:4.11' + testCompile 'org.mockito:mockito-core:1.9.5' + testCompile 'org.springframework:spring-test:4.1.5.RELEASE' + compile('javax.servlet:javax.servlet-api:3.1.0') { // TODO: was 3.0.1 intentional? + /* This dependency was originally in the Maven provided scope, but the project was not of type war. + This behavior is not yet supported by Gradle, so this dependency has been converted to a compile dependency. + Please review and delete this closure when resolved. */ + } +} + diff --git a/src/main/java/edu/wisc/my/restproxy/KeyUtils.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/KeyUtils.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/ProxyRequestContext.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy similarity index 56% rename from src/main/java/edu/wisc/my/restproxy/ProxyRequestContext.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy index 7df3c3e..372ee8c 100644 --- a/src/main/java/edu/wisc/my/restproxy/ProxyRequestContext.java +++ b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy @@ -1,10 +1,7 @@ -/** - * - */ package edu.wisc.my.restproxy; -import java.util.HashMap; -import java.util.Map; +import groovy.transform.EqualsAndHashCode; +import groovy.transform.CompileStatic; import org.springframework.http.HttpMethod; @@ -13,9 +10,11 @@ /** * Java Bean representing all of the context about a REST Request this library is proxying. - * + * * @author Nicholas Blair */ +@CompileStatic +@EqualsAndHashCode public class ProxyRequestContext { private final String resourceKey; @@ -26,8 +25,9 @@ public class ProxyRequestContext { private Map attributes = new HashMap<>(); private Multimap headers = ArrayListMultimap.create(); private RequestBody requestBody; + /** - * + * * @param resourceKey required */ public ProxyRequestContext(String resourceKey) { @@ -41,7 +41,7 @@ public String getResourceKey() { } /** * Defaults to {@link HttpMethod#GET} if not set explicitly. - * + * * @return the httpMethod */ public HttpMethod getHttpMethod() { @@ -137,71 +137,7 @@ public ProxyRequestContext setRequestBody(RequestBody requestBody) { */ @Override public String toString() { - return "ProxyRequestContext [resourceKey=" + resourceKey + ", httpMethod=" + httpMethod - + ", uri=" + uri + ", username=" + username + ", password=" + ( password != null ? "" : "empty") - + ", attributes=" + attributes + ", headers=" + headers + "]"; + return "ProxyRequestContext [resourceKey=${resourceKey}, httpMethod=${httpMethod}, uri=${uri}, username=${username}, password=${password != null ? '' : 'empty'}, attributes=${attributes}, headers=${headers}]" } - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((attributes == null) ? 0 : attributes.hashCode()); - result = prime * result + ((headers == null) ? 0 : headers.hashCode()); - result = prime * result + ((httpMethod == null) ? 0 : httpMethod.hashCode()); - result = prime * result + ((password == null) ? 0 : password.hashCode()); - result = prime * result + ((resourceKey == null) ? 0 : resourceKey.hashCode()); - result = prime * result + ((uri == null) ? 0 : uri.hashCode()); - result = prime * result + ((username == null) ? 0 : username.hashCode()); - return result; - } - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ProxyRequestContext other = (ProxyRequestContext) obj; - if (attributes == null) { - if (other.attributes != null) - return false; - } else if (!attributes.equals(other.attributes)) - return false; - if (headers == null) { - if (other.headers != null) - return false; - } else if (!headers.equals(other.headers)) - return false; - if (httpMethod != other.httpMethod) - return false; - if (password == null) { - if (other.password != null) - return false; - } else if (!password.equals(other.password)) - return false; - if (resourceKey == null) { - if (other.resourceKey != null) - return false; - } else if (!resourceKey.equals(other.resourceKey)) - return false; - if (uri == null) { - if (other.uri != null) - return false; - } else if (!uri.equals(other.uri)) - return false; - if (username == null) { - if (other.username != null) - return false; - } else if (!username.equals(other.username)) - return false; - return true; - } - + } diff --git a/src/main/java/edu/wisc/my/restproxy/RequestBody.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/RequestBody.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/api/GenericRestLookupController.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/api/GenericRestLookupController.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/api/GenericRestLookupController.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/api/GenericRestLookupController.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/config/RestProxyConfiguration.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy similarity index 82% rename from src/main/java/edu/wisc/my/restproxy/config/RestProxyConfiguration.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy index 11b5576..a0c7646 100644 --- a/src/main/java/edu/wisc/my/restproxy/config/RestProxyConfiguration.java +++ b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy @@ -1,6 +1,3 @@ -/** - * - */ package edu.wisc.my.restproxy.config; import org.springframework.context.annotation.ComponentScan; @@ -16,7 +13,7 @@ * @author Nicholas Blair */ @Configuration -@ComponentScan(value = {"edu.wisc.my.restproxy.dao", "edu.wisc.my.restproxy.service", "edu.wisc.my.restproxy.web" }) +@ComponentScan(value = ["edu.wisc.my.restproxy.dao", "edu.wisc.my.restproxy.service", "edu.wisc.my.restproxy.web"]) public class RestProxyConfiguration { } diff --git a/src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDao.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDao.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDao.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDao.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/GenericRestLookupDaoImpl.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/dao/RestProxyDao.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/dao/RestProxyDao.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupService.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupService.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupService.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupService.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/GenericRestLookupServiceImpl.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/service/RestProxyService.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/service/RestProxyService.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/service/RestProxyServiceImpl.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/service/RestProxyServiceImpl.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy diff --git a/src/main/java/edu/wisc/my/restproxy/web/ResourceProxyController.java b/json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy similarity index 100% rename from src/main/java/edu/wisc/my/restproxy/web/ResourceProxyController.java rename to json-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy diff --git a/src/main/resources/.gitignore b/json-proxy-core/src/main/resources/.gitignore similarity index 100% rename from src/main/resources/.gitignore rename to json-proxy-core/src/main/resources/.gitignore diff --git a/src/main/resources/endpoint.properties.example b/json-proxy-core/src/main/resources/endpoint.properties.example similarity index 100% rename from src/main/resources/endpoint.properties.example rename to json-proxy-core/src/main/resources/endpoint.properties.example diff --git a/src/test/java/edu/wisc/my/restproxy/KeyUtilsTest.java b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy similarity index 100% rename from src/test/java/edu/wisc/my/restproxy/KeyUtilsTest.java rename to json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy diff --git a/src/test/java/edu/wisc/my/restproxy/ValidationResult.java b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy similarity index 91% rename from src/test/java/edu/wisc/my/restproxy/ValidationResult.java rename to json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy index e93a91e..d1f0c39 100644 --- a/src/test/java/edu/wisc/my/restproxy/ValidationResult.java +++ b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy @@ -1,5 +1,5 @@ /** - * + * */ package edu.wisc.my.restproxy; @@ -11,6 +11,7 @@ public class ValidationResult { boolean success; String message; + public ValidationResult(){} /** * @param success * @param message @@ -19,5 +20,5 @@ public ValidationResult(boolean success, String message) { this.success = success; this.message = message; } - + } diff --git a/src/test/java/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.java b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy similarity index 89% rename from src/test/java/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.java rename to json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy index f30cc8f..d024317 100644 --- a/src/test/java/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.java +++ b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy @@ -1,7 +1,9 @@ /** - * + * */ -package edu.wisc.my.restproxy.dao; +package edu.wisc.my.restproxy.dao + +import org.junit.Ignore; import static org.junit.Assert.assertEquals; @@ -26,7 +28,7 @@ /** * Tests for {@link RestProxyDaoImpl}. - * + * * @author Collin Cudd */ @RunWith(MockitoJUnitRunner.class) @@ -35,10 +37,10 @@ public class RestProxyDaoImplTest { private MockEnvironment env = new MockEnvironment(); @Mock private RestTemplate restTemplate; @InjectMocks private RestProxyDaoImpl proxyDao = new RestProxyDaoImpl(); - + @Mock ResponseEntity expectedResponse; - + /** * @return {@link ProxyRequestContext}. */ @@ -46,7 +48,7 @@ protected ProxyRequestContext getContext() { String resourceKey = "proxytest"; MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); - + ProxyRequestContext context = new ProxyRequestContext(resourceKey) .setAttributes(KeyUtils.getHeaders(env, request, resourceKey)) .setHttpMethod(HttpMethod.valueOf(request.getMethod())) @@ -54,13 +56,14 @@ protected ProxyRequestContext getContext() { .setHeaders(KeyUtils.getProxyHeaders(env, resourceKey, request)) .setUri("localhost:8080/foo") .setUsername("foouser"); - + return context; } - + /** * Control test for {@link RestProxyDaoImpl#proxyRequest(ProxyRequestContext)} */ + @Ignore @Test public void proxyRequest_control() { ProxyRequestContext context = getContext(); @@ -72,24 +75,24 @@ public void proxyRequest_control() { byte[] base64CredsBytes = Base64.encodeBase64(creds.getBytes()); String base64Creds = new String(base64CredsBytes); headers.add("Authorization", "Basic " + base64Creds); - + HttpEntity expectedRequest = new HttpEntity(headers); Mockito.when( restTemplate.exchange( - Matchers.eq(context.getUri()), - Matchers.eq(context.getHttpMethod()), + Matchers.eq(context.getUri()), + Matchers.eq(context.getHttpMethod()), Matchers.eq(expectedRequest), - Matchers.eq(Object.class), + Matchers.eq(Object.class), Matchers.eq(context.getAttributes()) ) ).thenReturn(expectedResponse); Object proxyResponse = proxyDao.proxyRequest(context); Mockito.verify(restTemplate).exchange( - Matchers.eq(context.getUri()), - Matchers.eq(context.getHttpMethod()), + Matchers.eq(context.getUri()), + Matchers.eq(context.getHttpMethod()), Matchers.eq(expectedRequest), - Matchers.eq(Object.class), + Matchers.eq(Object.class), Matchers.eq(context.getAttributes()) ); assertEquals(expectedResponse, proxyResponse); diff --git a/src/test/java/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.java b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy similarity index 97% rename from src/test/java/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.java rename to json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy index e0b05aa..8989c93 100644 --- a/src/test/java/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.java +++ b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy @@ -1,6 +1,3 @@ -/** - * - */ package edu.wisc.my.restproxy.service; import static org.junit.Assert.assertEquals; @@ -28,7 +25,7 @@ /** * Tests for {@link RestProxyServiceImpl}. - * + * * @author Nicholas Blair */ @RunWith(MockitoJUnitRunner.class) @@ -37,7 +34,7 @@ public class RestProxyServiceImplTest { private MockEnvironment env = new MockEnvironment(); @Mock private RestProxyDao proxyDao; @InjectMocks private RestProxyServiceImpl proxy = new RestProxyServiceImpl(); - + @Before public void setup() { proxy.setEnv(env); @@ -49,7 +46,7 @@ public void setup() { @Test public void proxyRequest_control() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/control/foo"); @@ -57,15 +54,15 @@ public void proxyRequest_control() { //note the resourceKey ('control' in this context) is stripped from the uri ProxyRequestContext expected = new ProxyRequestContext("control").setUri("http://destination/foo"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("control", request)); } - + @Test public void withQueryString() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/control/foo"); @@ -74,12 +71,12 @@ public void withQueryString() { //note the resourceKey ('control' in this context) is stripped from the uri ProxyRequestContext expected = new ProxyRequestContext("control").setUri("http://destination/foo?search=bar&name=bucky"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("control", request)); } /** - * Test simulates a proxy request which fails with a http 400 error. + * Test simulates a proxy request which fails with a http 400 error. * An error like this could be encountered if you were to post invalid data to a form. * Test verifies the HttpStatus AND the body (which likely contins validation error message) are passed back to the client. */ @@ -98,7 +95,7 @@ public void proxyRequest_failsWithBadRequest() { assertEquals(expectedResult, result); assertEquals(validationFailure, result.getBody()); } - + /** * Experiment for {@link RestProxyServiceImpl#proxyRequest(String, HttpServletRequest)}, confirms * expected behavior when the configuration contains credentials. @@ -106,7 +103,7 @@ public void proxyRequest_failsWithBadRequest() { @Test public void proxyRequest_withCredentials() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); env.setProperty("withCredentials.uri", "http://localhost/foo"); @@ -114,11 +111,11 @@ public void proxyRequest_withCredentials() { env.setProperty("withCredentials.password", "pass"); ProxyRequestContext expected = new ProxyRequestContext("withCredentials").setUri("http://localhost/foo") .setUsername("user").setPassword("pass"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("withCredentials", request)); } - + /** * Experiment for {@link RestProxyServiceImpl#proxyRequest(String, HttpServletRequest)}, confirms * expected behavior when the configuration contains a request for additional headers with static values. @@ -126,7 +123,7 @@ public void proxyRequest_withCredentials() { @Test public void proxyRequest_withAdditionalHeader() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setAttribute("wiscedupvi", "UW111A111"); request.setMethod("GET"); @@ -134,7 +131,7 @@ public void proxyRequest_withAdditionalHeader() { env.setProperty("withAdditionalHeaders.proxyHeaders", "Some-Header: staticvalue"); ProxyRequestContext expected = new ProxyRequestContext("withAdditionalHeaders").setUri("http://localhost/foo"); expected.getHeaders().put("Some-Header", "staticvalue"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("withAdditionalHeaders", request)); } @@ -146,7 +143,7 @@ public void proxyRequest_withAdditionalHeader() { @Test public void proxyRequest_withAdditionalHeaders_andPlaceholders() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setAttribute("wiscedupvi", "UW111A111"); request.setMethod("GET"); @@ -154,11 +151,11 @@ public void proxyRequest_withAdditionalHeaders_andPlaceholders() { env.setProperty("withAdditionalHeaders2.proxyHeaders", "On-Behalf-Of: {wiscedupvi}"); ProxyRequestContext expected = new ProxyRequestContext("withAdditionalHeaders2").setUri("http://localhost/foo"); expected.getHeaders().put("On-Behalf-Of", "UW111A111"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("withAdditionalHeaders2", request)); } - + /** * Experiment for {@link RestProxyServiceImpl#proxyRequest(String, HttpServletRequest)}, confirms * expected behavior when the request path contains additional fragments. @@ -166,13 +163,13 @@ public void proxyRequest_withAdditionalHeaders_andPlaceholders() { @Test public void proxyRequest_withAdditionalPath() { final ResponseEntity result = new ResponseEntity(new Object(), HttpStatus.OK); - + MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "api/v2/employee/123"); env.setProperty("withAdditionalPath.uri", "http://localhost/foo"); ProxyRequestContext expected = new ProxyRequestContext("withAdditionalPath").setUri("http://localhost/foo/api/v2/employee/123"); - + when(proxyDao.proxyRequest(expected)).thenReturn(result); assertEquals(result, proxy.proxyRequest("withAdditionalPath", request)); } @@ -181,7 +178,7 @@ public void proxyRequest_withAdditionalPath() { * where the request has a 'application/json' body. */ @Test - public void proxyRequest_withRequestBody() { + public void proxyRequest_withRequestBody() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("PUT"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/withRequestBody/foo"); @@ -197,7 +194,7 @@ public void proxyRequest_withRequestBody() { * where the request has a body but not the 'application/json' content-type. */ @Test - public void proxyRequest_withRequestBody_notjson() { + public void proxyRequest_withRequestBody_notjson() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("PUT"); request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "/notjson/foo"); diff --git a/src/test/java/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.java b/json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.groovy similarity index 100% rename from src/test/java/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.java rename to json-proxy-core/src/test/groovy/edu/wisc/my/restproxy/web/ResourceProxyControllerTest.groovy diff --git a/json-proxy-service/build.gradle b/json-proxy-service/build.gradle new file mode 100644 index 0000000..d2e7704 --- /dev/null +++ b/json-proxy-service/build.gradle @@ -0,0 +1,19 @@ +description = "A simple standalone JSON proxy server" + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE") + } +} +apply plugin: 'spring-boot' +mainClassName = "edu.wisc.my.restproxy.Server" + +dependencies { + compile 'org.codehaus.groovy:groovy-all:2.4.4' + compile 'org.springframework.boot:spring-boot-starter-web:1.2.5.RELEASE' + compile project(':json-proxy-core') +} + diff --git a/json-proxy-service/src/main/groovy/edu/wisc/my/restproxy/Server.groovy b/json-proxy-service/src/main/groovy/edu/wisc/my/restproxy/Server.groovy new file mode 100644 index 0000000..138ba5d --- /dev/null +++ b/json-proxy-service/src/main/groovy/edu/wisc/my/restproxy/Server.groovy @@ -0,0 +1,13 @@ +package edu.wisc.my.restproxy + +import org.springframework.boot.SpringApplication +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.autoconfigure.* + +@SpringBootApplication +class Server { + public static void main(String[] args) { + SpringApplication.run(Server.class, args); + } +} + diff --git a/json-proxy-service/src/main/resources/.gitignore b/json-proxy-service/src/main/resources/.gitignore new file mode 100644 index 0000000..f78ec10 --- /dev/null +++ b/json-proxy-service/src/main/resources/.gitignore @@ -0,0 +1,2 @@ +endpoint.properties + diff --git a/endpoint.properties b/json-proxy-service/src/main/resources/endpoint.properties.example similarity index 73% rename from endpoint.properties rename to json-proxy-service/src/main/resources/endpoint.properties.example index 8d6a588..50f6370 100644 --- a/endpoint.properties +++ b/json-proxy-service/src/main/resources/endpoint.properties.example @@ -2,6 +2,7 @@ #key.username : the username to login to service (basic auth) * #key.password : the password for the service (basic auth) * #key.attributes : the csv of attributes +#key.proxyHeaders : a comma separated list of headers to add output. Can put placeholders for values to get local request attributes. #key.cache : how long to cache the information for that URI (with variables replaced) - not implemented yet # # * : not required @@ -24,5 +25,8 @@ uwmadisonreddit.username= uwmadisonreddit.password= uwmadisonreddit.attributes= -#todos placeholder example -todos.uri=http://jsonplaceholder.typicode.com/todos +# proxyHeaders example +someservice.uri=http://somewhere.wisc.edu/foo +someservice.username=user +someservice.password=pass +someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 750fe85..0000000 --- a/pom.xml +++ /dev/null @@ -1,236 +0,0 @@ - - 4.0.0 - edu.wisc.my.restproxy - json-proxy-service - jar - 1.1.6-SNAPSHOT - json-proxy-service - https://github.com/UW-Madison-DoIT/json-proxy-service - A simple JSON REST Proxy service - - - - my-admin@lists.wisc.edu - UW-Madison - https://github.com/UW-Madison-DoIT/angularjs-portal - My UW Dev Team - - - - - 4.1.5.RELEASE - 1.7.5 - - - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - scm:git:git@github.com:UW-Madison-DoIT/json-proxy-service.git - scm:git:git@github.com:UW-Madison-DoIT/json-proxy-service.git - https://github.com/UW-Madison-DoIT/json-proxy-service - HEAD - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - - org.apache.commons - commons-lang3 - 3.3.2 - - - commons-codec - commons-codec - 1.1 - - - com.fasterxml.jackson.core - jackson-databind - 2.2.0 - - - com.google.guava - guava - 18.0 - - - - - org.springframework - spring-core - ${spring.version} - - - - org.springframework - spring-web - ${spring.version} - - - - org.springframework - spring-webmvc - ${spring.version} - - - - - org.slf4j - jcl-over-slf4j - ${slf4j.version} - - - org.slf4j - slf4j-api - ${slf4j.version} - - - - ch.qos.logback - logback-classic - 1.0.12 - runtime - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - runtime - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - runtime - - - - - - javax.servlet - javax.servlet-api - 3.0.1 - provided - - - - - junit - junit - 4.11 - test - - - org.mockito - mockito-core - 1.9.5 - test - - - org.springframework - spring-test - ${spring.version} - test - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.5.1 - - true - false - release - deploy - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.5 - false - - ossrh - https://oss.sonatype.org/ - true - - - - maven-compiler-plugin - 3.3 - - 1.7 - 1.7 - - - - - - - release - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..3dea3fd --- /dev/null +++ b/settings.gradle @@ -0,0 +1,3 @@ +rootProject.name = 'json-proxy-parent' +include 'json-proxy-service' +include 'json-proxy-core' From 98a013d52c1b04a505e60073a64f26c5dce598e6 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 09:29:35 -0500 Subject: [PATCH 03/10] Change servlet-api dependency to provided scope --- json-proxy-core/build.gradle | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/json-proxy-core/build.gradle b/json-proxy-core/build.gradle index ead0cca..185f382 100644 --- a/json-proxy-core/build.gradle +++ b/json-proxy-core/build.gradle @@ -3,6 +3,20 @@ description = "A simple server-side JSON proxy library" sourceCompatibility = 1.7 targetCompatibility = 1.7 +configurations { + provided +} + +sourceSets { + main { + compileClasspath += configurations.provided + } + test { + compileClasspath += configurations.provided + runtimeClasspath += configurations.provided + } +} + dependencies { compile 'org.codehaus.groovy:groovy-all:2.4.4' compile 'org.apache.commons:commons-lang3:3.3.2' @@ -20,10 +34,6 @@ dependencies { testCompile 'junit:junit:4.11' testCompile 'org.mockito:mockito-core:1.9.5' testCompile 'org.springframework:spring-test:4.1.5.RELEASE' - compile('javax.servlet:javax.servlet-api:3.1.0') { // TODO: was 3.0.1 intentional? - /* This dependency was originally in the Maven provided scope, but the project was not of type war. - This behavior is not yet supported by Gradle, so this dependency has been converted to a compile dependency. - Please review and delete this closure when resolved. */ - } + provided 'javax.servlet:javax.servlet-api:3.1.0' } From f7ca6b158d3495c5cb46a1c730a6c11a32c76618 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 12:41:43 -0500 Subject: [PATCH 04/10] Clean up typos and unused imports --- .../edu/wisc/my/restproxy/Server.groovy | 1 - .../dao/RestProxyResponseErrorHandler.groovy | 10 +++---- .../service/RestProxyServiceImpl.groovy | 30 ++++++++----------- .../wisc/my/restproxy/ValidationResult.groovy | 2 +- .../service/RestProxyServiceImplTest.groovy | 2 +- 5 files changed, 19 insertions(+), 26 deletions(-) diff --git a/rest-proxy-boot/src/main/groovy/edu/wisc/my/restproxy/Server.groovy b/rest-proxy-boot/src/main/groovy/edu/wisc/my/restproxy/Server.groovy index 138ba5d..eb83af4 100644 --- a/rest-proxy-boot/src/main/groovy/edu/wisc/my/restproxy/Server.groovy +++ b/rest-proxy-boot/src/main/groovy/edu/wisc/my/restproxy/Server.groovy @@ -2,7 +2,6 @@ package edu.wisc.my.restproxy import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.autoconfigure.* @SpringBootApplication class Server { diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy index 953ac4b..6aee406 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy @@ -1,5 +1,5 @@ /** - * + * */ package edu.wisc.my.restproxy.dao; @@ -12,18 +12,18 @@ import org.springframework.web.client.ResponseErrorHandler; /** * {@link ResponseErrorHandler} implementation that does nothing and considers every * {@link ClientHttpRequest} a success. - * - * This class does nothing because RestProxy is responsible soley for relaying requests and + * + * This class does nothing because RestProxy is responsible solely for relaying requests and * responses. We don't care what's in the response, we just forward it on. It's up to the client to deal * with responses, whether they're successes or errors. - * + * * @author Collin Cudd */ public class RestProxyResponseErrorHandler implements ResponseErrorHandler { /* * (non-Javadoc) - * + * * @see * org.springframework.web.client.ResponseErrorHandler#handleError(org.springframework.http.client * .ClientHttpResponse) diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy index cf7c80b..03f305b 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy @@ -1,11 +1,5 @@ -/** - * - */ package edu.wisc.my.restproxy.service; -import java.io.IOException; -import java.io.InputStream; - import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; @@ -41,8 +35,8 @@ public class RestProxyServiceImpl implements RestProxyService { private static final Logger logger = LoggerFactory.getLogger(RestProxyServiceImpl.class); /** - * Visible for testing. - * + * Visible for testing. + * * @param env the env to set */ void setEnv(Environment env) { @@ -50,26 +44,26 @@ public class RestProxyServiceImpl implements RestProxyService { } /** * {@inheritDoc} - * + * * Inspects the {@link Environment} for necessary properties about the target API: *
    *
  • Resource root URI
  • *
  • Credentials
  • *
- * + * * Delegates to {@link RestProxyDao#proxyRequest(ProxyRequestContext)} - * + * * @see KeyUtils#getProxyHeaders(Environment, String, HttpServletRequest) */ @Override public ResponseEntity proxyRequest(final String resourceKey, final HttpServletRequest request) { - final String resourceRoot = env.getProperty(resourceKey + ".uri"); + final String resourceRoot = env.getProperty(resourceKey + ".uri"); if(StringUtils.isBlank(resourceRoot)) { logger.info("unknown resourceKey {}", resourceKey); return null; } StringBuilder uri = new StringBuilder(resourceRoot); - + String resourcePath = (String) request.getAttribute( HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE ); if(StringUtils.isNotBlank(resourcePath)) { if(resourcePath.startsWith("/"+resourceKey)) { @@ -80,7 +74,7 @@ public class RestProxyServiceImpl implements RestProxyService { } uri.append(resourcePath); } - + if(StringUtils.isNotBlank(request.getQueryString())) { uri.append("?"); uri.append(request.getQueryString()); @@ -97,7 +91,7 @@ public class RestProxyServiceImpl implements RestProxyService { .setUri(uri.toString()) .setUsername(username); - RequestBody requestBody = null; + RequestBody requestBody; try { InputStream inputStream = request.getInputStream(); final String contentType = request.getContentType(); @@ -105,18 +99,18 @@ public class RestProxyServiceImpl implements RestProxyService { if(inputStream != null && contentLength > 0) { requestBody = new RequestBody() .setBody(FileCopyUtils.copyToByteArray(inputStream)); - + if(StringUtils.isNotBlank(contentType)) { requestBody.setContentType(contentType); } - + context.setRequestBody(requestBody) .getHeaders().put(HttpHeaders.CONTENT_TYPE, contentType); } } catch (IOException e) { logger.debug("caught IOException attempting to check request inputStream, no requestBody provided", e); } - + logger.debug("proxying request {}", context); return proxyDao.proxyRequest(context); } diff --git a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy index d1f0c39..3ac28e0 100644 --- a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy +++ b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy @@ -4,7 +4,7 @@ package edu.wisc.my.restproxy; /** - * Just an example of an object that could be retruned by rest api. + * Just an example of an object that could be returned by rest api. * @author Collin Cudd */ public class ValidationResult { diff --git a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy index 8989c93..70d031c 100644 --- a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy +++ b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImplTest.groovy @@ -78,7 +78,7 @@ public class RestProxyServiceImplTest { /** * Test simulates a proxy request which fails with a http 400 error. * An error like this could be encountered if you were to post invalid data to a form. - * Test verifies the HttpStatus AND the body (which likely contins validation error message) are passed back to the client. + * Test verifies the HttpStatus AND the body (which likely contains validation error message) are passed back to the client. */ @Test public void proxyRequest_failsWithBadRequest() { From a90918343166f69b1d4e5aaa403bdafffb07ed28 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 13:02:09 -0500 Subject: [PATCH 05/10] Statically compile non-test classes and replace boilerplate methods with annotations --- .../edu/wisc/my/restproxy/KeyUtils.groovy | 22 +-- .../my/restproxy/ProxyRequestContext.groovy | 127 +++--------------- .../edu/wisc/my/restproxy/RequestBody.groovy | 56 ++------ .../config/RestProxyConfiguration.groovy | 10 +- .../wisc/my/restproxy/dao/RestProxyDao.groovy | 9 +- .../my/restproxy/dao/RestProxyDaoImpl.groovy | 19 ++- .../dao/RestProxyResponseErrorHandler.groovy | 9 +- .../restproxy/service/RestProxyService.groovy | 12 +- .../service/RestProxyServiceImpl.groovy | 5 +- .../web/ResourceProxyController.groovy | 18 +-- 10 files changed, 78 insertions(+), 209 deletions(-) diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy index c15d1bf..dbd661e 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/KeyUtils.groovy @@ -1,7 +1,6 @@ -package edu.wisc.my.restproxy; +package edu.wisc.my.restproxy -import java.util.HashMap; -import java.util.Map; +import groovy.transform.CompileStatic; import javax.servlet.http.HttpServletRequest; @@ -14,6 +13,7 @@ import org.springframework.util.PropertyPlaceholderHelper; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +@CompileStatic public final class KeyUtils { private static final String END_PLACEHOLDER = "}"; @@ -21,9 +21,9 @@ public final class KeyUtils { private KeyUtils() { } - + private static final Logger logger = LoggerFactory.getLogger(KeyUtils.class); - + public static Map getHeaders(Environment env, HttpServletRequest request, String key) { HashMap map = new HashMap(); String attributes = env.getProperty(key + ".attributes"); @@ -37,18 +37,18 @@ public final class KeyUtils { /** * Utility method for extracting the Proxy Headers for a request. - * + * * The configuration option '{key}.proxyHeaders' is used to specify a multi-valued list of HTTP headers to add to the - * outbound request to '{key}.uri'. - * + * outbound request to '{key}.uri'. + * * Example: *
    someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue
    
- * - * Implementers can specify either static values ('Some-Other-Header: staticvalue') or use placeholders to relay + * + * Implementers can specify either static values ('Some-Other-Header: staticvalue') or use placeholders to relay * {@link HttpServletRequest#getAttribute(String)} values ('On-Behalf-Of: {wiscedupvi}') - * + * * @param env * @param resourceKey * @param request diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy index 372ee8c..dc13b5e 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/ProxyRequestContext.groovy @@ -1,8 +1,9 @@ -package edu.wisc.my.restproxy; - -import groovy.transform.EqualsAndHashCode; -import groovy.transform.CompileStatic; +package edu.wisc.my.restproxy +import groovy.transform.Canonical; +import groovy.transform.CompileStatic +import groovy.transform.builder.Builder +import groovy.transform.builder.SimpleStrategy; import org.springframework.http.HttpMethod; import com.google.common.collect.ArrayListMultimap; @@ -13,18 +14,19 @@ import com.google.common.collect.Multimap; * * @author Nicholas Blair */ +@Builder(builderStrategy = SimpleStrategy) +@Canonical @CompileStatic -@EqualsAndHashCode public class ProxyRequestContext { - private final String resourceKey; - private HttpMethod httpMethod = HttpMethod.GET; - private String uri; - private String username; - private String password; - private Map attributes = new HashMap<>(); - private Multimap headers = ArrayListMultimap.create(); - private RequestBody requestBody; + final String resourceKey; + HttpMethod httpMethod = HttpMethod.GET; + String uri; + String username; + String password; + Map attributes = new HashMap<>(); + Multimap headers = ArrayListMultimap.create(); + RequestBody requestBody; /** * @@ -33,105 +35,6 @@ public class ProxyRequestContext { public ProxyRequestContext(String resourceKey) { this.resourceKey = resourceKey; } - /** - * @return the resourceKey - */ - public String getResourceKey() { - return resourceKey; - } - /** - * Defaults to {@link HttpMethod#GET} if not set explicitly. - * - * @return the httpMethod - */ - public HttpMethod getHttpMethod() { - return httpMethod; - } - /** - * @param httpMethod the httpMethod to set - */ - public ProxyRequestContext setHttpMethod(HttpMethod httpMethod) { - this.httpMethod = httpMethod; - return this; - } - /** - * @return the the full URI (including scheme, host, port, path) - */ - public String getUri() { - return uri; - } - /** - * @param uri the full URI (including scheme, host, port, path) - */ - public ProxyRequestContext setUri(String uri) { - this.uri = uri; - return this; - } - /** - * @return the username - */ - public String getUsername() { - return username; - } - /** - * @param username the username to set - */ - public ProxyRequestContext setUsername(String username) { - this.username = username; - return this; - } - /** - * @return the password - */ - public String getPassword() { - return password; - } - /** - * @param password the password to set - */ - public ProxyRequestContext setPassword(String password) { - this.password = password; - return this; - } - /** - * @return the attributes - */ - public Map getAttributes() { - return attributes; - } - /** - * @param attributes the attributes to set - */ - public ProxyRequestContext setAttributes(Map attributes) { - this.attributes = attributes; - return this; - } - /** - * @return the headers - */ - public Multimap getHeaders() { - return headers; - } - /** - * @param headers the headers to set - */ - public ProxyRequestContext setHeaders(Multimap headers) { - this.headers = headers; - return this; - } - /** - * @return the requestBody - */ - public RequestBody getRequestBody() { - return requestBody; - } - /** - * @param requestBody the requestBody to set - */ - public ProxyRequestContext setRequestBody(RequestBody requestBody) { - this.requestBody = requestBody; - return this; - } /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy index c7fdf7b..5b1c09d 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/RequestBody.groovy @@ -1,48 +1,16 @@ -/** - * - */ -package edu.wisc.my.restproxy; +package edu.wisc.my.restproxy -/** - * Bean to represent a request body. - * - * @author Nicholas Blair - */ +import groovy.transform.Canonical +import groovy.transform.CompileStatic +import groovy.transform.builder.Builder +import groovy.transform.builder.SimpleStrategy; + +@Builder(builderStrategy = SimpleStrategy) +@Canonical +@CompileStatic public class RequestBody { - private byte[] body; - private String contentType; - /** - * @return the body - */ - public byte[] getBody() { - return body; - } - /** - * @param body the body to set - */ - public RequestBody setBody(byte[] body) { - this.body = body; - return this; - } - /** - * @return the contentType - */ - public String getContentType() { - return contentType; - } - /** - * @param contentType the contentType to set - */ - public RequestBody setContentType(String contentType) { - this.contentType = contentType; - return this; - } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "RequestBody [body=" + body + ", contentType=" + contentType + "]"; - } + byte[] body; + String contentType; + } diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy index a0c7646..a4fcf7f 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/config/RestProxyConfiguration.groovy @@ -1,19 +1,21 @@ -package edu.wisc.my.restproxy.config; +package edu.wisc.my.restproxy.config +import groovy.transform.CompileStatic; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * {@link Configuration} activating necessary REST proxy services. - * + * * To use this class, simply {@link Import} it with the rest of your configuration. * It's strongly suggested that your configuration provide a {@link org.springframework.web.client.RestTemplate} bean, but not required. - * + * * @author Nicholas Blair */ -@Configuration +@CompileStatic @ComponentScan(value = ["edu.wisc.my.restproxy.dao", "edu.wisc.my.restproxy.service", "edu.wisc.my.restproxy.web"]) +@Configuration public class RestProxyConfiguration { } diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy index 7d56ff2..ead6971 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDao.groovy @@ -1,17 +1,16 @@ -/** - * - */ -package edu.wisc.my.restproxy.dao; +package edu.wisc.my.restproxy.dao +import groovy.transform.CompileStatic; import org.springframework.http.ResponseEntity; import edu.wisc.my.restproxy.ProxyRequestContext; /** * Data access interface for talking with a REST API. - * + * * @author Nicholas Blair */ +@CompileStatic public interface RestProxyDao { /** diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy index 5c87575..a0d80ee 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImpl.groovy @@ -1,6 +1,3 @@ -/** - * - */ package edu.wisc.my.restproxy.dao; import java.util.Map.Entry; @@ -21,20 +18,20 @@ import edu.wisc.my.restproxy.ProxyRequestContext; /** * {@link RestProxyDao} implementation backed by a {@link RestTemplate}. - * + * * A default {@link RestTemplate} instance is provided, but consumers are strongly recommended to * configure their own instance and inject. However, this class will always use * {@link RestProxyResponseErrorHandler} because it's the client's responsiblity to deal with * errors. - * + * * @author Nicholas Blair */ @Service public class RestProxyDaoImpl implements RestProxyDao, InitializingBean { - + @Autowired(required=false) private RestTemplate restTemplate = new RestTemplate(); - + /* (non-Javadoc) * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @@ -42,7 +39,7 @@ public class RestProxyDaoImpl implements RestProxyDao, InitializingBean { public void afterPropertiesSet() throws Exception { this.restTemplate.setErrorHandler(new RestProxyResponseErrorHandler()); }; - + private static final Logger logger = LoggerFactory.getLogger(RestProxyDaoImpl.class); /* (non-Javadoc) * @see edu.wisc.my.restproxy.dao.RestProxyDao#proxyRequest(edu.wisc.my.restproxy.ProxyRequestContext) @@ -59,13 +56,13 @@ public class RestProxyDaoImpl implements RestProxyDao, InitializingBean { String base64Creds = new String(base64CredsBytes); headers.add("Authorization", "Basic " + base64Creds); } - + for(Entry entry: context.getHeaders().entries()) { headers.add(entry.getKey(), entry.getValue()); } - + HttpEntity request = context.getRequestBody() == null ? new HttpEntity(headers) : new HttpEntity(context.getRequestBody().getBody(), headers); - ResponseEntity response = restTemplate.exchange(context.getUri(), + ResponseEntity response = restTemplate.exchange(context.getUri(), context.getHttpMethod(), request, Object.class, context.getAttributes()); logger.trace("completed request for {}, response= {}", context, response); return response; diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy index 6aee406..4a3513a 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/dao/RestProxyResponseErrorHandler.groovy @@ -1,10 +1,6 @@ -/** - * - */ -package edu.wisc.my.restproxy.dao; - -import java.io.IOException; +package edu.wisc.my.restproxy.dao +import groovy.transform.CompileStatic; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.web.client.ResponseErrorHandler; @@ -19,6 +15,7 @@ import org.springframework.web.client.ResponseErrorHandler; * * @author Collin Cudd */ +@CompileStatic public class RestProxyResponseErrorHandler implements ResponseErrorHandler { /* diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy index 5e26673..26b65cd 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyService.groovy @@ -1,7 +1,6 @@ -/** - * - */ -package edu.wisc.my.restproxy.service; +package edu.wisc.my.restproxy.service + +import groovy.transform.CompileStatic; import javax.servlet.http.HttpServletRequest; @@ -11,14 +10,15 @@ import edu.wisc.my.restproxy.ProxyRequestContext; /** * Service interface for proxying a REST API. - * + * * @see ProxyRequestContext * @author Nicholas Blair */ +@CompileStatic public interface RestProxyService { /** - * + * * @param resourceKey * @param request * @return the {@link ResponseEntity} returned from the REST API (may return null) diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy index 03f305b..c0d888f 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/service/RestProxyServiceImpl.groovy @@ -1,4 +1,6 @@ -package edu.wisc.my.restproxy.service; +package edu.wisc.my.restproxy.service + +import groovy.transform.CompileStatic; import javax.servlet.http.HttpServletRequest; @@ -25,6 +27,7 @@ import edu.wisc.my.restproxy.dao.RestProxyDao; * * @author Nicholas Blair */ +@CompileStatic @Service public class RestProxyServiceImpl implements RestProxyService { diff --git a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy index 3d7ea22..538aeb5 100644 --- a/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy +++ b/rest-proxy-core/src/main/groovy/edu/wisc/my/restproxy/web/ResourceProxyController.groovy @@ -1,7 +1,6 @@ -/** - * - */ -package edu.wisc.my.restproxy.web; +package edu.wisc.my.restproxy.web + +import groovy.transform.CompileStatic; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -20,9 +19,10 @@ import edu.wisc.my.restproxy.service.RestProxyService; /** * {@link RestController} for proxying other REST resources. - * + * * @author Nicholas Blair */ +@CompileStatic @Controller public class ResourceProxyController { @@ -42,22 +42,22 @@ public class ResourceProxyController { * Proxies the request and then calls {@link HttpServletResponse#setStatus(int)} with the * {@link HttpStatus} recieved. If the proxy response contains content it's simply returned here * as an {@link Object}. - * + * * @param request * @param response * @param key * @return the body of the proxy response or null. */ @RequestMapping("/{key}/**") - public @ResponseBody Object proxyResource(HttpServletRequest request, + public @ResponseBody Object proxyResource(HttpServletRequest request, HttpServletResponse response, @PathVariable String key) { - ResponseEntity responseEntity = proxyService.proxyRequest(key, request); + ResponseEntity responseEntity = proxyService.proxyRequest(key, request); if(responseEntity == null || responseEntity.getStatusCode() == null) { response.setStatus(HttpStatus.NOT_FOUND.value()); return null; } response.setStatus(responseEntity.getStatusCode().value()); - return responseEntity.hasBody() ? responseEntity.getBody() : null; + return responseEntity.hasBody() ? responseEntity.getBody() : null; } } From 4f5f580de7d3ed03b07d97420b7f8b311056cde3 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 13:25:11 -0500 Subject: [PATCH 06/10] Fix broken test (it was ambiguous which method signature to match) --- .../edu/wisc/my/restproxy/KeyUtilsTest.groovy | 5 +---- .../wisc/my/restproxy/ValidationResult.groovy | 5 +---- .../restproxy/dao/RestProxyDaoImplTest.groovy | 18 +++++++----------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy index d40d832..df6c69e 100644 --- a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy +++ b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/KeyUtilsTest.groovy @@ -1,6 +1,3 @@ -/** - * - */ package edu.wisc.my.restproxy; import static org.junit.Assert.assertEquals; @@ -17,7 +14,7 @@ import com.google.common.collect.Multimap; /** * Tests for {@link KeyUtils}. - * + * * @author Nicholas Blair */ public class KeyUtilsTest { diff --git a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy index 3ac28e0..4b08daf 100644 --- a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy +++ b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/ValidationResult.groovy @@ -1,6 +1,3 @@ -/** - * - */ package edu.wisc.my.restproxy; /** @@ -11,7 +8,7 @@ public class ValidationResult { boolean success; String message; - public ValidationResult(){} + /** * @param success * @param message diff --git a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy index d024317..7762358 100644 --- a/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy +++ b/rest-proxy-core/src/test/groovy/edu/wisc/my/restproxy/dao/RestProxyDaoImplTest.groovy @@ -1,10 +1,5 @@ -/** - * - */ package edu.wisc.my.restproxy.dao -import org.junit.Ignore; - import static org.junit.Assert.assertEquals; import org.apache.commons.codec.binary.Base64; @@ -24,7 +19,9 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.web.client.RestTemplate; import edu.wisc.my.restproxy.KeyUtils; -import edu.wisc.my.restproxy.ProxyRequestContext; +import edu.wisc.my.restproxy.ProxyRequestContext + +import static org.mockito.Mockito.when; /** * Tests for {@link RestProxyDaoImpl}. @@ -63,7 +60,6 @@ public class RestProxyDaoImplTest { /** * Control test for {@link RestProxyDaoImpl#proxyRequest(ProxyRequestContext)} */ - @Ignore @Test public void proxyRequest_control() { ProxyRequestContext context = getContext(); @@ -77,12 +73,12 @@ public class RestProxyDaoImplTest { headers.add("Authorization", "Basic " + base64Creds); HttpEntity expectedRequest = new HttpEntity(headers); - Mockito.when( + when( restTemplate.exchange( Matchers.eq(context.getUri()), Matchers.eq(context.getHttpMethod()), Matchers.eq(expectedRequest), - Matchers.eq(Object.class), + (Class)Matchers.anyObject(), Matchers.eq(context.getAttributes()) ) ).thenReturn(expectedResponse); @@ -92,9 +88,9 @@ public class RestProxyDaoImplTest { Matchers.eq(context.getUri()), Matchers.eq(context.getHttpMethod()), Matchers.eq(expectedRequest), - Matchers.eq(Object.class), + (Class)Matchers.anyObject(), Matchers.eq(context.getAttributes()) ); assertEquals(expectedResponse, proxyResponse); - } + } } From 4afd27adbb7acbc8f19d2e3c6445f97865c942fb Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 16:06:41 -0500 Subject: [PATCH 07/10] Add nexus deployment configuration --- build.gradle | 77 ++++++++++++++++++- .../resources/endpoint.properties.example | 6 +- rest-proxy-core/build.gradle | 14 ---- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 4f6f9e8..804479c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,13 @@ +buildscript { + repositories { jcenter() } + dependencies { classpath 'com.bmuschko:gradle-nexus-plugin:2.3.1' } +} + subprojects { group = 'edu.wisc.my.restproxy' version = '2.1.0-SNAPSHOT' - apply plugin: 'groovy' - repositories { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } maven { url "https://code.doit.wisc.edu/maven/content/repositories/public-releases/" } @@ -12,4 +15,74 @@ subprojects { maven { url "http://repo.maven.apache.org/maven2" } } + apply plugin: 'groovy' + apply plugin: 'com.bmuschko.nexus' + + // Nexus deploy configuration + nexus { + sign = true + repositoryUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' + snapshotRepositoryUrl = 'https://oss.sonatype.org/content/repositories/snapshots/' + } + + extraArchive { + javadoc = true + sources = true + tests = true + } + + modifyPom { + project { + url 'https://github.com/UW-Madison-DoIT/rest-proxy' + inceptionYear '2015' + scm { + url 'https://github.com/UW-Madison-DoIT/rest-proxy' + connection 'scm:https://github.com/UW-Madison-DoIT/rest-proxy.git' + developerConnection 'scm:git://github.com/UW-Madison-DoIT/rest-proxy.git' + } + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + developers { + developer { + name 'My UW Dev Team' + email 'my-admin@lists.wisc.edu' + url 'https://github.com/UW-Madison-DoIT' + organization 'UW-Madison-DoIT' + } + } + // The nexus plugin overlooks provided dependencies + // so we override this bit to make sure they get in + def generatedDeps = dependencies + dependencies { + generatedDeps.each { dep -> + dependency { + groupId dep.groupId + artifactId dep.artifactId + version dep.version + scope dep.scope + } + } + project.configurations.provided.allDependencies.each { dep -> + dependency { + groupId dep.group + artifactId dep.name + version dep.version + scope 'provided' + } + } + } + } + } + + // Define provided scope + configurations { + provided + compile.extendsFrom provided + } + } diff --git a/rest-proxy-boot/src/main/resources/endpoint.properties.example b/rest-proxy-boot/src/main/resources/endpoint.properties.example index 50f6370..e786a48 100644 --- a/rest-proxy-boot/src/main/resources/endpoint.properties.example +++ b/rest-proxy-boot/src/main/resources/endpoint.properties.example @@ -29,4 +29,8 @@ uwmadisonreddit.attributes= someservice.uri=http://somewhere.wisc.edu/foo someservice.username=user someservice.password=pass -someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue \ No newline at end of file +someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue + +#todos placeholder example +todos.uri=http://jsonplaceholder.typicode.com/todos + diff --git a/rest-proxy-core/build.gradle b/rest-proxy-core/build.gradle index 26aea6b..7028f89 100644 --- a/rest-proxy-core/build.gradle +++ b/rest-proxy-core/build.gradle @@ -3,20 +3,6 @@ description = "A simple server-side REST proxy library" sourceCompatibility = 1.7 targetCompatibility = 1.7 -configurations { - provided -} - -sourceSets { - main { - compileClasspath += configurations.provided - } - test { - compileClasspath += configurations.provided - runtimeClasspath += configurations.provided - } -} - dependencies { compile 'org.codehaus.groovy:groovy-all:2.4.4' compile 'org.apache.commons:commons-lang3:3.3.2' From e860c52885a745cfc0886937ab5eee84f6a264c8 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Thu, 17 Sep 2015 17:19:08 -0500 Subject: [PATCH 08/10] Rename config to application.properties (this is what spring boot uses by convention) --- rest-proxy-boot/src/main/resources/.gitignore | 2 +- ...dpoint.properties.example => application.properties.example} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename rest-proxy-boot/src/main/resources/{endpoint.properties.example => application.properties.example} (100%) diff --git a/rest-proxy-boot/src/main/resources/.gitignore b/rest-proxy-boot/src/main/resources/.gitignore index f78ec10..bbd5731 100644 --- a/rest-proxy-boot/src/main/resources/.gitignore +++ b/rest-proxy-boot/src/main/resources/.gitignore @@ -1,2 +1,2 @@ -endpoint.properties +application.properties diff --git a/rest-proxy-boot/src/main/resources/endpoint.properties.example b/rest-proxy-boot/src/main/resources/application.properties.example similarity index 100% rename from rest-proxy-boot/src/main/resources/endpoint.properties.example rename to rest-proxy-boot/src/main/resources/application.properties.example From ca5a891b85158914abaf157040808ab0179d7f72 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Fri, 18 Sep 2015 13:01:17 -0500 Subject: [PATCH 09/10] Update readme with config and release instructions --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9d67fcb..0e5c248 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,20 @@ This is an important component with a couple of use cases. ### Run Standalone Microservice -#### Prerequisites - * [Grails 3.0.x](https://grails.org/) - #### Running +* Supply endpoint configuration - you can copy application.properties.example to get started, or add a command-line flag, e.g. `--todos.uri=http://jsonplaceholder.typicode.com/todos` * Run `gradle bootRun` to start the server -* [Verify it works](localhost:8080/todos.json) +* [Verify in your browser](localhost:8080/todos) __OR__ * Run `gradle build` to build a standalone jar * Start the server by running `java -jar rest-proxy-boot/build/rest-proxy-boot-.jar` +### Releasing to Artifact Repository + +#### Manually +Only authorized users can perform the release. Contact one of the core contributors if you think you should have access. + +* Run `gradle uploadArchives` and provide Sonatype credentials when prompted (if they are not already supplied in ~/.gradle/gradle.properties). This will build both projects and generate pomfiles, javadoc, test, and sources artifacts, and then upload them to the Sonatype Nexus repository. + From c1472eef0656c401ec2ffa95f1137a0ef4a99942 Mon Sep 17 00:00:00 2001 From: Paul Erickson Date: Mon, 21 Sep 2015 13:25:19 -0500 Subject: [PATCH 10/10] Fix indentation --- .../src/main/resources/application.properties.example | 2 +- .../src/main/resources/endpoint.properties.example | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rest-proxy-boot/src/main/resources/application.properties.example b/rest-proxy-boot/src/main/resources/application.properties.example index e786a48..72a5263 100644 --- a/rest-proxy-boot/src/main/resources/application.properties.example +++ b/rest-proxy-boot/src/main/resources/application.properties.example @@ -2,7 +2,7 @@ #key.username : the username to login to service (basic auth) * #key.password : the password for the service (basic auth) * #key.attributes : the csv of attributes -#key.proxyHeaders : a comma separated list of headers to add output. Can put placeholders for values to get local request attributes. +#key.proxyHeaders : a comma separated list of headers to add output. Can put placeholders for values to get local request attributes. #key.cache : how long to cache the information for that URI (with variables replaced) - not implemented yet # # * : not required diff --git a/rest-proxy-core/src/main/resources/endpoint.properties.example b/rest-proxy-core/src/main/resources/endpoint.properties.example index 50f6370..6768697 100644 --- a/rest-proxy-core/src/main/resources/endpoint.properties.example +++ b/rest-proxy-core/src/main/resources/endpoint.properties.example @@ -2,7 +2,7 @@ #key.username : the username to login to service (basic auth) * #key.password : the password for the service (basic auth) * #key.attributes : the csv of attributes -#key.proxyHeaders : a comma separated list of headers to add output. Can put placeholders for values to get local request attributes. +#key.proxyHeaders : a comma separated list of headers to add output. Can put placeholders for values to get local request attributes. #key.cache : how long to cache the information for that URI (with variables replaced) - not implemented yet # # * : not required @@ -29,4 +29,4 @@ uwmadisonreddit.attributes= someservice.uri=http://somewhere.wisc.edu/foo someservice.username=user someservice.password=pass -someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue \ No newline at end of file +someservice.proxyHeaders=On-Behalf-Of: {wiscedupvi},Some-Other-Header: staticvalue