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.solr;
18  
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  import org.springbyexample.httpclient.HttpClientOxmTemplate;
28  import org.springbyexample.httpclient.HttpClientTemplate;
29  import org.springbyexample.httpclient.ResponseCallback;
30  import org.springframework.beans.factory.DisposableBean;
31  import org.springframework.beans.factory.InitializingBean;
32  import org.springframework.oxm.Marshaller;
33  import org.springframework.oxm.Unmarshaller;
34  import org.springframework.util.Assert;
35  
36  
37  /**
38   * Specialized client for processing requests with Solr 
39   * that are marshalled and unmarshalled.
40   * 
41   * @author David Winterfeldt
42   */
43  public class SolrOxmClient<T> implements InitializingBean, DisposableBean {
44  
45      final Logger logger = LoggerFactory.getLogger(SolrOxmClient.class);
46  
47      public final static String SEARCH_QUERY_PARAM = "q";
48      
49      protected final static String SELECT_URL_SUFFIX = "/select";
50      protected final static String UPDATE_URL_SUFFIX = "/update";
51  
52      protected final static String DELETE_ELEMENT_NAME = "delete";
53      protected final static String DELETE_ID_ELEMENT_NAME = "id";
54      protected final static String DELETE_QUERY_ELEMENT_NAME = "query";
55  
56      protected final static String COMMIT_ELEMENT_NAME = "commit";
57      protected final static String ROLLBACK_REQUEST = "<rollback/>";
58      protected final static String OPTIMIZE_ELEMENT_NAME = "optimize";
59  
60      protected HttpClientOxmTemplate<List<T>> selectTemplate = null;
61      protected HttpClientOxmTemplate<List<T>> updateTemplate = null;
62      protected HttpClientTemplate postTemplate = null;
63  
64      protected String baseUrl = null;
65      protected Marshaller marshaller = null;
66      protected Unmarshaller unmarshaller = null;
67  
68      /**
69       * Gets base url (ex: http://localhost:8983/solr).
70       */
71      public String getBaseUrl() {
72          return baseUrl;
73      }
74  
75      /**
76       * Sets base url (ex: http://localhost:8983/solr).
77       */
78      public void setBaseUrl(String baseUrl) {
79          this.baseUrl = baseUrl;
80      }
81  
82      /**
83       * Gets Solr select url.
84       */
85      protected String getSelectUrl() {
86          return baseUrl + SELECT_URL_SUFFIX;
87      }
88  
89      /**
90       * Gets Solr update url.
91       */
92      protected String getUpdateUrl() {
93          return baseUrl + UPDATE_URL_SUFFIX;
94      }
95  
96  
97      /**
98       * Gets marshaller.
99       */
100     public Marshaller getMarshaller() {
101         return marshaller;
102     }
103 
104     /**
105      * Sets marshaller.
106      */
107     public void setMarshaller(Marshaller marshaller) {
108         this.marshaller = marshaller;
109     }
110 
111     /**
112      * Gets unmarshaller.
113      */
114     public Unmarshaller getUnmarshaller() {
115         return unmarshaller;
116     }
117 
118     /**
119      * Sets unmarshaller.
120      */
121     public void setUnmarshaller(Unmarshaller unmarshaller) {
122         this.unmarshaller = unmarshaller;
123     }
124 
125     /**
126      * <p>Initializes <code>HttpClientTemplate</code>s.</p>
127      * 
128      * <p>Implementation of <code>InitializingBean</code>.</p>
129      */
130     public void afterPropertiesSet() throws Exception {
131         Assert.notNull(baseUrl);
132         Assert.notNull(marshaller);
133         Assert.notNull(unmarshaller);
134         
135         selectTemplate = new HttpClientOxmTemplate<List<T>>(getSelectUrl());
136         selectTemplate.setMarshaller(marshaller);
137         selectTemplate.setUnmarshaller(unmarshaller);
138         // call init
139         selectTemplate.afterPropertiesSet();
140 
141         updateTemplate = new HttpClientOxmTemplate<List<T>>(getUpdateUrl());
142         updateTemplate.setMarshaller(marshaller);
143         updateTemplate.setUnmarshaller(unmarshaller);
144         // call init
145         updateTemplate.afterPropertiesSet();
146 
147         postTemplate = new HttpClientTemplate(getUpdateUrl(), true);        
148     }
149 
150     /**
151      * <p>Calls destroy on <code>HttpClientTemplate</code>s.</p>
152      *  
153      * <p>Implementation of <code>DisposableBean</code>.</p>
154      */
155     public void destroy() throws Exception {
156         selectTemplate.destroy();
157         updateTemplate.destroy();
158         postTemplate.destroy();
159     }
160 
161     /**
162      * Search.
163      * 
164      * @param   query       Search query.
165      */ 
166     public List<T> search(String query) {
167         Map<String, String> hParams = new HashMap<String, String>();
168         hParams.put(SEARCH_QUERY_PARAM, query);
169 
170         return search(hParams);
171     }
172 
173     /**
174      * Search.
175      * 
176      * @param   query       Search query.
177      * @param   hParams     <code>Map</code> of query parameters.
178      */ 
179     public List<T> search(String query, Map<String, String> hParams) {
180         hParams.put(SEARCH_QUERY_PARAM, query);
181 
182         return search(hParams);
183     }
184 
185     /**
186      * Search.
187      * 
188      * @param   hParams     <code>Map</code> of query parameters.
189      */ 
190     public List<T> search(final Map<String, String> hParams) {
191         final List<T> lResults = new ArrayList<T>();
192 
193         selectTemplate.executeGetMethod(hParams, new ResponseCallback<List<T>>() {
194             public void doWithResponse(List<T> lBeans) throws IOException {
195                 lResults.addAll(lBeans);
196             }
197         });
198 
199         return lResults;
200     }
201 
202     /**
203      * Updates a list of beans and automatically commits the updates.
204      * 
205      * @param   lBeans      List of beans to create or update.
206      */
207     public void update(List<T> lBeans) {
208         update(lBeans, true);
209     }
210 
211     /**
212      * Updates a list of beans.
213      * 
214      * @param   lBeans      List of beans to create or update.
215      * @param   commit      Whether or not to commit the request.
216      */
217     public void update(List<T> lBeans, boolean commit) {
218         updateTemplate.executePostMethod(lBeans);
219 
220         if (commit) {
221             commit();
222         }
223     }
224 
225     /**
226      * Deletes a record based on an id and automatically commits the delete.
227      * 
228      * @param   id          ID to delete.
229      */
230     public void deleteById(String id) {
231         deleteById(id, true);
232     }
233 
234     /**
235      * Deletes a record based on an id.
236      * 
237      * @param   id          ID to delete.
238      * @param   commit      Whether or not to commit the request.
239      */
240     public void deleteById(String id, boolean commit) {
241         delete(getEnclosingElement(DELETE_ID_ELEMENT_NAME, id), commit);
242     }
243     
244     /**
245      * Deletes an id and automatically commits the delete.
246      * 
247      * @param   query       ID to delete.
248      */
249     public void deleteByQuery(String query) {
250         deleteByQuery(query, true);
251     }
252 
253     /**
254      * Deletes an id and automatically commits the delete.
255      * 
256      * @param   query       ID to delete.
257      * @param   commit      Whether or not to commit the request.
258      */
259     public void deleteByQuery(String query, boolean commit) {
260         delete(getEnclosingElement(DELETE_QUERY_ELEMENT_NAME, query), commit);
261     }
262 
263     /**
264      * Deletes.
265      * 
266      * @param   query       Query should either be an <i>id</i> element or 
267      *                      <i>query</i> element.
268      * @param   commit      Whether or not to commit the request.
269      */
270     protected void delete(String query, boolean commit) {
271         String request = getEnclosingElement(DELETE_ELEMENT_NAME, query);
272         
273         postTemplate.executePostMethod(request);
274         
275         if (commit) {
276             commit();
277         }
278         
279         logger.info("Processed delete.  request='{}' commit={}", request, commit);
280     }
281 
282     /**
283      * Commits pending transactions.
284      */
285     public void commit() {
286         commit(null);
287     }
288 
289     /**
290      * Commits pending transactions using specified attributes.
291      */
292     public void commit(SolrRequestAttributes attrs) {
293         String request = getElementWithAttributes(COMMIT_ELEMENT_NAME, attrs);
294         
295         postTemplate.executePostMethod(request);
296         
297         logger.debug("Processed commit.  request={}", request);
298     }
299 
300     /**
301      * Rollback pending transactions.
302      */
303     public void rollback() {
304         postTemplate.executePostMethod(ROLLBACK_REQUEST);
305         
306         logger.info("Processed rollback.");
307     }
308 
309     /**
310      * Optimize.
311      */
312     public void optimize() {
313         optimize(null);
314     }
315 
316     /**
317      * Optimize using specified attributes.
318      */
319     public void optimize(SolrRequestAttributes attrs) {
320         String request = getElementWithAttributes(OPTIMIZE_ELEMENT_NAME, attrs);
321         
322         postTemplate.executePostMethod(request);
323         
324         logger.debug("Processed optimize.  request={}", request);
325     }
326 
327     /**
328      * Gets an element enclosing a value. 
329      */
330     private String getEnclosingElement(String elementName, String value) {
331         StringBuilder result = new StringBuilder();
332         
333         result.append("<" +elementName + ">");
334         result.append(value);
335         result.append("</" +elementName + ">");
336 
337         return result.toString();
338     }
339 
340     /**
341      * Gets an element with attributes. 
342      */
343     private String getElementWithAttributes(String elementName, SolrRequestAttributes attrs) {
344         StringBuilder result = new StringBuilder();
345 
346         result.append("<");
347         result.append(elementName);
348 
349         if (attrs != null) {
350             if (attrs.getMaxSegments() != null) {
351                 result.append(" maxSegments=\"" + attrs.getMaxSegments() + "\"");
352             }
353     
354             if (attrs.getWaitFlush() != null) {
355                 result.append(" waitFlush=\"" + attrs.getWaitFlush() + "\"");
356             }
357     
358             if (attrs.getWaitSearcher() != null) {
359                 result.append(" waitSearcher=\"" + attrs.getWaitSearcher() + "\"");
360             }
361         }
362         
363         result.append("/>");
364 
365         return result.toString();
366     }
367     
368 }
369