View Javadoc

1   /*
2    * Copyright 2007-2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springbyexample.httpclient;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.IOException;
21  import java.util.Map;
22  
23  import javax.xml.transform.stream.StreamResult;
24  import javax.xml.transform.stream.StreamSource;
25  
26  import org.apache.commons.httpclient.HttpException;
27  import org.apache.commons.httpclient.HttpMethod;
28  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
29  import org.apache.commons.httpclient.methods.PostMethod;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.springframework.beans.factory.InitializingBean;
33  import org.springframework.oxm.Marshaller;
34  import org.springframework.oxm.MarshallingFailureException;
35  import org.springframework.oxm.Unmarshaller;
36  import org.springframework.stereotype.Component;
37  import org.springframework.util.Assert;
38  
39  /**
40   * Template for easier use of <code>HttpClient</code> and 
41   * also uses Spring Web Services OXM framework to marshall/unmarshall 
42   * XML from requests and responses.
43   * 
44   * @author David Winterfeldt
45   */
46  @Component
47  public class HttpClientOxmTemplate<T> extends AbstractHttpClientTemplate<T> 
48          implements InitializingBean {
49  
50      final Logger logger = LoggerFactory.getLogger(HttpClientOxmTemplate.class);
51  
52      protected Marshaller marshaller = null;
53      protected Unmarshaller unmarshaller = null;
54      
55      /**
56       * Constructor.
57       */
58      public HttpClientOxmTemplate() {}
59  
60      /**
61       * Constructor.
62       * 
63       * @param   defaultUri      Default uri.
64       */
65      public HttpClientOxmTemplate(String defaultUri) {
66          super(defaultUri, false);
67      }
68  
69      /**
70       * Constructor.
71       * 
72       * @param   defaultUri      Default uri.
73       * @param   marshaller      Marshaller to use for marshalling requests.
74       * @param   unmarshaller    Unmarshaller to use for unmarshalling requests.
75       */
76      public HttpClientOxmTemplate(String defaultUri, 
77                                   Marshaller marshaller, Unmarshaller unmarshaller) {
78          this(defaultUri);
79          
80          this.marshaller = marshaller;
81          this.unmarshaller = unmarshaller;
82      }
83      
84      /**
85       * Constructor.
86       * 
87       * @param   defaultUri      Default uri.
88       * @param   marshaller      Marshaller to use for marshalling requests.
89       * @param   unmarshaller    Unmarshaller to use for unmarshalling requests.
90       * @param   init            Whether or not to initialize the bean.
91       */
92      public HttpClientOxmTemplate(String defaultUri, 
93                                   Marshaller marshaller, Unmarshaller unmarshaller,
94                                   boolean init) {
95          this(defaultUri, marshaller, unmarshaller);
96          
97          if (init) {
98              try {
99                  afterPropertiesSet();
100             } catch(Exception e) {
101                 throw new HttpAccessException(e.getMessage(), e);
102             }
103         }
104     }
105     
106     /**
107      * Gets marshaller.
108      */
109     public Marshaller getMarshaller() {
110         return marshaller;
111     }
112 
113     /**
114      * Sets marshaller.
115      */
116     public void setMarshaller(Marshaller marshaller) {
117         this.marshaller = marshaller;
118     }
119     
120     /**
121      * Gets unmarshaller.
122      */
123     public Unmarshaller getUnmarshaller() {
124         return unmarshaller;
125     }
126 
127     /**
128      * Sets unmarshaller.
129      */
130     public void setUnmarshaller(Unmarshaller unmarshaller) {
131         this.unmarshaller = unmarshaller;
132     }
133     
134     /**
135      * Implementation of <code>InitializingBean</code> 
136      * that initializes the <code>HttpClient</code> if it is <code>null</code> 
137      * and also sets the connection manager to <code>MultiThreadedHttpConnectionManager</code> 
138      * if it is <code>null</code> while initializing the <code>HttpClient</code>.
139      */
140     public void afterPropertiesSet() throws Exception {
141         Assert.notNull(marshaller);
142         Assert.notNull(unmarshaller);
143         
144         super.afterPropertiesSet();
145     }
146 
147     /**
148      * Execute post method.
149      * 
150      * @param   requestPayload  Request data to post after marshalling.  
151      *                          The <code>Marshaller</code> should be able to 
152      *                          process this instance. 
153      */
154     public void executePostMethod(T requestPayload) {
155         executePostMethod(defaultUri, requestPayload, null, null);
156     }
157     
158     /**
159      * Execute post method.
160      * 
161      * @param   requestPayload  Request data to post after marshalling.  
162      *                          The <code>Marshaller</code> should be able to 
163      *                          process this instance. 
164      * @param   callback        Callback with HTTP method's response.
165      */
166     public void executePostMethod(T requestPayload, ResponseCallback<?> callback) {
167         executePostMethod(defaultUri, requestPayload, null, callback);
168     }
169 
170     /**
171      * Execute post method.
172      * 
173      * @param   requestPayload  Request data to post after marshalling.  
174      *                          The <code>Marshaller</code> should be able to 
175      *                          process this instance. 
176      * @param   hParams         Parameters for the HTTP post.
177      */
178     public void executePostMethod(T requestPayload, Map<String, String> hParams) {
179         executePostMethod(requestPayload, hParams, null);
180     }
181 
182     /**
183      * Execute post method.
184      * 
185      * @param   requestPayload  Request data to post after marshalling.  
186      *                          The <code>Marshaller</code> should be able to 
187      *                          process this instance. 
188      * @param   hParams         Parameters for the HTTP post.
189      * @param   callback        Callback with HTTP method's response.
190      */
191     public void executePostMethod(T requestPayload, Map<String, String> hParams,
192                                   ResponseCallback<?> callback) {
193         executePostMethod(defaultUri, requestPayload, hParams, callback);
194     }
195     
196     /**
197      * Execute post method.
198      * 
199      * @param   uri             URI to use when processing this HTTP request instead 
200      *                          of using the default URI.
201      * @param   requestPayload  Request data to post after marshalling.  
202      *                          The <code>Marshaller</code> should be able to 
203      *                          process this instance. 
204      * @param   hParams         Parameters for the HTTP post.
205      * @param   callback        Callback with HTTP method's response.
206      */
207     public void executePostMethod(String uri,  
208                                   T requestPayload, Map<String, String> hParams,
209                                   ResponseCallback<?> callback) {
210         PostMethod post = new PostMethod(uri);
211         
212         if (requestPayload != null) {
213             ByteArrayOutputStream out = new ByteArrayOutputStream();
214             
215             try {
216                 marshaller.marshal(requestPayload, new StreamResult(out));
217             } catch (IOException e) {
218                 throw new MarshallingFailureException(e.getMessage(), e);
219             }
220             
221             post.setRequestEntity(new ByteArrayRequestEntity(out.toByteArray()));
222         }
223         
224         processHttpMethodParams(post, hParams);
225         
226         processHttpMethod(post, callback);
227     }
228     
229     /**
230      * Processes <code>HttpMethod</code> by executing the method, 
231      * validating the response, and calling the callback.
232      * 
233      * @param   httpMethod      <code>HttpMethod</code> to process.
234      * @param   callback        Callback with HTTP method's response.
235      */
236     @SuppressWarnings("unchecked")
237     protected void processHttpMethod(HttpMethod httpMethod, ResponseCallback callback) {
238         try {
239             client.executeMethod(httpMethod);
240             
241             validateResponse(httpMethod);
242             
243             if (callback != null) {
244                 Object value = unmarshaller.unmarshal(new StreamSource(httpMethod.getResponseBodyAsStream()));
245             
246                 callback.doWithResponse((T)value);
247             }
248         } catch (HttpException e) {
249             throw new HttpAccessException(e.getMessage(), e, httpMethod.getStatusCode());
250         } catch (IOException e) {
251             throw new HttpAccessException(e.getMessage(), e);
252         } finally {
253             httpMethod.releaseConnection();
254         }
255     }
256     
257 }