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
This commit is contained in:
committed by
Gunnar Hillert
parent
c97fb87ae8
commit
f7bd84e22f
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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> employee;
|
||||
|
||||
@XmlElement(name = "returnStatus", required = true)
|
||||
private String returnStatus;
|
||||
|
||||
@XmlElement(name = "returnStatusMsg", required = true)
|
||||
private String returnStatusMsg;
|
||||
|
||||
/**
|
||||
* @return the employee
|
||||
*/
|
||||
public List<Employee> getEmployee() {
|
||||
if (employee == null){
|
||||
employee = new ArrayList<Employee>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Employee
|
||||
EmployeeList
|
||||
@@ -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
|
||||
* <p>
|
||||
* 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.
|
||||
* <p> *
|
||||
* @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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
* @author Vigil Bose
|
||||
*/
|
||||
public class ExtendedMappingJacksonJsonView extends MappingJacksonJsonView {
|
||||
|
||||
@SuppressWarnings({"rawtypes" })
|
||||
@Override
|
||||
protected Object filterModel(Map<String, Object> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <code>getEmployee()</code> 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 <code>{@link Message}</code> that wraps <code>{@link EmployeeList}</code>
|
||||
*/
|
||||
@Secured("ROLE_REST_HTTP_USER")
|
||||
public Message<EmployeeList> getEmployee(Message<?> inMessage){
|
||||
|
||||
EmployeeList employeeList = new EmployeeList();
|
||||
Map<String, Object> responseHeaderMap = new HashMap<String, Object>();
|
||||
|
||||
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<EmployeeList> message = new GenericMessage<EmployeeList>(employeeList, responseHeaderMap);
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* The API <code>setReturnStatusAndMessage()</code> 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<String, Object> responseHeaderMap){
|
||||
|
||||
employeeList.setReturnStatus(status);
|
||||
employeeList.setReturnStatusMsg(message);
|
||||
responseHeaderMap.put("Return-Status", status);
|
||||
responseHeaderMap.put("Return-Status-Msg", message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:oxm="http://www.springframework.org/schema/oxm"
|
||||
xmlns:int-http="http://www.springframework.org/schema/integration/http">
|
||||
|
||||
<int:annotation-config/>
|
||||
|
||||
<!-- handler mapping implementation that is aware of inbound Spring Integration
|
||||
http inbound gateway's and inbound adapter's with "path" attributes -->
|
||||
<bean class="org.springframework.integration.http.inbound.UriPathHandlerMapping"/>
|
||||
|
||||
<!-- Inbound/Outbound Channels -->
|
||||
<int:channel id="employeeSearchRequest" />
|
||||
<int:channel id="employeeSearchResponse" />
|
||||
|
||||
|
||||
<int-http:inbound-gateway id="inboundEmployeeSearchRequestGateway"
|
||||
supported-methods="GET, POST"
|
||||
request-channel="employeeSearchRequest"
|
||||
reply-channel="employeeSearchResponse"
|
||||
mapped-response-headers="Return-Status, Return-Status-Msg, HTTP_RESPONSE_HEADERS"
|
||||
view-name="/employee"
|
||||
path="/services/employee/{id}/search"
|
||||
reply-timeout="50000">
|
||||
|
||||
<int-http:header name="employeeId" expression="#pathVariables.id"/>
|
||||
|
||||
</int-http:inbound-gateway>
|
||||
|
||||
|
||||
<!-- Note: The default parameter name for favorParameter is 'format'. For instance, when this flag is true, a request for /services/employee/{id}/search?format=json will result
|
||||
in an MappingJacksonJsonView being resolved, while the Accept header can be the browser-defined text/html,application/xhtml+xml -->
|
||||
|
||||
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
|
||||
<property name="order" value="1" />
|
||||
<property name="defaultContentType" value="application/xml"/>
|
||||
<property name="favorParameter" value="true"/>
|
||||
<property name="ignoreAcceptHeader" value="true" />
|
||||
<property name="mediaTypes">
|
||||
<map>
|
||||
<entry key="json" value="application/json" />
|
||||
<entry key="xml" value="application/xml" />
|
||||
</map>
|
||||
</property>
|
||||
<property name="defaultViews">
|
||||
<list>
|
||||
<bean
|
||||
class="org.springframework.integration.samples.rest.json.view.ExtendedMappingJacksonJsonView" >
|
||||
<property name="objectMapper" ref="jaxbJacksonObjectMapper"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
|
||||
<constructor-arg ref="marshaller"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.integration.samples.rest.domain" />
|
||||
|
||||
<int:service-activator id="employeeServiceActivator"
|
||||
input-channel="employeeSearchRequest"
|
||||
output-channel="employeeSearchResponse"
|
||||
ref="employeeSearchService"
|
||||
method="getEmployee"
|
||||
requires-reply="true"
|
||||
send-timeout="60000"/>
|
||||
|
||||
<bean id="jaxbJacksonObjectMapper" class="org.springframework.integration.samples.rest.json.JaxbJacksonObjectMapper"/>
|
||||
|
||||
</beans>
|
||||
24
intermediate/rest-http/src/main/resources/log4j.properties
Normal file
24
intermediate/rest-http/src/main/resources/log4j.properties
Normal file
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
#REST HTTP User
|
||||
SPRING=gI/OZ3yejUtSxsF9XySg5TfFJFo=,ROLE_REST_HTTP_USER,enabled
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Class-Path:
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
|
||||
|
||||
<security:global-method-security
|
||||
secured-annotations="enabled" />
|
||||
|
||||
<!-- Configure Spring Security -->
|
||||
<security:http auto-config="true" use-expressions="true" realm="REST HTTP Web Service" create-session="never">
|
||||
<security:http-basic />
|
||||
<security:intercept-url pattern='/services/employee/*' access="hasRole('ROLE_REST_HTTP_USER')" />
|
||||
</security:http>
|
||||
|
||||
<!-- In this example, we are using in memory authentication. The password encoder depends on
|
||||
Jasypt's String Digester to digest the password stored in users.properties -->
|
||||
<security:authentication-manager alias="authenticationManager">
|
||||
<security:authentication-provider>
|
||||
<security:password-encoder ref="passwordEncoder"/>
|
||||
<security:user-service properties="classpath:users.properties" />
|
||||
</security:authentication-provider>
|
||||
</security:authentication-manager>
|
||||
|
||||
<!--
|
||||
Use the StringDigester to create uni-directional password encryption.
|
||||
All uni-directional encryption methods supported in jasypt is integrated into
|
||||
Spring Security
|
||||
-->
|
||||
<bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester" >
|
||||
<property name="algorithm" value="SHA-1" />
|
||||
<property name="iterations" value="100000" />
|
||||
<property name="saltGenerator">
|
||||
<bean id="zeroSaltGenerator" class="org.jasypt.salt.ZeroSaltGenerator"/>
|
||||
</property>
|
||||
<property name="saltSizeBytes" value="10"/>
|
||||
</bean>
|
||||
|
||||
<!--
|
||||
This Spring Security-friendly PasswordEncoder implementation will
|
||||
wrap the StringDigester instance so that it can be used from
|
||||
the security framework.
|
||||
-->
|
||||
<bean id="passwordEncoder" class="org.jasypt.spring.security3.PasswordEncoder">
|
||||
<property name="stringDigester" ref="jasyptStringDigester"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<import resource="security-config.xml" />
|
||||
<import resource="classpath:META-INF/spring/integration/applicationContext-http-int.xml"/>
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.samples.rest"/>
|
||||
|
||||
</beans>
|
||||
109
intermediate/rest-http/src/main/webapp/WEB-INF/web.xml
Normal file
109
intermediate/rest-http/src/main/webapp/WEB-INF/web.xml
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
|
||||
<display-name>Spring Integration Rest HTTP Path Usage Demo</display-name>
|
||||
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>
|
||||
<!-- Spring application context declaration -->
|
||||
/WEB-INF/config/web-application-config.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
Key of the system property that should specify the root directory of this
|
||||
web app. Applied by WebAppRootListener or Log4jConfigListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>webAppRootKey</param-name>
|
||||
<param-value>rest-http.root</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
Location of the Log4J config file, for initialization and refresh checks.
|
||||
Applied by Log4jConfigListener.
|
||||
-->
|
||||
<context-param>
|
||||
<param-name>log4jConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/classes/log4j.properties</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
- Configures Log4J for this web app.
|
||||
- As this context specifies a context-param "log4jConfigLocation", its file path
|
||||
- is used to load the Log4J configuration, including periodic refresh checks.
|
||||
-
|
||||
- Would fall back to default Log4J initialization (non-refreshing) if no special
|
||||
- context-params are given.
|
||||
-
|
||||
- Exports a "web app root key", i.e. a system property that specifies the root
|
||||
- directory of this web app, for usage in log file paths.
|
||||
- This web app specifies "rest-http.root" (see log4j.properties file).
|
||||
-->
|
||||
<!-- Leave the listener commented-out if using JBoss -->
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
- Loads the root application context of this web app at startup,
|
||||
- by default from "/WEB-INF/applicationContext.xml".
|
||||
- Note that you need to fall back to Spring's ContextLoaderServlet for
|
||||
- J2EE servers that do not follow the Servlet 2.4 initialization order.
|
||||
-
|
||||
- Use WebApplicationContextUtils.getWebApplicationContext(servletContext)
|
||||
- to access it anywhere in the web application, outside of the framework.
|
||||
-
|
||||
- The root context is the parent of all servlet-specific contexts.
|
||||
- This means that its beans are automatically available in these child contexts,
|
||||
- both for getBean(name) calls and (external) bean references.
|
||||
-->
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<filter>
|
||||
<filter-name>charEncodingFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>forceEncoding</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>charEncodingFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
<filter>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Spring Integration Rest HTTP Path Usage</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value></param-value>
|
||||
</init-param>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Spring Integration Rest HTTP Path Usage</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
@@ -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<EmployeeList> 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>(EmployeeList.class, restTemplate.getMessageConverters());
|
||||
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
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<String, Object> 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<String, Object> getEmployeeSearchMap(String id) {
|
||||
Map<String, Object> employeeSearchMap = new HashMap<String, Object>();
|
||||
employeeSearchMap.put("id", id);
|
||||
return employeeSearchMap;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEmployeeAsJson() throws Exception{
|
||||
Map<String, Object> 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<Object> request = new HttpEntity<Object>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-http="http://www.springframework.org/schema/integration/http"
|
||||
xmlns:oxm="http://www.springframework.org/schema/oxm"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/http http://www.springframework.org/schema/integration/http/spring-integration-http.xsd
|
||||
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
|
||||
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
|
||||
<property name="messageConverters">
|
||||
<list>
|
||||
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
|
||||
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
|
||||
<property name="marshaller" ref="marshaller"/>
|
||||
<property name="unmarshaller" ref="marshaller"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
|
||||
<property name="objectMapper" ref="jaxbJacksonObjectMapper"/>
|
||||
</bean>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.samples.rest"/>
|
||||
|
||||
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.integration.samples.rest.domain" />
|
||||
|
||||
<bean id="jaxbJacksonObjectMapper" class="org.springframework.integration.samples.rest.json.JaxbJacksonObjectMapper"/>
|
||||
|
||||
</beans>
|
||||
15
intermediate/rest-http/src/test/resources/log4j.properties
Normal file
15
intermediate/rest-http/src/test/resources/log4j.properties
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user