From f7bd84e22fccaf0a8ececf804cc6a3d80b4b036f Mon Sep 17 00:00:00 2001 From: Vigil Bose Date: Wed, 16 Nov 2011 15:52:37 -0500 Subject: [PATCH] INTSAMPLES-36 - Adding rest-http sample to demonstrate the usage of Spring Integration's new HTTP Path facility usage * The JIRA referenced for this sample is https://jira.springsource.org/browse/INTSAMPLES-36 --- .gitignore | 2 +- README.md | 3 + intermediate/rest-http/pom.xml | 188 ++++++++++++++++++ intermediate/rest-http/readme.md | 44 ++++ .../samples/rest/domain/Employee.java | 85 ++++++++ .../samples/rest/domain/EmployeeList.java | 88 ++++++++ .../samples/rest/domain/jaxb.index | 2 + .../rest/json/JaxbJacksonObjectMapper.java | 48 +++++ .../view/ExtendedMappingJacksonJsonView.java | 48 +++++ .../rest/service/EmployeeSearchService.java | 104 ++++++++++ .../applicationContext-http-int.xml | 76 +++++++ .../src/main/resources/log4j.properties | 24 +++ .../src/main/resources/users.properties | 2 + .../src/main/webapp/META-INF/MANIFEST.MF | 3 + .../webapp/WEB-INF/config/security-config.xml | 50 +++++ .../WEB-INF/config/web-application-config.xml | 16 ++ .../rest-http/src/main/webapp/WEB-INF/web.xml | 109 ++++++++++ .../samples/rest/RestHttpClientTest.java | 146 ++++++++++++++ .../integration/http-outbound-config.xml | 35 ++++ .../src/test/resources/log4j.properties | 15 ++ 20 files changed, 1087 insertions(+), 1 deletion(-) create mode 100644 intermediate/rest-http/pom.xml create mode 100644 intermediate/rest-http/readme.md create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/Employee.java create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/EmployeeList.java create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/jaxb.index create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/JaxbJacksonObjectMapper.java create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/view/ExtendedMappingJacksonJsonView.java create mode 100644 intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/service/EmployeeSearchService.java create mode 100644 intermediate/rest-http/src/main/resources/META-INF/spring/integration/applicationContext-http-int.xml create mode 100644 intermediate/rest-http/src/main/resources/log4j.properties create mode 100644 intermediate/rest-http/src/main/resources/users.properties create mode 100644 intermediate/rest-http/src/main/webapp/META-INF/MANIFEST.MF create mode 100644 intermediate/rest-http/src/main/webapp/WEB-INF/config/security-config.xml create mode 100644 intermediate/rest-http/src/main/webapp/WEB-INF/config/web-application-config.xml create mode 100644 intermediate/rest-http/src/main/webapp/WEB-INF/web.xml create mode 100644 intermediate/rest-http/src/test/java/org/springframework/integration/samples/rest/RestHttpClientTest.java create mode 100644 intermediate/rest-http/src/test/resources/META-INF/spring/integration/http-outbound-config.xml create mode 100644 intermediate/rest-http/src/test/resources/log4j.properties diff --git a/.gitignore b/.gitignore index e06881e9..48007b90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ application.log application.log* target/ -.settings/ log.roo .project .classpath @@ -13,3 +12,4 @@ log.roo derby.log .idea activemq-data +.settings/ diff --git a/README.md b/README.md index 985ad8ec..1777d41e 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,9 @@ This category targets developers who are already more familiar with the Spring I * **tcp-client-server-multiplex** - Demonstrates the use of *Collaborating Channel Adapters* * **stored-procedures-derby** Provides an example of the stored procedure Outbound Gateway using *[Apache Derby](http://db.apache.org/derby/)* * **stored-procedures-oracle** Provides an example of the stored procedure Outbound Gateway using *ORACLE XE* +* **rest-http** - This sample demonstrates how to send an HTTP request to a Spring Integration's HTTP service while utilizing Spring Integration's new HTTP Path usage. This sample also uses Spring Security for HTTP Basic authentication. With HTTP Path facility, the client program can send requests with URL Variables. +* **stored-procedures-derby** Provides an example of the stored procedure Outbound Gateway using *[Apache Derby](http://db.apache.org/derby/)* +* **stored-procedures-oracle** Provides an example of the stored procedure Outbound Gateway using *ORACLE XE* ## Advanced diff --git a/intermediate/rest-http/pom.xml b/intermediate/rest-http/pom.xml new file mode 100644 index 00000000..fa8427eb --- /dev/null +++ b/intermediate/rest-http/pom.xml @@ -0,0 +1,188 @@ + + 4.0.0 + org.springframework.integration.samples + rest-http + 2.1.0.BUILD-SNAPSHOT + war + Spring Integration Rest HTTP Path Usage Demo + Spring Integration Rest HTTP Path Usage Demo + + 2.1.0.RELEASE + 3.1.0.RELEASE + 3.1.0.RELEASE + 1.2 + 1.3.2 + 1.2.16 + 2.5 + 4.8.1 + 1.7 + 2.2 + + + + org.springframework.integration + spring-integration-http + ${spring.integration.version} + + + org.codehaus.jackson + jackson-mapper-asl + 1.8.0 + compile + + + org.springframework.integration + spring-integration-core + ${spring.integration.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + org.springframework + spring-oxm + ${spring.version} + + + org.springframework + spring-tx + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework.security + spring-security-core + compile + ${spring.security.version} + + + org.springframework.security + spring-security-config + compile + ${spring.security.version} + + + org.springframework.security + spring-security-web + compile + ${spring.security.version} + + + log4j + log4j + ${log4j.version} + + + org.jasypt + jasypt + ${jasypt.version} + runtime + + + cglib + cglib + ${cglib.version} + runtime + + + + javax.servlet + servlet-api + ${javax.servlet.version} + provided + + + org.springframework + spring-test + ${spring.version} + test + + + org.springframework + spring-tx + + + + + junit + junit + ${junit.version} + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + -Xlint:all + true + false + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.6 + + + clean + + + Copying jaxb.index to classes folder + + + + + + + + + + clean + + run + + + + + + + + + repository.springframework.maven.release + Spring Framework Maven Release Repository + http://maven.springframework.org/release + + + repository.springframework.maven.milestone + Spring Framework Maven Milestone Repository + http://maven.springframework.org/milestone + + + repository.springframework.maven.snapshot + Spring Framework Maven Snapshot Repository + http://maven.springframework.org/snapshot + + + + \ No newline at end of file diff --git a/intermediate/rest-http/readme.md b/intermediate/rest-http/readme.md new file mode 100644 index 00000000..8071cbd9 --- /dev/null +++ b/intermediate/rest-http/readme.md @@ -0,0 +1,44 @@ +# Introduction + +This sample demonstrates how you can send an HTTP request to a Spring Integration's HTTP service while utilizing Spring Integration's new HTTP Path usage; +This sample also uses Spring Security for HTTP Basic authentication. With HTTP Path facility, the client program can send requests with URL Variables. + +It consists of two parts - Client and Server. + +The following client program can be used to test the HTTP Path usage. + +1. RestHttpClientTest. It uses Spring's RestTemplate to assemble and send HTTP request + +Server is Spring Integration's HTTP endpoint configuration. + +To run this sample + +1. deploy project + - If you are using STS and project is imported as Eclipse project in your workspace you can just execute 'Run on Server' + - You can also run 'mvn clean install' and generate the WAR file that you can deploy the conventional way +2. run the simple JUNIT Test: org.springframework.integration.samples.rest.RestHttpClientTest + You may change the URI Variable value in the test to see different results. + +For example, when you give 0 as the URL Variable's value in the test, then you should see the following output from the server: + + 14:01:34,337 INFO main rest.RestHttpClientTest:95 - The employee list size :2 + 14:01:34,353 INFO main rest.RestHttpClientTest:101 - + + + 1 + John + Doe + + + 2 + Jane + Doe + + 0 + Success + + + 14:01:34,556 INFO main rest.RestHttpClientTest:121 - Return Status :[0] + 14:01:34,556 INFO main rest.RestHttpClientTest:122 - Return Status Message :[Success] + {"employee":[{"employeeId":1,"fname":"John","lname":"Doe"},{"employeeId":2,"fname":"Jane","lname":"Doe"}],"returnStatus":"0","returnStatusMsg":"Success"} + diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/Employee.java b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/Employee.java new file mode 100644 index 00000000..6280fda9 --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/Employee.java @@ -0,0 +1,85 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest.domain; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * Employee.java: Employee Domain class + * @author Vigil Bose + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "employeeId", + "fname", + "lname" +}) +@XmlRootElement(name = "Customer") +public class Employee { + + private Integer employeeId; + private String fname; + private String lname; + + public Employee() {} + + public Employee(Integer employeeId, String fname, String lname) { + this.employeeId = employeeId; + this.fname = fname; + this.lname = lname; + } + /** + * @return the employeeId + */ + public Integer getEmployeeId() { + return employeeId; + } + /** + * @param employeeId the employeeId to set + */ + public void setEmployeeId(Integer employeeId) { + this.employeeId = employeeId; + } + /** + * @return the fname + */ + public String getFname() { + return fname; + } + /** + * @param fname the fname to set + */ + public void setFname(String fname) { + this.fname = fname; + } + /** + * @return the lname + */ + public String getLname() { + return lname; + } + /** + * @param lname the lname to set + */ + public void setLname(String lname) { + this.lname = lname; + } +} + + diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/EmployeeList.java b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/EmployeeList.java new file mode 100644 index 00000000..6fb0e39a --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/EmployeeList.java @@ -0,0 +1,88 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest.domain; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + +/** + * EmployeeList.java: EmployeeList Domain class + * @author Vigil Bose + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "employee", + "returnStatus", + "returnStatusMsg" +}) +@XmlRootElement(name = "EmployeeList") +public class EmployeeList { + + @XmlElement(name = "Employee", required = true) + private List employee; + + @XmlElement(name = "returnStatus", required = true) + private String returnStatus; + + @XmlElement(name = "returnStatusMsg", required = true) + private String returnStatusMsg; + + /** + * @return the employee + */ + public List getEmployee() { + if (employee == null){ + employee = new ArrayList(); + } + return employee; + } + + /** + * @return the returnStatus + */ + public String getReturnStatus() { + return returnStatus; + } + + /** + * @param returnStatus the returnStatus to set + */ + public void setReturnStatus(String returnStatus) { + this.returnStatus = returnStatus; + } + + /** + * @return the returnStatusMsg + */ + public String getReturnStatusMsg() { + return returnStatusMsg; + } + + /** + * @param returnStatusMsg the returnStatusMsg to set + */ + public void setReturnStatusMsg(String returnStatusMsg) { + this.returnStatusMsg = returnStatusMsg; + } +} + + diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/jaxb.index b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/jaxb.index new file mode 100644 index 00000000..465e4f14 --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/domain/jaxb.index @@ -0,0 +1,2 @@ +Employee +EmployeeList \ No newline at end of file diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/JaxbJacksonObjectMapper.java b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/JaxbJacksonObjectMapper.java new file mode 100644 index 00000000..74bfe3b9 --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/JaxbJacksonObjectMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest.json; + +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; + +/** + * JaxbJacksonObjectMapper.java: This is the custom JAXB JSON ObjectMapper + *

+ * NOTE: The source code is provided by Gunnar Hillert in his blog posted at + * http://hillert.blogspot.com/2011/01/marshal-json-data-using-jackson-in.html. + * I modified a little bit to use the latest {@link DeserializationConfig} API + * instead of deprecated ones. + *

* + * @author Vigil Bose + */ +public class JaxbJacksonObjectMapper extends ObjectMapper { + + /** + * Annotation introspector to use for serialization process + * is configured separately for serialization and deserialization purposes + */ + public JaxbJacksonObjectMapper() { + final AnnotationIntrospector introspector + = new JacksonAnnotationIntrospector(); + super.getDeserializationConfig() + .withAnnotationIntrospector(introspector); + super.getSerializationConfig() + .withAnnotationIntrospector(introspector); + + } +} diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/view/ExtendedMappingJacksonJsonView.java b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/view/ExtendedMappingJacksonJsonView.java new file mode 100644 index 00000000..6c817c70 --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/json/view/ExtendedMappingJacksonJsonView.java @@ -0,0 +1,48 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest.json.view; + +import java.util.Map; + +import org.springframework.web.servlet.view.json.MappingJacksonJsonView; + +/** + * ExtendedMappingJacksonJsonView.java: This class extends the Spring's MappingJacksonJsonView + *

+ * Note: The source code for this class is taken from the forum posted by AhungerArtist + * at http://forum.springsource.org/archive/index.php/t-84006.html + *

+ * @author Vigil Bose + */ +public class ExtendedMappingJacksonJsonView extends MappingJacksonJsonView { + + @SuppressWarnings({"rawtypes" }) + @Override + protected Object filterModel(Map model){ + Object result = super.filterModel(model); + if (!(result instanceof Map)){ + return result; + } + + Map map = (Map) result; + if (map.size() == 1){ + return map.values().toArray()[0]; + } + return map; + } +} + + diff --git a/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/service/EmployeeSearchService.java b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/service/EmployeeSearchService.java new file mode 100644 index 00000000..88b42ead --- /dev/null +++ b/intermediate/rest-http/src/main/java/org/springframework/integration/samples/rest/service/EmployeeSearchService.java @@ -0,0 +1,104 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest.service; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.springframework.integration.Message; +import org.springframework.integration.MessageHeaders; +import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.samples.rest.domain.Employee; +import org.springframework.integration.samples.rest.domain.EmployeeList; +import org.springframework.security.access.annotation.Secured; +import org.springframework.stereotype.Service; + +/** + * EmployeeSearchService.java: This is the default employee search service + * @author Vigil Bose + */ +@Service("employeeSearchService") +public class EmployeeSearchService { + + private static Logger logger = Logger.getLogger(EmployeeSearchService.class); + /** + * The API getEmployee() looks up the mapped in coming message header's id param + * and fills the return object with the appropriate employee details. The return + * object is wrapped in Spring Integration Message with response headers filled in. + * This example shows the usage of URL path variables and how the service act on + * those variables. + * @param inMessage + * @return an instance of {@link Message} that wraps {@link EmployeeList} + */ + @Secured("ROLE_REST_HTTP_USER") + public Message getEmployee(Message inMessage){ + + EmployeeList employeeList = new EmployeeList(); + Map responseHeaderMap = new HashMap(); + + try{ + MessageHeaders headers = inMessage.getHeaders(); + String id = (String)headers.get("employeeId"); + boolean isFound; + if (id.equals("1")){ + employeeList.getEmployee().add(new Employee(1, "John", "Doe")); + isFound = true; + }else if (id.equals("2")){ + employeeList.getEmployee().add(new Employee(2, "Jane", "Doe")); + isFound = true; + }else if (id.equals("0")){ + employeeList.getEmployee().add(new Employee(1, "John", "Doe")); + employeeList.getEmployee().add(new Employee(2, "Jane", "Doe")); + isFound = true; + }else{ + isFound = false; + } + if (isFound){ + setReturnStatusAndMessage("0", "Success", employeeList, responseHeaderMap); + }else{ + setReturnStatusAndMessage("2", "Employee Not Found", employeeList, responseHeaderMap); + } + + }catch (Throwable e){ + setReturnStatusAndMessage("1", "System Error", employeeList, responseHeaderMap); + logger.error("System error occured :"+e); + } + Message message = new GenericMessage(employeeList, responseHeaderMap); + return message; + } + + /** + * The API setReturnStatusAndMessage() sets the return status and return message + * in the return message payload and its header. + * @param status + * @param message + * @param employeeList + * @param responseHeaderMap + */ + private void setReturnStatusAndMessage(String status, + String message, + EmployeeList employeeList, + Map responseHeaderMap){ + + employeeList.setReturnStatus(status); + employeeList.setReturnStatusMsg(message); + responseHeaderMap.put("Return-Status", status); + responseHeaderMap.put("Return-Status-Msg", message); + } +} + + diff --git a/intermediate/rest-http/src/main/resources/META-INF/spring/integration/applicationContext-http-int.xml b/intermediate/rest-http/src/main/resources/META-INF/spring/integration/applicationContext-http-int.xml new file mode 100644 index 00000000..fee9fa23 --- /dev/null +++ b/intermediate/rest-http/src/main/resources/META-INF/spring/integration/applicationContext-http-int.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/intermediate/rest-http/src/main/resources/log4j.properties b/intermediate/rest-http/src/main/resources/log4j.properties new file mode 100644 index 00000000..d25b1ca9 --- /dev/null +++ b/intermediate/rest-http/src/main/resources/log4j.properties @@ -0,0 +1,24 @@ +# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml! +# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J. +log4j.rootLogger=INFO, stdout, logfile + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n + +log4j.appender.logfile=org.apache.log4j.RollingFileAppender +log4j.appender.logfile.File=${rest-http.root}/WEB-INF/logs/rest-http.log +log4j.appender.logfile.MaxFileSize=25MB +# Keep three backup files. +log4j.appender.logfile.MaxBackupIndex=10 +# Pattern to output: date priority [category] - message +log4j.appender.logfile.layout=org.apache.log4j.PatternLayout +log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n + +log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE +log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG +log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG + +# the httpclient.wire category provides a trace of all of +# httpclient's network communication +log4j.category.httpclient.wire=INFO \ No newline at end of file diff --git a/intermediate/rest-http/src/main/resources/users.properties b/intermediate/rest-http/src/main/resources/users.properties new file mode 100644 index 00000000..1e5bfb58 --- /dev/null +++ b/intermediate/rest-http/src/main/resources/users.properties @@ -0,0 +1,2 @@ +#REST HTTP User +SPRING=gI/OZ3yejUtSxsF9XySg5TfFJFo=,ROLE_REST_HTTP_USER,enabled \ No newline at end of file diff --git a/intermediate/rest-http/src/main/webapp/META-INF/MANIFEST.MF b/intermediate/rest-http/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 00000000..254272e1 --- /dev/null +++ b/intermediate/rest-http/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/intermediate/rest-http/src/main/webapp/WEB-INF/config/security-config.xml b/intermediate/rest-http/src/main/webapp/WEB-INF/config/security-config.xml new file mode 100644 index 00000000..1109cc0b --- /dev/null +++ b/intermediate/rest-http/src/main/webapp/WEB-INF/config/security-config.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/intermediate/rest-http/src/main/webapp/WEB-INF/config/web-application-config.xml b/intermediate/rest-http/src/main/webapp/WEB-INF/config/web-application-config.xml new file mode 100644 index 00000000..f9f13360 --- /dev/null +++ b/intermediate/rest-http/src/main/webapp/WEB-INF/config/web-application-config.xml @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/intermediate/rest-http/src/main/webapp/WEB-INF/web.xml b/intermediate/rest-http/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..64cfe746 --- /dev/null +++ b/intermediate/rest-http/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,109 @@ + + + + Spring Integration Rest HTTP Path Usage Demo + + + contextConfigLocation + + + /WEB-INF/config/web-application-config.xml + + + + + + webAppRootKey + rest-http.root + + + + + log4jConfigLocation + /WEB-INF/classes/log4j.properties + + + + + + + org.springframework.web.util.Log4jConfigListener + + + + + org.springframework.web.context.ContextLoaderListener + + + + charEncodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + forceEncoding + true + + + + charEncodingFilter + /* + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + springSecurityFilterChain + /* + + + + Spring Integration Rest HTTP Path Usage + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + + + 2 + + + Spring Integration Rest HTTP Path Usage + /* + + + \ No newline at end of file diff --git a/intermediate/rest-http/src/test/java/org/springframework/integration/samples/rest/RestHttpClientTest.java b/intermediate/rest-http/src/test/java/org/springframework/integration/samples/rest/RestHttpClientTest.java new file mode 100644 index 00000000..add66c27 --- /dev/null +++ b/intermediate/rest-http/src/test/java/org/springframework/integration/samples/rest/RestHttpClientTest.java @@ -0,0 +1,146 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.rest; + +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.transform.stream.StreamResult; + +import org.apache.log4j.Logger; +import org.codehaus.jackson.map.ObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.integration.samples.rest.domain.EmployeeList; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import org.springframework.security.crypto.codec.Base64; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.client.HttpMessageConverterExtractor; +import org.springframework.web.client.RequestCallback; +import org.springframework.web.client.RestTemplate; + +/** + * RestHttpClientTest.java: Functional Test to test the REST HTTP Path usage. This test requires + * rest-http application running in HTTP environment. + * @author Vigil Bose + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations={"classpath*:META-INF/spring/integration/http-outbound-config.xml"}) +public class RestHttpClientTest { + + @Autowired + private RestTemplate restTemplate; + private HttpMessageConverterExtractor responseExtractor; + private static Logger logger = Logger.getLogger(RestHttpClientTest.class); + @Autowired + private Jaxb2Marshaller marshaller; + @Autowired + private ObjectMapper jaxbJacksonObjectMapper; + + @Before + public void setUp() { + responseExtractor = new HttpMessageConverterExtractor(EmployeeList.class, restTemplate.getMessageConverters()); + + Map properties = new HashMap(); + properties.put(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); + properties.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.setMarshallerProperties(properties); + } + /** + * + * @throws Exception + */ + @Test + public void testGetEmployeeAsXml() throws Exception{ + + Map employeeSearchMap = getEmployeeSearchMap("0"); + + final String fullUrl = "http://localhost:8080/rest-http/services/employee/{id}/search"; + + EmployeeList employeeList = restTemplate.execute(fullUrl, HttpMethod.GET, + new RequestCallback() { + @Override + public void doWithRequest(ClientHttpRequest request) throws IOException { + HttpHeaders headers = getHttpHeadersWithUserCredentials(request); + headers.add("Accept", "application/xml"); + } + }, responseExtractor, employeeSearchMap); + + logger.info("The employee list size :"+employeeList.getEmployee().size()); + + StringWriter sw = new StringWriter(); + StreamResult sr = new StreamResult(sw); + + marshaller.marshal(employeeList, sr); + logger.info(sr.getWriter().toString()); + assertTrue(employeeList.getEmployee().size() > 0); + } + + private Map getEmployeeSearchMap(String id) { + Map employeeSearchMap = new HashMap(); + employeeSearchMap.put("id", id); + return employeeSearchMap; + } + + @Test + public void testGetEmployeeAsJson() throws Exception{ + Map employeeSearchMap = getEmployeeSearchMap("0"); + + final String fullUrl = "http://localhost:8080/rest-http/services/employee/{id}/search?format=json"; + HttpHeaders headers = getHttpHeadersWithUserCredentials(new HttpHeaders()); + headers.add("Accept", "application/json"); + HttpEntity request = new HttpEntity(headers); + + ResponseEntity httpResponse = restTemplate.exchange(fullUrl, HttpMethod.GET, request, EmployeeList.class, employeeSearchMap); + logger.info("Return Status :"+httpResponse.getHeaders().get("X-Return-Status")); + logger.info("Return Status Message :"+httpResponse.getHeaders().get("X-Return-Status-Msg")); + assertTrue(httpResponse.getStatusCode().equals(HttpStatus.OK)); + jaxbJacksonObjectMapper.writeValue(System.out, httpResponse.getBody()); + } + + private HttpHeaders getHttpHeadersWithUserCredentials(ClientHttpRequest request){ + return (getHttpHeadersWithUserCredentials(request.getHeaders())); + } + + private HttpHeaders getHttpHeadersWithUserCredentials(HttpHeaders headers){ + + String username = "SPRING"; + String password = "spring"; + + String combinedUsernamePassword = username+":"+password; + byte[] base64Token = Base64.encode(combinedUsernamePassword.getBytes()); + String base64EncodedToken = new String (base64Token); + //adding Authorization header for HTTP Basic authentication + headers.add("Authorization","Basic "+base64EncodedToken); + + return headers; + } +} + + diff --git a/intermediate/rest-http/src/test/resources/META-INF/spring/integration/http-outbound-config.xml b/intermediate/rest-http/src/test/resources/META-INF/spring/integration/http-outbound-config.xml new file mode 100644 index 00000000..7eb39a9c --- /dev/null +++ b/intermediate/rest-http/src/test/resources/META-INF/spring/integration/http-outbound-config.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/intermediate/rest-http/src/test/resources/log4j.properties b/intermediate/rest-http/src/test/resources/log4j.properties new file mode 100644 index 00000000..746f3016 --- /dev/null +++ b/intermediate/rest-http/src/test/resources/log4j.properties @@ -0,0 +1,15 @@ +log4j.rootCategory=INFO, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n + +log4j.logger.org.springframework.ws.client.MessageTracing.sent=TRACE +log4j.logger.org.springframework.ws.client.MessageTracing.received=DEBUG +log4j.logger.org.springframework.ws.server.MessageTracing=DEBUG + +# the httpclient.wire category provides a trace of all of +# httpclient's network communication +log4j.category.httpclient.wire=INFO +log4j.category.org.springframework=WARN +log4j.category.org.springframework.integration=INFO \ No newline at end of file